<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Juraj Malenica</title>
    <description>The latest articles on DEV Community by Juraj Malenica (@jurajmalenica).</description>
    <link>https://dev.to/jurajmalenica</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F213000%2Fab1995eb-85b4-4d76-80ff-de029b4fd56f.jpg</url>
      <title>DEV Community: Juraj Malenica</title>
      <link>https://dev.to/jurajmalenica</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jurajmalenica"/>
    <language>en</language>
    <item>
      <title>Death to the invincible engineer</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Wed, 20 Mar 2024 13:00:00 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/death-to-the-invincible-engineer-o1l</link>
      <guid>https://dev.to/jurajmalenica/death-to-the-invincible-engineer-o1l</guid>
      <description>&lt;p&gt;“&lt;em&gt;No vulnerability, no creativity. No tolerance for failure, no innovation. It is that simple. If you’re not willing to fail, you can’t innovate. If you’re not willing to build a vulnerable culture, you can’t create.&lt;/em&gt;”&lt;br&gt;
— Brené Brown, professor and author&lt;/p&gt;

&lt;p&gt;I believe there to be two types of people in the workplace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;those who strongly believe being vulnerable at work is a sign of weakness that will be used against them,&lt;/li&gt;
&lt;li&gt;and those who have had that happen, but still do it to stay authentic, hoping it will pay off in the long run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve spent years working with both types. I’ve also worked in other people’s teams, as well as built my own. In this article, we will discuss why &lt;em&gt;an invincible engineer&lt;/em&gt; only sabotages the team, the company, and the individual, and how vulnerability can have an incredible impact, if used correctly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This post was originally published on my personal blog - it would mean a lot if you &lt;a href="https://juraj.hashnode.dev/death-to-the-invincible-engineer"&gt;subscribed there&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Me against the world&lt;/em&gt; mentality
&lt;/h2&gt;

&lt;p&gt;In the current job market where an average software engineer &lt;a href="https://www.linkedin.com/pulse/how-long-do-software-engineers-stay-job-firas-abbasi/"&gt;stays just 2 years at a single company&lt;/a&gt;, where remote work and freelancing lead to &lt;a href="https://www.businessinsider.com/overemployed-workers-secret-two-multiple-jobs-salaries-tech-tips-2023-11"&gt;engineers having 2 or 3 full-time positions at the same time&lt;/a&gt;, and companies are &lt;a href="https://layoffs.fyi/"&gt;firing thousands of software engineers&lt;/a&gt; with little to no notice, it’s easy to enter the &lt;em&gt;me against the world&lt;/em&gt; mentality.&lt;/p&gt;

&lt;p&gt;This way of thinking leads us to always compete with everyone else for superiority, material prosperity and recognition. Pushing it further, it reduces any chance for real, meaningful connections, and can instill paranoia. Shutting everyone out gives us a false sense of security, as no one can really hurt us (or at least they won’t know they did.) &lt;/p&gt;

&lt;p&gt;When I first started working, I was overwhelmed with the feeling of incompetence. Surrounded with brilliant engineers who talked in terms I didn’t understand, the adaptation was hard. Every time I had to ask for help or when something didn’t work, I felt shame. To cope with it, I followed my instincts and emotionally shut out, trying not to feel overcome by agitation and shame.&lt;/p&gt;

&lt;p&gt;Two years in, this was still my main coping mechanism. Whenever frustrations with myself or my colleagues would arise, I’d try to ignore it and just move on, because that way no one could judge me for my weaknesses and shortcomings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Looking back at my 10 years of professional development, the single greatest impact on it was accepting my emotions, my limitations in knowledge and capabilities, and being open about them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A wake-up call came from someone dear to me, who was in many ways my mentor. They helped me realize that I was bottling up emotions - a situation that’s neither sustainable, nor optimal. After that, it was up to me: would I adapt my instinct reactions and start showing real vulnerability?&lt;/p&gt;

&lt;p&gt;I believe I’ve made the right choice. To this day, it helps me stay authentic and honest, it gives power to my words and helps me connect with people more easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Showing vulnerability in a team
&lt;/h2&gt;

&lt;p&gt;Great software companies don’t measure productivity and output at an individual level, but at the team level. This not only incentivizes everyone to work together, but also disrupts the &lt;em&gt;me against the world&lt;/em&gt; mentality.&lt;/p&gt;

&lt;p&gt;A lot of the successful teams’ dynamics comes down to trust. Trust between team-members is the glue that holds everything together when things get hard. Everyone has good and bad days — sometimes that means things don’t get communicated correctly, or at all. Working closely with someone means there will be a million opportunities to be disappointed or frustrated.&lt;/p&gt;

&lt;p&gt;In these times, we need to trust that someone doesn’t mean us harm, giving them the benefit of the doubt, and being honest if things aren’t working out. If the trust is mutual and the goals are aligned, it will be a net-positive game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Great teams don’t have perfect members. Instead, they have honest, open communication that nurtures trust and a feeling of unity.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ve been a part of both toxic and nurturing teams, and the dynamics are completely different. Toxicity disrupts everything, from communication to cooperation and delivery speed. Something I’ve learned over the years is that, when faced with toxic team-members, their attitude and behavior needs to be addressed directly no matter their brilliance and output. Otherwise, their negative influence will pull everyone down, and affect the team spirit.&lt;/p&gt;

&lt;p&gt;The first step in addressing such situations is direct and honest communication, expressing our observations and feelings. I believe people are inherently good, and toxicity comes from unaddressed issues in the past coupled with some personal insecurities. Although past can’t be changed, together we can commit to do better in the future.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdubka93yskbcivvf17qs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdubka93yskbcivvf17qs.png" alt="WholeHearted School Counseling" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;a href="https://wholeheartedschoolcounseling.com/product/feelings-behind-anger-free-poster/"&gt;WholeHearted School Counseling&lt;/a&gt;&lt;/center&gt;

&lt;p&gt;Talking privately with a person about the negative feelings they might be causing is incredibly hard. The first time I organized such a conversation was with a senior peer, and it was one of the scariest things I ever did in my career. It was long, intense and honest. We were both open, constructive and non-judgmental. By the end, I had massive newly-found respect for my colleague, even though things didn’t work out in the long run.&lt;/p&gt;

&lt;p&gt;If we can find that common language with such individuals, the focus switches from “addressing toxicity” to “mending relationships”, which is a much more constructive outlook. If we then successfully continue to improve that relationship, things will start to heal and trust will slowly be re-established! If it goes the other way, at least we gave it our best.&lt;/p&gt;

&lt;h2&gt;
  
  
  Champions of vulnerability
&lt;/h2&gt;

&lt;p&gt;An environment that cherishes vulnerability also encourages authenticity, gives employees a feeling that they can speak up and make suggestions, agree and disagree, admit mistakes. It entices learning through sharing, and creating genuine connections with the team.&lt;/p&gt;

&lt;p&gt;The first step towards creating such a culture is leading by example — not to compromise on honesty, accepting the hard and uncomfortable conversations. It is also important to educate others about it, about the benefits, but also the misconceptions that showing vulnerability is a sign of weakness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vulnerability is something we cannot enforce, as it would have the opposite effect. It starts with a safe environment, people who care about one another, and who focus on learning over outcomes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Working in a startup is especially challenging — the hours are long, the pay is bad compared to many other places, the documentation is lacking, and the processes are semi-defined at best. Having interviewed hundreds of candidates, I realized that the best filtering strategy is showing real vulnerability. I am very open about all these downsides, and will emphasize them in interviews.&lt;/p&gt;

&lt;p&gt;Some candidates will be attracted by this, and will see these challenges as an opportunity to grow and make an impact. Most will say &lt;em&gt;thank you, no thank you.&lt;/em&gt; And I’m OK with that, as it saves us all some time, regardless of the fact that we might miss some incredible engineers.&lt;/p&gt;

&lt;p&gt;Not compromising on vulnerability is incredibly powerful, and has lasting effects. I realized that during my last vacation, when my team had 2 production outages. They realized there was something wrong, alerted the clients, did damage control, fixed the mistakes, and made sure something like this wouldn’t happen again — all while I was gone. From what I heard, it was extremely stressful, intense, and at times unpleasant.&lt;/p&gt;

&lt;p&gt;During all that time, there was no shaming or finger-pointing. Everyone tackled it as a team. Furthermore, the individuals in charge of the failing systems immediately spoke up when they detected something was wrong, and chose not to hide. They showed real vulnerability and courage, and everyone else rewarded them with support. This wouldn’t have happened if our sole priority was engineering excellence, and not finding a cultural fit.&lt;/p&gt;

&lt;p&gt;If we’re not in the position of high influence, we can’t really expect to change the whole company, their hiring processes or their core principles. However, we can influence the team we work in. We can share our feelings and ideas, honestly talk about potential improvements, actively listen, and be vulnerable. We can be champions of vulnerability — role-models for others to do the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;There are two types of people in the work place: those who feel alone and threatened by others, and those who treat work as net-positive game.&lt;/p&gt;

&lt;p&gt;By being vulnerable with our team members, we instill trust and a sense of connection, we empathize with colleagues who struggle, doubt themselves, or feel overwhelmed. We demonstrate a strength of character, and show self-awareness.&lt;/p&gt;

&lt;p&gt;These are the foundations that build great teams. With challenges brought by remote work and a crazy job market, it is very important to prioritize what really matters, which is people.&lt;/p&gt;

&lt;p&gt;If you’re someone in an influential position, create an environment where people will feel appreciated, included, and relied upon. And if you’re someone who’s just starting out, find a place where your potential and passion will be cherished, and your failures treated as learning opportunities.&lt;/p&gt;

&lt;p&gt;We need courage and grit to be vulnerable — that’s hard. But everyone will know us for our authentic, honest selves, which pays off in the long run. Acting invincible just doesn't pay off.&lt;/p&gt;




&lt;p&gt;P.S. To learn more about vulnerability, I suggest you read &lt;em&gt;Daring Greatly by Brené Brown&lt;/em&gt;. It helped me better understand things I see in my everyday life.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>vulnerability</category>
      <category>communication</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Bad engineers learn new skills - great engineers improve their mindset</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Thu, 26 Oct 2023 12:26:39 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/good-engineers-train-their-skills-great-engineers-train-their-mindset-21h</link>
      <guid>https://dev.to/jurajmalenica/good-engineers-train-their-skills-great-engineers-train-their-mindset-21h</guid>
      <description>&lt;p&gt;In my career, I’ve gone through many challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starting off, I struggled with writing functional and stable code,&lt;/li&gt;
&lt;li&gt;Later, I had problems following more complex conversations about architecture styles, scaling, automation, etc.,&lt;/li&gt;
&lt;li&gt;After that, I had a hard time communicating with some team members that weren’t like me, and whom I didn’t quite understand,&lt;/li&gt;
&lt;li&gt;And now, I find it hard to be a continuous source of inspiration to my team, to help them tackle new challenges in the right mindset.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Through my personal career growth and that of my peers and mentees, I learned that growing professionally is always a hard challenge to face. Time and again, we go through a similar skill acquisition cycle, and understanding this process can help make the journey more enjoyable and less chaotic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I would separate the process of learning new skills into 3 phases:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adjustment phase — when starting in a new position, we obviously lack the experience and familiarity with best practices. That’s why we begin by learning rules that guide us,&lt;/li&gt;
&lt;li&gt;Intuition-building phase — as we learn by doing, acting on rules is replaced with acting on intuition. Be careful not to confuse intuition with overconfidence, though,&lt;/li&gt;
&lt;li&gt;Stagnation phase — once we’ve mastered our new responsibilities, do we push onward or move on to something new?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qyb9t2h9qilszt5pjr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qyb9t2h9qilszt5pjr2.png" alt="3 phases of learning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In what follows, we’ll go through each phase, why it happens, and how to get the best out of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adopting the Growth Mindset
&lt;/h2&gt;

&lt;p&gt;We can describe the neurological process of learning like carving a new path in our brains. Neural pathways in the brain become more efficient with use, making them easier to access. But it takes a lot of effort to carve those new paths: in order to grow, we need to push ourselves outside our comfort zone, beyond our capabilities.&lt;/p&gt;

&lt;p&gt;When faced with such efforts, it is very helpful to adopt a growth mindset. This mindset helps us see our capabilities as expandable, and our failures as learning opportunities that empower growth. By doing so, we can look positively at all the hard work that is required in order to master something new.&lt;/p&gt;

&lt;p&gt;No matter which phase of life we’re in, growing is always painful. But if we fuel it with the right mindset and keep pushing forward, things are bound to get easier over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  #1 Adjustment phase
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuufimbrtovmltx9zdl2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuufimbrtovmltx9zdl2y.png" alt="Adjustment phase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the hardest challenges I’ve faced so far — transitioning to engineering management — shook my perception of software engineering.&lt;/p&gt;

&lt;p&gt;I always loved solving hard engineering challenges, and have tied much of my sense of professional self-worth to it. Transitioning to engineering management meant I would focus big chunks of my time on new types of problems. Although I had led teams before and mentored other engineers, making that my full-time job together with project and resource management, meant I would have less (if any) time for my original passion.&lt;/p&gt;

&lt;p&gt;My key performance indicators (KPIs) needed to change. I used to evaluate myself based on my own contributions, but now I had to do it through my team. Is the team functional? Are the engineers happy? It was difficult to make that shift, and I struggled for months. I became frustrated and started to doubt myself — I suffered from a severe case of impostor syndrome. &lt;/p&gt;

&lt;p&gt;It took multiple cycles in my career progression to finally recognize how this is just a phase, that the struggle is normal, and I was going to get through it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand that impostor syndrome is a natural occurrence when taking on new responsibilities&lt;/strong&gt;, whether we’re just starting at our first job, or shifting to a new position. All we need to do is keep pushing, let the new neural pathways start to form, and things will start going our way.&lt;/p&gt;

&lt;h2&gt;
  
  
  #2 Intuition-building phase
&lt;/h2&gt;

&lt;p&gt;At some point, we stop feeling as stuck, and things aren’t as hard. There will be challenges and some failures, but for many, this is the sweet spot — the dynamic that feels most empowering. But this is also a phase in which we might fall prey to overconfidence — where we overestimate our skills due to lack of expertise, as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fhaines-lab.com%2Fmedia%2Fdunning-kruger_misinterpretation.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fhaines-lab.com%2Fmedia%2Fdunning-kruger_misinterpretation.png"&gt;&lt;/a&gt;Source: &lt;a href="https://www.businesstimes.com.sg/opinion-features/features/not-so-blissful-ignorance-dunning-kruger-effect-work" rel="noopener noreferrer"&gt;Dunning-Kruger Effect&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To raise our level of expertise, we must build an intuition about the best ways to solve our new challenges&lt;/strong&gt;. We start off by learning rules given to us by mentors, colleagues, and other people with relevant experience. But things are rarely straight-forward, and those rules can’t cover all situations. Only by experimenting and collecting timely feedback can we train our brains to intuit solutions beyond given rules.&lt;/p&gt;

&lt;p&gt;When I started mentoring engineers and holding one-on-one meetings, I did a deep dive into the best practices: what questions to ask, how often to have them, for how long, etc. It was a great start that gave me solid foundations on which I could continue building my intuition.&lt;/p&gt;

&lt;p&gt;After many sessions, I learned to adapt to each individual’s needs. For example, some engineers would be very open about sharing what’s on their mind, while others were more reluctant to do so, and needed more encouragement from my side. But it took me a while to build up intuition on recognizing if an engineer was not sharing something they struggled with, why they might be doing so, and how to approach it best.&lt;/p&gt;

&lt;p&gt;I’ve been wrong plenty of times. But by proactively looking for ways to improve, I kept the confidence of my mentees because they could see I was taking their feedback seriously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t fall into the trap of overconfidence, keep pushing and looking for feedback.&lt;/strong&gt; At times it feels like we’re on top of the world, and at times everything is hard. Forming your intuition on what works best takes time and some hustling, so don’t skip any steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  #3 Stagnation phase
&lt;/h2&gt;

&lt;p&gt;How do we know we’re past the overconfidence phase and are actual experts? This usually happens when things aren’t as difficult anymore. They can be challenging because of the &lt;em&gt;amount&lt;/em&gt; of work, but the work itself becomes relatively straight-forward. We’ve now seen things enough times that nothing can really surprise us, and we can rely on our intuition. We’ve reached our peak!&lt;/p&gt;

&lt;p&gt;At this point, a hard decision is in front of every engineer — do we stay in this position, where things aren’t as challenging, bringing the benefit of reduced mental load and lower stress, while providing a high-quality output — or, do we take a fresh challenge by taking on new responsibilities, inside the current company or somewhere else, being bad at something once again?&lt;/p&gt;

&lt;p&gt;One of the bigger questions for me as a senior engineer was — do I go into engineering management career track, or into individual contributor track. They are fundamentally different, and it’s a really difficult choice to make. I was a solid senior engineer and I loved it. But by looking at what I truly want for myself and with the support of my team, I went down the engineering management route.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Talk with your mentors and peers about possible next steps, and stay true to what’s important to you.&lt;/strong&gt; Ideally, we can align our career progression with our professional goals, and learning about all the possibilities helps make a more informed decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good news: learning has a compound effect
&lt;/h2&gt;

&lt;p&gt;Throughout our careers we learn and grow — it is an emotional journey that brings both joy and pain. By understanding what challenges lie ahead, and that it’s all a natural part of the process, we can learn to appreciate them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firfagls063n9xn5pu5e2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firfagls063n9xn5pu5e2.png" alt="Compound learning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the awesome thing is — as we continue growing, new challenges become easier to tackle, like the snowball effect of layering skills. Learning how to communicate with engineers will make learning how to communicate with business people somewhat easier to do. Which will make learning presentation skills easier. And the chain goes on.&lt;/p&gt;

&lt;p&gt;This blog is part of my challenge — to share my thoughts and ideas, connect with the engineering community, learn from them and find new opportunities. And while at times it feels hard as hell, exposing my thoughts and giving a chance to the world to prove me wrong, I learned to appreciate how it makes me grow.&lt;/p&gt;

&lt;p&gt;So, next time you take on a new responsibility, keep the big picture in mind and try to enjoy the challenges ahead: &lt;em&gt;the impostor syndrome&lt;/em&gt; as you start out, followed by occasional lapses into &lt;em&gt;overconfidence as you learn and experiment&lt;/em&gt;, and just as you reach the peak, &lt;em&gt;stagnation and thinking about next steps.&lt;/em&gt; They are helping us grow!&lt;/p&gt;




&lt;h2&gt;
  
  
  By the way…
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Call to action
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Hi, Juraj here — I’m building a newsletter that covers deep topics in the space of engineering. If that sounds interesting, &lt;a href="https://juraj.hashnode.dev/newsletter" rel="noopener noreferrer"&gt;subscribe&lt;/a&gt; and don’t miss anything. If you have have some thoughts you’d like to share or a topic suggestion, reach out to me via &lt;a href="https://www.linkedin.com/in/juraj-malenica-29705156/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or &lt;a href="https://twitter.com/jurajmalenica" rel="noopener noreferrer"&gt;X&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;And if you’re interested in diving deeper into these concepts, here are some great starting points:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://www.mindtools.com/atdbxer/the-dreyfus-model-of-skill-acquisition" rel="noopener noreferrer"&gt;Dreyfus model&lt;/a&gt; - or how we make decisions when learning new skills&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://thedecisionlab.com/biases/dunning-kruger-effect" rel="noopener noreferrer"&gt;Dunning-Kruger effect&lt;/a&gt; - or how our confidence changes with expertise&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://www.jakeyou.com/blog/compound-learning-acquiring-skills-builds-up-as-interest" rel="noopener noreferrer"&gt;Compound learning&lt;/a&gt; - or how learning stacks&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://www.wgu.edu/blog/what-is-growth-mindset-8-steps-develop-one1904.html#:~:text=A%20growth%20mindset%20means%20that,are%20all%20susceptible%20to%20growth." rel="noopener noreferrer"&gt;Growth mindset&lt;/a&gt; - or how to establish an empowering outlook on life&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://thebrain.mcgill.ca/flash/d/d_07/d_07_cl/d_07_cl_tra/d_07_cl_tra.html" rel="noopener noreferrer"&gt;Impostor syndrome&lt;/a&gt; - or why you feel bad about yourself when you shouldn’t&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Unpopular Opinion: It’s harder than ever to be a good software engineer</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Thu, 12 Oct 2023 12:00:17 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/unpopular-opinion-its-harder-than-ever-to-be-a-good-software-engineer-32ek</link>
      <guid>https://dev.to/jurajmalenica/unpopular-opinion-its-harder-than-ever-to-be-a-good-software-engineer-32ek</guid>
      <description>&lt;p&gt;Working in a startup environment for almost a decade has given me privileged access to a fast-paced culture of innovation, exploration, and a fail-fast approach. I followed the standard progression ladder: intern, junior, mid, senior, and eventually moved to the engineering management track. Over time, many people I grew with later moved on to work at other companies, becoming highly-respected contributors there. It would be fair to say they are good engineers.&lt;/p&gt;

&lt;p&gt;Looking back at the journey of my peers, mentees, and my own, it seems harder than ever to be a &lt;em&gt;good&lt;/em&gt; engineer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Defining a &lt;em&gt;good&lt;/em&gt; engineer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What does it mean to be an engineer?&lt;/strong&gt; As software engineers, we are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsible for translating complex problems into efficient and scalable solutions&lt;/li&gt;
&lt;li&gt;Tasked with analyzing user requirements, designing software architecture, writing code, and testing and debugging software&lt;/li&gt;
&lt;li&gt;Expected to stay on top of trends, seeking new business opportunities and ways to improve existing products&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So no – engineering doesn’t equal programming. Sometimes, that is the smallest part. It definitely appears so as one acquires more experience, as shown in the figure below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfcrp0dz22qnrhkas89u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfcrp0dz22qnrhkas89u.png"&gt;&lt;/a&gt;Source: &lt;a href="https://newsletter.pragmaticengineer.com/p/engineering-leadership-skillset-overlaps" rel="noopener noreferrer"&gt;Engineering Leadership Skill Set Overlaps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does it mean to be a &lt;em&gt;good&lt;/em&gt; engineer?&lt;/strong&gt; Based on numerous interviews, and supporting my mentees’ progress, I noticed that people with different levels of expertise might give different answers.&lt;/p&gt;

&lt;p&gt;Someone just starting out might think it’s the number of languages and frameworks a developer knows. A more experienced engineer might not even care about the language they’re using, instead emphasizing code quality - adhering to all coding principles and conducting QA, while moving swiftly.&lt;/p&gt;

&lt;p&gt;Highly experienced engineers place an enormous focus on bringing value. Sometimes we’ll quickly write throw-away code that breaks all the rules to prove a hypothesis; sometimes we’ll spend days writing a couple of lines of mission-critical code. But most days, we are making architectural decisions, discussing mission-critical issues, improving processes, etc. Why? Because often, that brings the most value.&lt;/p&gt;

&lt;p&gt;Although there are always exceptions to the rule, we can say that &lt;strong&gt;a good engineer is one that efficiently focuses their effort to bring maximum value in achieving a goal.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Growing markets and competition
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The tech market is constantly evolving.&lt;/strong&gt; We have all seen massive successes over the years: from WhatsApp to Uber, Airbnb, and TikTok. While these may be exceptions, such examples often set the north star for people – something they should strive for. This way of thinking puts extra pressure on engineers. They feel stress from inside, thinking they're doing something wrong, and from outside, with people comparing their company to many competitors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpwm7yro8nqukgnfpbw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpwm7yro8nqukgnfpbw6.png"&gt;&lt;/a&gt;Source: &lt;a href="https://tomtunguz.com/tech-consolidation/" rel="noopener noreferrer"&gt;How Healthy is the Public Technology Market?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To succeed in such an environment, companies needed to “move fast and break things,” as the famous Facebook motto says. Today this is more obvious than ever – almost every company is becoming an “AI company.” Everyone is integrating ChatGPT, often for no real reason, without a strategy on how it will bring value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By moving away from the core principle&lt;/strong&gt; – how can we bring more value to our customers – and moving towards beating the competition on the hype train, &lt;strong&gt;we get engineers building functionalities that are doomed to fail.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  World is a confusing place
&lt;/h2&gt;

&lt;p&gt;What should an enthusiast such as myself do to become a better engineer? Apart from the obvious choice of perfecting coding skills by improving clean code and architecture philosophies, nowadays, there are lots of temptations lurking. Learning TypeScript and that one latest framework that changes everything, diving into the world of blockchain and crypto, experimenting with a myriad of AI products… Options are endless.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhz12rguhiupwiwmmsebt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhz12rguhiupwiwmmsebt.png" alt="All javascript libraries"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To be honest, after so many years in the industry, I still felt threatened by the new wave of change brought by ChatGPT, GitHub Copilot, and other emerging tech. My brain started imagining scenarios where I’m out of touch on so many things. Am I focusing on the right things to bring value? Am I using my maximum potential?&lt;/p&gt;

&lt;p&gt;After some time, it became clear we’re in a hype. That too will pass, leaving only AI companies that are creating long-term value. The number of AI companies in the last 5 years has doubled in the US, with many startups just adding a feature on top of then newly-released GPT-3. They would later die with the release of ChatGPT or GPT-4, which could do the same thing, but better. But that doesn’t stop the hype army of Twitter and other platforms from proclaiming the new world order.&lt;/p&gt;

&lt;p&gt;Even with so many years working in tech, I got sucked into the hype. Rookie mistake!&lt;/p&gt;

&lt;p&gt;Programming languages and constant releases of new frameworks also add to the confusion. Tailwind, TypeScript, Haskell and Rust are all great; they each have an angle which gives them an advantage. However, people often mistake learning them for something that will give them an edge. It won’t, or at least, it shouldn’t. They are just tools which are nice to know but can’t replace experience. That is why we never put language/framework requirements in our job descriptions. I would be a fool to miss a talented engineer because they don’t know TypeScript, prompt engineering, or microservices.&lt;/p&gt;

&lt;p&gt;My advice is - &lt;strong&gt;don’t get caught up in new trends and hypes to the point where you lose focus on bringing value.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast pace and high expectations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;When seeking new challenges, it can be difficult to strive for positive stress, while avoiding negative stress.&lt;/strong&gt; Positive stress is one where we perceive a stressful situation as an opportunity leading to a good outcome, while negative stress is one that can have detrimental physical and mental health effects, as seen in the image below. Continuously delivering results on a tight schedule is stressful, and building features for the wrong reasons sways towards the latter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F503c52srikb307qm3gw7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F503c52srikb307qm3gw7.png" alt="Positive stress vs. negative stress"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both as a mentor and as a hard worker, I’ve seen stress lead to burnouts. Without exception, having someone go through burnout results in less output than reducing workload, taking a break, and optimizing for the long term. That's why we always try to make raising red flags as straightforward as possible, with periodic team updates, one-on-ones, and a nurturing culture.&lt;/p&gt;

&lt;p&gt;Still, things will go wrong. When they do, we cut scope, involve people who can help, or communicate with our clients to postpone a launch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pressure is higher than ever, coming both from within and without. Stay focused and surround yourself with a supportive team optimizing long-term.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How can we do better?
&lt;/h2&gt;

&lt;p&gt;We all have our down moments – feeling like inadequate engineers, mentors, or colleagues. Things will never be perfect or easy, and they shouldn’t. Without making mistakes and hard times, we don’t learn. But there are some things I find can increase efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomj6ri7izk3d2bz723w9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomj6ri7izk3d2bz723w9.png" alt="Levels of influence"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Individually,&lt;/strong&gt; stay true to what is really important. Technologies will come and go, but the value you bring to the world is what counts. It’s hard to fake hard work and experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As a company,&lt;/strong&gt; start with &lt;em&gt;why&lt;/em&gt; when making decisions. This is the best way to deliver functionalities that will bring value. Also, make sure the employees know that &lt;strong&gt;&lt;em&gt;why&lt;/em&gt;&lt;/strong&gt;. In my experience, they will make better decisions, give valuable feedback and be happier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Culturally,&lt;/strong&gt; establish processes that will support the employees, optimizing long-term. Together with your colleagues establish a culture of trust, support and caring. That way, you will all get the best of one another.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>We launched 10k+ code changes to production. It took us 4.5h and it was (surprisingly) problem-free. This was our recipe.</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Fri, 14 Jan 2022 22:20:57 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/we-launched-10k-code-changes-to-production-it-took-us-45h-and-it-was-surprisingly-problem-free-this-was-our-recipe-4g03</link>
      <guid>https://dev.to/jurajmalenica/we-launched-10k-code-changes-to-production-it-took-us-45h-and-it-was-surprisingly-problem-free-this-was-our-recipe-4g03</guid>
      <description>&lt;p&gt;Two days ago we launched 10k+ code changes to production. Although it was intense, it was problem-free, unlike some other deployments. The deployment process lasted 4.5 hours, with us following a 10-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We organized everyone mission-critical on standby and were ready for the deployment to last much more than anticipated.&lt;/li&gt;
&lt;li&gt;We did it overnight to disturb as few users as possible. For us, this meant fewer variables to worry about.&lt;/li&gt;
&lt;li&gt;We created a Google spreadsheet with all the scenarios that had to work perfectly. For every scenario, we defined 3 phases: development, dev QA, product QA. &lt;/li&gt;
&lt;li&gt;We wrote a deployment guide, simulated deployment locally multiple times, and iterated over it.&lt;/li&gt;
&lt;li&gt;Before launch, we deployed a sandbox, restored production databases there, and verified that everything worked.&lt;/li&gt;
&lt;li&gt;We then deployed a new production environment next to the active one. We had to set up many things and wanted to verify everything was done correctly.&lt;/li&gt;
&lt;li&gt;Once verified, we created new backups on the old production and restored them on the new production.&lt;/li&gt;
&lt;li&gt;We rerouted the traffic to the new production.&lt;/li&gt;
&lt;li&gt;We kept the old production on standby if things went terribly wrong (you never know). Since everything worked, we turned it off after a day.&lt;/li&gt;
&lt;li&gt;We all went to sleep with our ringtones on maximum in case of any errors.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you find my content interesting, follow me on &lt;a href="https://twitter.com/JurajMalenica"&gt;twitter&lt;/a&gt;. We can share half-baked ideas and discuss engineering challenges.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>webdev</category>
      <category>testing</category>
      <category>programming</category>
    </item>
    <item>
      <title>My AI startup journey is full of battles. Giving users an option to answer in text I'm always trying to avoid.</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Sun, 09 Jan 2022 14:27:05 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/my-ai-startup-journey-is-full-of-battles-giving-users-an-option-to-answer-in-text-im-always-trying-to-avoid-4091</link>
      <guid>https://dev.to/jurajmalenica/my-ai-startup-journey-is-full-of-battles-giving-users-an-option-to-answer-in-text-im-always-trying-to-avoid-4091</guid>
      <description>&lt;p&gt;If you've ever created an experience where your users need to write some information in plain text, I can image how shocking some values were. This story shows how users can complicate our lives, no matter how simple the task.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ask
&lt;/h2&gt;

&lt;p&gt;We created an AI assistant that helped people with hypertension (high blood pressure) better manage their condition. It communicated with users through Telegram messaging app (it's really accessible, developer-friendly and stable, which is really important for a startup).&lt;/p&gt;

&lt;p&gt;We needed to collect daily blood pressure &amp;amp; pulse values from our users. It would allow us to suggest the next best action (everything is great / values are high, try to relax / you should contact your doctor / you need to go to the emergency room). The only really accessible way for getting those values was by asking. I know, so primitive - but effective. The ask was simple: "Please send us our values (example: 120/60/60)"&lt;/p&gt;

&lt;h2&gt;
  
  
  The harsh reality
&lt;/h2&gt;

&lt;p&gt;The users followed the guidelines for maybe one day. Maybe! In less than 24 hours my beautiful implementation &lt;code&gt;[int(value) for value in text.split('/')]&lt;/code&gt; fell apart.&lt;/p&gt;

&lt;p&gt;Users started mistyping, and sending things like: "120.60/60" or "120 60  60". No problem, right? We can just find the 3 numbers in our text using regex and everything is ok. Something like this: &lt;code&gt;r"\D*(\d{1,3})\D*(\d{1,3})\D*(\d{1,3})\D*"&lt;/code&gt;. Great thing about this approach was that it also covered messages like: "systolic: 120, diastolic: 60, pulse: 60".&lt;/p&gt;

&lt;p&gt;And then, I lost my mind. Some users started sending: "On date 29.10.21 the pulse is: 120/60/60". Well, now we have to &lt;strong&gt;guess&lt;/strong&gt; that something is a date, and the other thing is a pulse. Because as cardiologists will tell you, values 29/10/21 are technically possible. Good thing is, they are very rare. So we would just guess - if values are withing date range, it's a date.&lt;/p&gt;

&lt;p&gt;And from that moment, all was good. Still some edge-cases appeared, but it worked for like 99.5% of the cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Battles worth fighting
&lt;/h2&gt;

&lt;p&gt;Months later we implemented a ML solution using &lt;a href="https://towardsdatascience.com/bert-explained-state-of-the-art-language-model-for-nlp-f8b21a9b6270"&gt;BERT&lt;/a&gt;. More for fun than anything else, because the added benefit was negligible.&lt;/p&gt;

&lt;p&gt;Being part of the startup taught me there are a lot of battles that can be solved, just by investing time and effort. But a startup has very limited resources, and choosing to fight the wrong battles will get it killed.&lt;/p&gt;




&lt;p&gt;If you find my content interesting, follow me on &lt;a href="https://twitter.com/JurajMalenica"&gt;twitter&lt;/a&gt;. We can share half-baked ideas and discuss engineering challenges.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>startup</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why it's Tough to Be a Mentor</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Sun, 10 Jan 2021 18:59:44 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/in-the-shoes-of-a-mentor-what-5-years-have-taught-me-1b9m</link>
      <guid>https://dev.to/jurajmalenica/in-the-shoes-of-a-mentor-what-5-years-have-taught-me-1b9m</guid>
      <description>&lt;p&gt;This is the first part of the three-part series about mentorship. We are going to cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;why being a mentor is tough,&lt;/li&gt;
&lt;li&gt;why it is rewarding,&lt;/li&gt;
&lt;li&gt;concrete advice on leveling up your mentorship skills.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mentorship is about people
&lt;/h2&gt;

&lt;p&gt;I’ve never stopped having a mentor. For 7 years now, different people mentored me in different roles. It started with programming, then architectural design, then project and team management. One constant mentorship was on communication and empathy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7FW5RgeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/0f2y9kby8ci6f9z8i2kw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7FW5RgeU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/0f2y9kby8ci6f9z8i2kw.jpg" alt="Engineer growth example" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For me, mentorship is not about teaching someone algorithms, recommending the "right books", or giving them tasks to solve. It is about guiding individuals to achieve their full potential, being there for them and being honest with them.&lt;/p&gt;

&lt;p&gt;Somewhere in my second year, I was solving problems with real significance for the company. That meant tackling a lot of new problems about which I knew little. I pestered my mentor with new questions every 10-15 minutes until at some point he introduced a 10-minute time window of every hour when I could ask questions. I stopped with the questions in a matter of weeks.&lt;/p&gt;

&lt;p&gt;Looking back now when I’m facing the same mentorship challenge, this was a genius way to force me to become independent and improve my googling skills. Unfortunately, at the time I didn’t understand this intent and would feel discarded.&lt;/p&gt;

&lt;p&gt;The intent was good, but the execution was only partially successful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Being a mentor is tough stuff
&lt;/h2&gt;

&lt;p&gt;In my 7 years, I’ve been a mentor for around 5, teaching different people different things. My understanding of the mentor role has changed a lot through time, changing the way I teach, give advice, and communicate.&lt;/p&gt;

&lt;h3&gt;
  
  
  It can take a lot of time
&lt;/h3&gt;

&lt;p&gt;The story from before is a great example. Mentorship can easily chip away 10%-20% of your time, depending on the mentorship setup. This time is spent on providing guidance and support, discussing ideas, giving constructive criticisms, and challenging your mentoree just the right amount.&lt;/p&gt;

&lt;p&gt;But investing time is critical for the success of both mentor and mentoree. It is the only way to develop a real, tangible relationship.&lt;/p&gt;

&lt;p&gt;As a mentoree, I really appreciate the ability to ask my mentors for help at any time, although it might be a very busy day or a Sunday afternoon. That’s why, although I sometimes have a bunch of important and/or urgent things to do, I will always try to take the time to listen to my mentorees and be there for them.&lt;/p&gt;

&lt;h3&gt;
  
  
  It can be frustrating
&lt;/h3&gt;

&lt;p&gt;I try to instill the question “Why?” into my mentorees. They need to understand why something is important enough to do, why now, why them. This is not easy to do for anyone, especially for newer employees. They are not here to “complete tasks”, but to solve problems. I give them more responsibility, owning features, projects, being mentors themselves. They are constantly challenged to grow.&lt;/p&gt;

&lt;p&gt;Growing includes failing. As a mentor, this is sometimes hard for me to take in. It is easy to forget how hard those same problems were for me when I was starting out. Especially when those same people successfully solved similar or harder problems. This is true for programming as much as it is for communication, time estimations, cooperation, and everything else.&lt;/p&gt;

&lt;p&gt;The important thing for me to understand in those situations is how they saw the situation. Most likely they were missing some key information that would complete the picture. Once I understand the cause, we both can learn something and move forward, no big deal.&lt;/p&gt;

&lt;h3&gt;
  
  
  It can be uncomfortable
&lt;/h3&gt;

&lt;p&gt;To best help someone, I always try to be honest and give direct feedback in form of constructive criticism. It is very important not to “assume” I’m right and start with the things I’ve noticed and how I feel. I expect the same in return. Disclaimer – I’m not a person that can easily talk about feelings and directly confront people. After years of practice, it is still a conscious effort.&lt;/p&gt;

&lt;p&gt;Although this is very effective and I still haven’t had a single bad experience, it is very uncomfortable and can be nerve-wracking. But that is the reason more to do it – it helps build meaningful relationships based on honesty and transparency.&lt;/p&gt;

&lt;h3&gt;
  
  
  It can be heart-breaking
&lt;/h3&gt;

&lt;p&gt;I remember having to let go one of my mentorees. The fact that we’ve built a relationship based on honesty helped us part ways without anyone holding a grudge, but I was still sad. I’ve invested a lot of time in him, and we built a friendly rapport, but this just wasn’t a place for him.&lt;/p&gt;

&lt;p&gt;Most relationships have to come to an end at some point. But as the cliche says, it’s not about the destination, it’s about the journey. People we mentor have a mind of their own and will do things we don’t agree with. This will lead to heartbreak, and that will feel painful until we embrace that it is part of the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Mentoship is about people. The real problems you face will never be about the right algorithm or the right approach. It might seem like it is, but there is usually something deeper. It could be problems with honesty or trust, you could be frustrated or heart-broken, and too shy to talk about your current mental state. And all that will take a lot of time to improve.&lt;/p&gt;

&lt;p&gt;That doesn’t mean it’s not worth the effort!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you like my content, please consider subscribing at &lt;a href="http://devwayoflife.com/"&gt;DevWayOfLife&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>Think twice before adding another language to your micro-services architecture</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Thu, 11 Jun 2020 14:23:50 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/when-is-it-ok-to-add-another-language-into-your-micro-services-1</link>
      <guid>https://dev.to/jurajmalenica/when-is-it-ok-to-add-another-language-into-your-micro-services-1</guid>
      <description>&lt;p&gt;When in startup mode, a very important thing is to be flexible. Your product isn’t defined well-enough yet and it can change frequently and drastically. We knew that and decided to use &lt;em&gt;Python&lt;/em&gt; – it’s simple and allows very fast development.&lt;/p&gt;

&lt;p&gt;Business grew and we started having clients. With every new client, our understanding of the product would expand. Some features turned out to be more relevant than others, as they produced more value for clients. We started to understand what was our core product and began cutting irrelevant functionalities out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changing focus
&lt;/h2&gt;

&lt;p&gt;Next step was doing what we do – just better. How can we reduce our costs but deliver the same amount of value (or more). There are 3 components from the development aspect I think are relevant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;cost of development&lt;/em&gt; which is most influenced by how hard it is to create a product using the platform&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;cost of deployment&lt;/em&gt; defined by the cost to run the whole product. This relates to the code performance and technologies used,&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;cost of maintenance&lt;/em&gt; depends on how much expertise does someone need to have in order to maintain a product on the platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Python is great, but it has its limits. It is designed to be easy-to-use, while languages like &lt;em&gt;C&lt;/em&gt;, &lt;em&gt;Java&lt;/em&gt;, and &lt;em&gt;Go&lt;/em&gt; are designed to be performant.&lt;/p&gt;

&lt;p&gt;Between those languages, Go is the new and cool kid and is loved by some of my colleagues, so we decided to check it out. The hypothesis was that it should easily beat Python performance-wise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Research: comparing Python &amp;amp; Go performance
&lt;/h2&gt;

&lt;p&gt;We’ve taken one service called &lt;em&gt;Gatekeeper&lt;/em&gt; inside our platform which was our biggest bottleneck. It communicates with &lt;em&gt;MongoDB&lt;/em&gt; and &lt;em&gt;Kafka&lt;/em&gt; a lot, and those IO operations turned out to take the longest. That is the part we wanted to improve most.&lt;/p&gt;

&lt;p&gt;Due to the nature of our product, the test was focused more on increasing throughput, with latency reduction being less important. We’ve identified 5 scenarios on &lt;em&gt;Gatekeeper&lt;/em&gt; that should be tested. In Python, we implemented a Sync and Async version. The Async one used &lt;em&gt;asyncio&lt;/em&gt; – Python’s newest library that allows implementing coroutines. Also, Go was limited to a single core to reproduce our production setup.&lt;/p&gt;

&lt;p&gt;The results:&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Go&lt;/em&gt; turned out to be a clear winner in all 5 scenarios. When considering the frequency of each scenario happening in real life, &lt;em&gt;the expected throughput increase is around 450%&lt;/em&gt;. That is great news for our &lt;em&gt;cost of deployment&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it worth switching?
&lt;/h2&gt;

&lt;p&gt;For me, the formula to calculate if it’s worth switching is this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;y = A × xdev + B × ydepl + C × zmain&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;xdev&lt;/em&gt;, &lt;em&gt;ydepl&lt;/em&gt; &amp;amp; &lt;em&gt;zmain&lt;/em&gt; are values representing the impact of a solution to each cost component. &lt;em&gt;A&lt;/em&gt;, &lt;em&gt;B&lt;/em&gt; &amp;amp; &lt;em&gt;C&lt;/em&gt; are weights – how important is it to reduce each cost. &lt;em&gt;y&lt;/em&gt; is the end result, how much does a solution cost considering our priorities. We’re trying to keep that as low as possible.&lt;/p&gt;

&lt;p&gt;For example, at the beginning, we didn’t care that much about the &lt;em&gt;cost of deployment and maintenance&lt;/em&gt;, so our formula could look like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;y = 0.75 × xdev + 0.1 × ydepl + 0.15 × zmain&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We could really focus on &lt;em&gt;reducing the &lt;em&gt;cost of development&lt;/em&gt;&lt;/em&gt;, not really caring about the other two.&lt;/p&gt;

&lt;p&gt;Right now, I’d say things have balanced out a lot. The formula looks much more like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;y = 0.50 × xdev + 0.25 × ydepl + 0.25 × zmain&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our main driver is still the &lt;em&gt;cost of development&lt;/em&gt;, but the other two have increased significantly relative to it. That gives us a lot of incentive to consider changing things up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are our options?
&lt;/h2&gt;

&lt;p&gt;We could rewrite everything to Go. Unfortunately, it’s a bit unrealistic. It would take too long to learn Go properly and do the rewrite. It would also negatively affect our productivity. Our &lt;em&gt;cost of development&lt;/em&gt; and &lt;em&gt;cost of maintenance&lt;/em&gt; would skyrocket.&lt;/p&gt;

&lt;p&gt;We could stay all the way in Python. We would keep &lt;em&gt;cost of development and maintenance&lt;/em&gt; low, but it keeps &lt;em&gt;cost of deployment&lt;/em&gt; too high.&lt;/p&gt;

&lt;p&gt;The final option we could try is introducing Go where it matters most, while keeping the minimum impact on developers using the platform. Our micro-services architecture allows us to do just a partial rewrite in another language. We could try rewriting only the components that handle internal stuff not visible by developers. That should keep &lt;em&gt;cost of development&lt;/em&gt; somewhat low, but &lt;em&gt;cost of maintenance&lt;/em&gt; for the platform just increased, since now we have to maintain 2 languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s never black or white
&lt;/h2&gt;

&lt;p&gt;We will try to do a partial rewrite. If things go great, we could gradually switch to Go. There could be more suitable languages or implementations that would help even more, but we have to move forward. We can only guess how things will turn out. The best we can do is making reality checks often to learn if we made the right choice early (and pivot if we didn’t).&lt;/p&gt;

&lt;p&gt;This post was originally posted on &lt;a href="https://devwayoflife.com/2020/06/11/when-is-it-ok-to-add-another-language-into-your-micro-services/"&gt;my blog&lt;/a&gt;. Consider subscribing 😊&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>microservices</category>
    </item>
    <item>
      <title>I made over 1,000 code reviews - this is what I learned</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Thu, 04 Jun 2020 10:14:03 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/i-made-over-1-000-code-reviews-this-is-what-i-learned-4e9e</link>
      <guid>https://dev.to/jurajmalenica/i-made-over-1-000-code-reviews-this-is-what-i-learned-4e9e</guid>
      <description>&lt;p&gt;Over the last 3 years, I’ve reviewed more than 1,000 pull (merge) requests. During that time I learned a lot – mostly about how not to review code, how to make the process less painful, what makes good-quality code and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull request needs to do just one thing
&lt;/h2&gt;

&lt;p&gt;This is the single most important thing to watch out for!&lt;/p&gt;

&lt;p&gt;While doing a code review, you need to keep a lot of things in your head. &lt;em&gt;“What is the intention behind this?”&lt;/em&gt;, &lt;em&gt;“How does this comply with the rest of the code?”&lt;/em&gt; and &lt;em&gt;“Will this perform well?”&lt;/em&gt; are just some of the questions that need to be answered. So, when you have a focused pull request that is trying to solve a single problem, some of those questions become easier to answer.&lt;/p&gt;

&lt;p&gt;Another important aspect is the size of the pull request. Bigger requests require exponentially more time to review. And when I know that I’ll need to spend more than 15 minutes on the request, you’ll have to wait up to a couple of hours.&lt;/p&gt;

&lt;p&gt;Larger pull requests also have more mistakes, so the time to get approved will also increase significantly. That means that you could have code waiting to get approved for days. And if your company is agile, that increases the chances for merge conflicts which are just painful.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best thing to do is split pull requests into meaningful pieces – one pull request should solve just one thing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, watch out for the common traps like &lt;em&gt;renamings&lt;/em&gt;, &lt;em&gt;code generalizations&lt;/em&gt;, and such. Although innocent and done with good intent, it removes focus from important parts – raising code quality and reducing error count. Just do your genius idea in another pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automate as many checks as possible
&lt;/h2&gt;

&lt;p&gt;Continuing on the notion that a reviewer has to keep a lot of things in his head, that also includes checking code formatting, the existence of appropriate documentation, passable tests, and so on. I remember the time when I had to take all that into consideration – it was distracting and time-consuming.&lt;/p&gt;

&lt;p&gt;Good thing is that the solution is pretty simple – integrate all the checks into the CI pipeline. That basically runs all the checks whenever someone submits a pull request, and won’t allow merging before all the checks pass. You as the reviewer will never have to worry about formatting again.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Automated tests&lt;/em&gt; help make sure that the author didn’t break anything, and that the tests are still passing. Depending on your approach to tests, this is easily the most important check to have in your pull request CI.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Automated code&lt;/em&gt; formatting makes all the arguments around ideal line-length or where to add newline disappear. Just pick a set of formatting rules as a team and give it to the auto-formatter. This will rid you of a lot of nuisance. If you’re having problems agreeing to a format, take a look at how Google, Facebook, or some other big companies are doing it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Automated lint&lt;/em&gt; checker is also very important for languages like Python where code formatting affects code logic. Most code formatters for Python will only format code for which they know for sure won’t affect any logic. By adding the lint checker you’ll cover everything.&lt;/p&gt;

&lt;p&gt;Some honorable mentions are &lt;em&gt;type checker&lt;/em&gt; and &lt;em&gt;documentation checker&lt;/em&gt;, but the most important thing is to automate checks that make sense for you and your team. If you think something would help, talk it out and try it for a week or two.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sit with the author to review the code
&lt;/h2&gt;

&lt;p&gt;It makes the review process faster since you’re able to iterate faster over the code with the author and share your point of view. The author can also better explain the reasoning behind his approach, like if he tried something already and why it didn’t work.&lt;/p&gt;

&lt;p&gt;This can also be a great opportunity to connect with people more, which is very important. When your fellow developers see that you’re invested in their personal and business growth, they will appreciate it. This is also a great opportunity for you and the author to practice your communication which is crucial for well-functioning teams.&lt;/p&gt;

&lt;p&gt;Watch out not to over-do this though. Some pull requests are too small and too simple to have any impactful conversation. In that case sitting down with the author might be a waste of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be considerate when writing reviews
&lt;/h2&gt;

&lt;p&gt;If you’re more experienced than the author of the code, you need to take into account that how you say things matters – a lot. A criticism written nicely can empower a developer to become better in the future, but it can also crush someone’s dreams.&lt;/p&gt;

&lt;p&gt;What I found that works best is to ask open-ended questions – it’s not aggressive and even encourages the developer to think critically. Will this take more time than just telling someone what the solution is? Yes, short-term. But long-term you’re helping them grow and they’re less likely to repeat their mistakes.&lt;/p&gt;

&lt;p&gt;So, next time someone opens the file inside the for-loop and not before it, instead of plainly pointing that out, ask &lt;em&gt;“How would you reduce complexity here?“&lt;/em&gt;. It will mean a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a flag called I ran this code locally
&lt;/h2&gt;

&lt;p&gt;The thing that bugs me the most is finding an error in some small pull request because of which a functionality doesn’t work at all. That means that the developer didn’t even run the code – probably thinking it’s not necessary since the change is so small.&lt;/p&gt;

&lt;p&gt;After that happened a couple of times, I added a flag called &lt;em&gt;I ran this code locally&lt;/em&gt; which solved the problem completely. I stopped reviewing code that wasn’t run locally and people didn’t lie about doing it. There were no hard feelings because we all actually knew that it should be done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bonus:&lt;/em&gt; this is our template that every developer has to fill out when creating pull requests:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Merge request description
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;What is new?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implemented...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What has changed?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changed...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Checklist
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I ran this code locally&lt;/li&gt;
&lt;li&gt;[ ] I wrote the necessary tests&lt;/li&gt;
&lt;li&gt;[ ] I covered my code with type-hints&lt;/li&gt;
&lt;li&gt;[ ] I updated CHANGELOG&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Trello card
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://trello.com/c/"&gt;https://trello.com/c/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Should know about
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is there anything else that should be known?&lt;/li&gt;
&lt;li&gt;Any deployment notes?&lt;/li&gt;
&lt;li&gt;Any additional documentation?&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  In other news
&lt;/h3&gt;

&lt;p&gt;I've been inspired by dev.to to write more, so I've started a &lt;a href="https://devwayoflife.com/"&gt;blog&lt;/a&gt;. If you're interested in this kind of content, feel free to check it out and subscribe&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>git</category>
      <category>development</category>
    </item>
    <item>
      <title>Writing elegant solutions doesn't really help - here is what does</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Sun, 10 May 2020 21:12:01 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/lesson-learned-elegant-solutions-optimal-solutions-5c1n</link>
      <guid>https://dev.to/jurajmalenica/lesson-learned-elegant-solutions-optimal-solutions-5c1n</guid>
      <description>&lt;p&gt;For almost two years now, I've been part of a core team developing a platform for building AI assistants. The assistants built were always focused more on quality instead of quantity. That meant that our requests-per-second would be relatively low, while the assistant's functionalities would be complex and numerous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then came Covid-19.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Developing a diagnosis-oriented assistant in 2 weeks
&lt;/h1&gt;

&lt;p&gt;The culture of our company is oriented towards bringing value, and we decided to do what we do best - create an assistant for Covid-19 and donate it to the government.&lt;/p&gt;

&lt;p&gt;After around a week of intense work, we were finished with the first version of the assistant. But that assistant (as all we had developed) was intended to bring a lot of value to a small number of concurrent users. But this assistant needed to be like no other.&lt;/p&gt;

&lt;p&gt;Our goal: &lt;strong&gt;throughput of 250 req/sec, with a latency of under 3 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lesson 1: some languages are just inherently better at certain things
&lt;/h1&gt;

&lt;p&gt;Our platform is built from micro-services, and they are written in Python. We were always sticking to Python because, as this &lt;a href="https://www.youtube.com/watch?v=j6ow-UemzBc"&gt;great talk&lt;/a&gt; suggests, it's mostly a bad idea to go around writing services in different languages. The guideline from the talk - "one programming language for every 4,000 engineers." We have less than 100 engineers!&lt;/p&gt;

&lt;p&gt;Our challenge was that we needed to support accepting &lt;code&gt;250 HTTP req/s&lt;/code&gt; almost instantly, and we need to support creating &lt;code&gt;250 HTTP req/s&lt;/code&gt; almost instantly.&lt;/p&gt;

&lt;p&gt;We tried developing it with Python but ran into too many problems. It would (kinda) work, but for some reason the async nature of the code made the logs not work properly. Sometimes the code also had problems accessing the cache. Things got weird and hard to debug.&lt;/p&gt;

&lt;p&gt;Since we didn't have enough time, we decided to write those components in Go. That turned out to be a brilliant idea. The performance was on the spot, it didn't require too many resources, and it scaled without any problems.&lt;/p&gt;

&lt;p&gt;Looking back, I'm pretty happy that we made that call, although it does put additional strain on the developers in terms of the required knowledge.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lesson 2: it's about satisfying requirements, not "beautiful" solutions
&lt;/h1&gt;

&lt;p&gt;We made some great architectural designs in regards to consistency and simplicity. But, as it turns out, some of them were not so great in terms of performance. So, let's focus on just one of those designs.&lt;/p&gt;

&lt;p&gt;We had this notion that the "assistant's brain" should have all the information about a user when making decisions about what to do next for him. The idea was that it would make the assistant very flexible and would support creating any crazy idea that the product could (but didn't) have.&lt;/p&gt;

&lt;p&gt;Unfortunately, when you have a lot of data about a user, that puts a lot of strain on the database (MongoDB) and the messaging system (Kafka). And then, we had to do it 250 times per second. Some data just had to go!&lt;/p&gt;

&lt;p&gt;Days of previous planning that allowed us such flexibility was overridden in a couple of hours of reckless, rushed coding. My heart was broken, but it had to be done.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lesson 3: hard times bring creative solutions
&lt;/h1&gt;

&lt;p&gt;Working on a project like this that is meant for the greater good unified us. It made us work as a hyper-productive team for weeks, with 12h+ workdays and no notion of weekends. We knew what our goal was, and we were charging forward.&lt;/p&gt;

&lt;p&gt;A lot of changes were made driven by the needs of the project with disregard to any "self-imposed rules" from before. This injected a lot of creative new approaches that we hadn't thought of before. Some of them are one-time "cheats", but others serve as a great starting point for further improvements.&lt;/p&gt;

&lt;p&gt;This experience has greatly improved my understanding of the world and our place in it. The solutions we once coined are elegant, but are not adequate anymore for the needs of our users.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>python</category>
      <category>architecture</category>
      <category>startup</category>
    </item>
    <item>
      <title>Should you explicitly define APIs when using Microservices?</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Sat, 16 Nov 2019 16:09:10 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/should-you-define-apis-when-using-microservices-19l6</link>
      <guid>https://dev.to/jurajmalenica/should-you-define-apis-when-using-microservices-19l6</guid>
      <description>&lt;p&gt;If you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a project that is running tens, or even hundreds of microservices,&lt;/li&gt;
&lt;li&gt;with multiple teams handling different parts,&lt;/li&gt;
&lt;li&gt;all being connected with Kafka,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;how do you ensure other developers can easily talk to any microservice?&lt;/p&gt;

&lt;h1&gt;
  
  
  Pros and Cons of an API
&lt;/h1&gt;

&lt;p&gt;I'm not completely sure if explicitly defining an API is the best solution for this situation. In the company where I work, we have them defined and there are mixed feelings.&lt;/p&gt;

&lt;p&gt;👍 On the one hand, explicitly saying what a microservice expects as an input seems logical - other developers should then only care about reading that, and not worrying about the underlying implementation.&lt;br&gt;
And if someone makes a change in their API, it will be clearly visible via the changelog on that API.&lt;br&gt;
Also, when creating a new feature, developers can start by defining the APIs which helps a lot in the thought process.&lt;/p&gt;

&lt;p&gt;👎 On the other hand, making an API easily readable is hard, and almost impossible for scenarios with complex data structures.&lt;br&gt;
It also takes a lot of time to write it and maintain it.&lt;br&gt;
If the developer who wrote it is near, oftentimes it's much easier to just ask them for help.&lt;/p&gt;
&lt;h1&gt;
  
  
  Approaches to defining an API
&lt;/h1&gt;

&lt;p&gt;There are two approaches to defining an API I'm going to cover.&lt;/p&gt;

&lt;p&gt;To keep things simple, we'll write an API for a microservice that can add or subtract N numbers.&lt;/p&gt;

&lt;p&gt;For our example: all we need are two fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;action&lt;/code&gt; which can be &lt;code&gt;ADD/SUBTRACT&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;arguments&lt;/code&gt; which is a list of numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The message payload into the microservice will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ADD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Approach 1: JsonSchema
&lt;/h2&gt;

&lt;p&gt;This is the approach I have the most experience with. &lt;a href="https://json-schema.org/"&gt;JsonSchema&lt;/a&gt; is a vocabulary that allows you to annotate and validate JSON documents (our messages from Kafka).&lt;/p&gt;

&lt;p&gt;Everything in the schema is pretty self-explanatory, so I won't go into any details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://json-schema.org/draft-07/schema#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"arguments"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ADD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SUBTRACT"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"additionalProperties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can only tell you that things get pretty crazy when there are more complex data structures (&amp;gt; 700 lines).&lt;/p&gt;

&lt;p&gt;To cope with the low readability and to test our schema, we oftentimes write examples for different cases. This way, other developers can look at them instead and reference the real schema for fine details.&lt;/p&gt;

&lt;p&gt;P.S. An awesome tool for debugging schemas is this &lt;a href="https://www.jsonschemavalidator.net/"&gt;JSON Schema Validator&lt;/a&gt;. I've been using it for months now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 2: Python &lt;code&gt;dataclasses&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;For this example, we'll stick with Python, but I guess the approach is applicable to most object-oriented languages.&lt;/p&gt;

&lt;p&gt;Basically, Python introduced &lt;code&gt;dataclasses&lt;/code&gt; in version 3.7, and they make defining data structures easier and cleaner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActionOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ADD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'ADD'&lt;/span&gt;
    &lt;span class="n"&gt;SUBTRACT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'SUBTRACT'&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ActionOptions&lt;/span&gt;
    &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, by using a package &lt;a href="https://github.com/konradhalas/dacite/"&gt;dacite&lt;/a&gt; we can import our message into this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;dacite&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;from_dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;  


&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ADD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;8.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;from_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type_hooks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ActionOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ActionOptions&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dacite&lt;/code&gt; allows us to import more complex data structures and raises an exception when the data doesn't match our structure.&lt;/p&gt;

&lt;p&gt;I like the idea that the dataclasses can have different methods on them that may fit its context. It is easy to write any custom validation that can't be easily expressed otherwise. &lt;br&gt;
It is also possibly easier to read for a developer, but I don't know for sure yet.&lt;/p&gt;

&lt;p&gt;The downside is that the classes have to be defined bottom-up so python can reference everything correctly (although that can probably be bypassed). Also, &lt;code&gt;dacite&lt;/code&gt; is still in active development and needs some improvements.&lt;/p&gt;

&lt;h1&gt;
  
  
  What to choose?
&lt;/h1&gt;

&lt;p&gt;I'm really looking forward to trying the second approach and battle-testing it. As time passes by, I'm seeing JsonSchema as more of a pain point than a relief. Although, to be honest, maybe I just don't appreciate it enough 🙂&lt;/p&gt;

&lt;p&gt;What I want to hear is what do you think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do you write APIs for your microservices?&lt;/li&gt;
&lt;li&gt;Which approaches work and which don't?&lt;/li&gt;
&lt;li&gt;Do you know other reasons why the two approaches I listed could be awesome/awful?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>microservices</category>
      <category>architecture</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How does your company choose between two possible solutions?</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Wed, 13 Nov 2019 21:15:32 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/how-does-your-company-choose-between-two-possible-solutions-58f2</link>
      <guid>https://dev.to/jurajmalenica/how-does-your-company-choose-between-two-possible-solutions-58f2</guid>
      <description>&lt;p&gt;Hi everyone 👋&lt;/p&gt;

&lt;p&gt;I want to find out more about what strategies do other companies have when dealing with problems that have multiple, seemingly equally good solutions? Maybe when discussing the topic of integrating new technology, or when solving a difficult edge-case?&lt;/p&gt;

&lt;p&gt;Is there a process behind it? Are you thinking more short-term or long-term? What happens if you made the wrong choice?&lt;/p&gt;

&lt;p&gt;I'd love to hear about any and all of your experiences. Thanks!&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>architecture</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Developer's Inner Conflicts, or How Over-engineering Increased Our Platform Expenses 10x Times</title>
      <dc:creator>Juraj Malenica</dc:creator>
      <pubDate>Mon, 04 Nov 2019 13:24:44 +0000</pubDate>
      <link>https://dev.to/jurajmalenica/developer-s-inner-conflicts-or-how-over-engineering-increased-our-platform-expenses-10x-times-56oa</link>
      <guid>https://dev.to/jurajmalenica/developer-s-inner-conflicts-or-how-over-engineering-increased-our-platform-expenses-10x-times-56oa</guid>
      <description>&lt;p&gt;I've noticed that we developers have some psychological bugs - I see it in my colleagues, young and old, and in myself. Things that we know aren't rational, aren't "optimized for our success", and can get us in trouble. But we still do them for some reason.&lt;/p&gt;

&lt;p&gt;I wanted to share my view of three such bugs through a story that happened not so long ago.&lt;/p&gt;

&lt;h1&gt;
  
  
  A little backstory
&lt;/h1&gt;

&lt;p&gt;Projects at the company I work for revolve around building complex AI assistants. To make the creation and development of the assistants as easy as possible, we built a platform that enables you to mostly focus on the assistant's logic and behavior (think any web framework for web development). The platform consists of a dozen microservices, MongoDB, Kafka, Memcached, etc. Basically our components with stable and scalable third-party solutions. &lt;/p&gt;

&lt;p&gt;We also decided to run our projects on AWS (even the ones in beta), to remove the need for handling servers. This meant we could use the excess time for something more productive.&lt;/p&gt;

&lt;h1&gt;
  
  
  Developing the platform
&lt;/h1&gt;

&lt;p&gt;Looking back, it's very easy to now recognize the first psychological bug, once I've gained some experience by using the platform. But back then, things weren't so simple and straight-forward, hard decisions had to be made, and there was no time to spare.&lt;/p&gt;

&lt;p&gt;Back then, while we were developing some database-related parts of the platform, came the question "What if an action on the database fails?" We didn't know what could happen, how or why, but we've become emotionally attached to the platform and there was this opportunity for things to go wrong that we just couldn't let by.&lt;/p&gt;

&lt;p&gt;So, as would any developer that really cares about his project, we covered a lot of ground in the next few days:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data redundancy (multiple mongo instances)&lt;/li&gt;
&lt;li&gt;atomic transactions&lt;/li&gt;
&lt;li&gt;auto-reconnection to the Mongo client&lt;/li&gt;
&lt;li&gt;strict database access capabilities&lt;/li&gt;
&lt;li&gt;"helper functions" for uncommon tasks (e.g. updating an object in an array that is an object in some collection)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We needed to run three Mongo server instances to support all of this, which increased the complexity of the platform, which again, used more time... Months later, we decided to turn off most of the security measurements as they were only slowing us down and causing us problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug #1: over-engineering because of engineering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Over-engineering often comes when we're faced with complicated tasks, which almost all developers love solving. This is very satisfying for our ego and is almost always fun. Most often, though, it's not worth the time and effort for the company.&lt;/p&gt;

&lt;p&gt;We can almost always argue that doing something will make this piece of code more stable, or increase the execution speed 10%. But when you're still trying to figure out how a car works, it doesn't really matter what color it is (at least not yet). To fight the over-engineering urge, check out the &lt;a href="https://deviq.com/yagni/" rel="noopener noreferrer"&gt;YAGNI&lt;/a&gt; pattern.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6yt1a3g84rqpnpda4za1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6yt1a3g84rqpnpda4za1.png" alt="YAGNI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Dev-Ops on demand
&lt;/h1&gt;

&lt;p&gt;While finishing up a project which used our now almost finished platform, we decided to set it up on AWS, with which we didn't have too much prior experience working with, as we used to set up everything on our servers. One of our first impressions was that it's very nice how AWS makes horizontal scaling fairly easy.&lt;/p&gt;

&lt;p&gt;And having more instances of Memcached, Kafka, and Mongo is always better than running just one instance. If one instance fails others will take over, the component can handle more load and so on. Also, the changes we made on the database management as part of the 1st bug meant that we now had to have multiple instances of Mongo.&lt;/p&gt;

&lt;p&gt;What basically happened was this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F57v2ml8o0np3bx1fdmxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F57v2ml8o0np3bx1fdmxv.png" alt="Say "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I just didn't want to counter our dev-ops although there was no clear reason for scaling up. At least the dev-ops guy had some fun.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug #2: never saying "no"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fear of conflict is natural but sometimes necessary. Although, ideally, we always try to come to a solution together, so there is always a clear understanding of the logic behind our decisions.&lt;/p&gt;

&lt;p&gt;We always make an effort to be open to new ideas, but the world is not black and white and that means hard decisions will have to be made. And oftentimes, the best thing we can do is consider "what minimal effort will produce maximum output?"&lt;/p&gt;

&lt;h1&gt;
  
  
  Scaling down
&lt;/h1&gt;

&lt;p&gt;All this brought us in a situation where each project on the platform was spending lots of money because it used lots of resources. And with one project done, two in the pipeline, and four that we needed to start working on, that would amount to way too much.&lt;/p&gt;

&lt;p&gt;We needed a better solution. But for what? And why? We've all been focused on pushing forward that no one communicated with other teams, talking about what's important and what's not. We needed to change that.&lt;/p&gt;

&lt;p&gt;Once this became obvious, we did something that was needed much earlier - a meeting with all stakeholders of the platform and the projects, including the product team, dev-ops, and our CEO. Once we went through the big picture, hashed out our plans for the future of those projects and defined our requirements, we could finally move forward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug #3: working in silos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Involving other people in the decision-making process is painful. It takes time to get to the same page, there can be disagreements, sometimes a decision even won't be made. So it's easier to just go with our gut feeling or educated guess.&lt;/p&gt;

&lt;p&gt;Here we should always try to get back to the question "why" - why are we doing this? Why does this make sense? Why will this help us long-term? Doing that is hard, but other stakeholders can help.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final result
&lt;/h1&gt;

&lt;p&gt;To fix the spending issue, we had two main approaches: down-scaling the instances and resource sharing. We were far from having any performance problems so down-scaling was a sensible thing to do, and we decided to share resources (Kafka, Mongo, Memcached) until a project becomes profitable enough to stand on his own.&lt;/p&gt;

&lt;p&gt;The final result was that we could deploy 10 projects for the same amount of money that we would need to deploy just one project before.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;These three psychological bugs (over-engineering, avoiding NO, working in silos) are ones of many. We as developers are optimization maniacs, and I hope learning about these common mistakes will help you optimize better.&lt;/p&gt;

&lt;p&gt;So remember:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do minimal effort for maximum results,&lt;/li&gt;
&lt;li&gt;It's ok to say no, and&lt;/li&gt;
&lt;li&gt;Two heads are better than one, talk to other people.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Good luck 🖖&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>startup</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
