<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Resilient Systems]]></title><description><![CDATA[Creating software with the future in mind]]></description><link>https://evgenii.info/</link><image><url>https://evgenii.info/favicon.png</url><title>Resilient Systems</title><link>https://evgenii.info/</link></image><generator>Ghost 5.26</generator><lastBuildDate>Thu, 09 Apr 2026 19:35:01 GMT</lastBuildDate><atom:link href="https://evgenii.info/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[How Weak Opinions Damage Code Review]]></title><description><![CDATA[Weak opinions are comments that don't require action. They may seem gentle, but can lead to hard issues down the line. Let’s aim higher and promote strong opinions, constructive feedback, and a commitment to excellence.]]></description><link>https://evgenii.info/weak-opinions/</link><guid isPermaLink="false">660747b854395704e01df221</guid><category><![CDATA[Resilient Teams]]></category><category><![CDATA[Resilient Software]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Tue, 02 Apr 2024 20:37:32 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1595109838382-3eabbfb330fb?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDIwfHx1bmNlcnRhaW58ZW58MHx8fHwxNzExNzUzMjAzfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1595109838382-3eabbfb330fb?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDIwfHx1bmNlcnRhaW58ZW58MHx8fHwxNzExNzUzMjAzfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="How Weak Opinions Damage Code Review"><p>Let&#x2019;s talk about <strong>strong and weak opinions</strong> before jumping to how exactly they damage your code review. I just need some contrast here.</p><p>Consider this scenario:</p><blockquote>Sofia is reviewing a new feature that Arthur has implemented. She notices similarities between some new functions and existing code in another module.<br><br>&#x201C;We should get rid of this duplication,&#x201D; she decides and requests changes with a comment.</blockquote><p>Sofia&#x2019;s stance is clear &#x2014; she&#x2019;s calling for action. Arthur might have his reasons for the duplication, or maybe Sofia has overlooked something and the code from another module isn&#x2019;t that similar. Either way, this opens up a conversation to agree on the best course of action because in most teams, it would be considered inappropriate for Arthur to dismiss this comment and proceed with the merge.</p><p>Requesting a change or asking a question is a direct way to express a strong opinion. Anything that would require an action would do.</p><p>Now, consider a different situation:</p><blockquote>Jack is looking over Arthur&#x2019;s code and spots several functions doing the same thing. He sees potential for improvement but also knows Arthur has put a lot of effort into this feature, and it&#x2019;s functioning well.<br><br><em>With this in mind, Jack approves the pull request but adds a note: &#x201C;These functions seem similar; I would consider combining them.&#x201D;</em></blockquote><p>The key distinction here is Jack&#x2019;s approach&#x2014;he didn&#x2019;t request changes; he approved the pull request <strong>and added a comment</strong>. He might think he&#x2019;s pointed out a potential improvement, but in reality, he&#x2019;s shifted a reviewer&#x2019;s responsibility onto the author. Now, it&#x2019;s up to Arthur what to do.</p><p>Arthur sees an approved pull request and some mumbling about what Jack would consider but at this point who really cares what Jack would consider. The feature is good to go and the change is approved.</p><p>This exemplifies what I call a <strong>weak opinion</strong>&#x2014;a remark that doesn&#x2019;t require action, allowing it to be easily disregarded. The reviewer feels good for offering input, and the author is free to proceed with the merge.</p><p>Obviously, there is always an option to <strong>withhold an opinion</strong>:</p><blockquote>Marcus has finished reviewing Arthur&#x2019;s code and feels uncertain. Could the code be better? Probably. But that&#x2019;s true for most code, right? <br>Marcus thinks about leaving some comments but wonders if they&#x2019;d be helpful. Arthur probably knows about those issues and chose not to fix them because of the tight deadline. Why bring up the obvious?<br><br>Thinking his input won&#x2019;t add value, Marcus approves the change without comments.</blockquote><p>Reviewers might hold back for various reasons, such as doubting their feedback will lead to positive change or assuming the author is already aware of the issues and made a conscious decision. However, this can be more detrimental as it deprives the author of potentially valuable insights that could help to improve the code.</p><p>To recap:</p><ul><li>A <strong>strong opinion</strong> requires an action and is difficult to overlook.</li><li>A <strong>weak opinion</strong> merely provides information and can be ignored.</li><li>A <strong>withheld opinion</strong> is the absence of feedback when a reviewer has something to contribute.</li></ul><h2 id="roles-in-code-review">Roles in code review</h2><p>In the code review process, we have two key roles: the author and the reviewer.</p><p>Their shared goal is to find the most suitable solution, but they approach it from different angles, which is precisely what adds value to code reviews.</p><p>The author is deeply familiar with the problem, its significance, constraints (including deadlines), and the code they&#x2019;ve written. This deep involvement comes with certain risks:</p><ul><li>The author might prioritize the problem&#x2019;s urgency over other aspects due to its recency and their personal responsibility for resolving it.</li><li>Being so close to their own work, the author may struggle to evaluate the solution objectively.</li></ul><p>A reviewer is supposed to be in a better position to balance things out because they aren&#x2019;t familiar with this new code, not affected by the time spent deep in the solution mode, and probably less attached to the problem than to a pre-existing state of the system.</p><h2 id="challenge-of-being-a-reviewer">Challenge of being a reviewer</h2><p>The role of a reviewer isn&#x2019;t something that comes naturally to engineers. We&#x2019;re wired to write code and solve problems &#x2013; that&#x2019;s our comfort zone, where we spend most of our time.</p><p>But were you ever taught how to review code? If so, you&#x2019;re one of the lucky few. For most of us, code review just became another responsibility. The assumption was simple: if you can write code, you can surely comment on someone else&#x2019;s. But it&#x2019;s not that straightforward.</p><p>The difference between writing code and reviewing it is like the difference between playing the game and coaching. The game is the same, but the skills are different, and they need to be learned. Being a star player doesn&#x2019;t automatically make you a great coach.</p><p><strong>Therefore, reviewers often fall back into an author&#x2019;s mindset.</strong> </p><p>What does an author want? A fast, smooth review, a second set of eyes to confirm everything&#x2019;s okay, maybe a bug caught here or there. And that&#x2019;s what they end up giving &#x2014; quick checks instead of deep dives into the code that could reveal inefficiencies and provide constructive feedback to enhance both the codebase and the author&#x2019;s skills.</p><h2 id="where-weak-opinions-come-in">Where weak opinions come in</h2><p>From a reviewer&apos;s perspecitve, realizing the code could be improved and staying silent doesn&#x2019;t feel right. Yet, it&#x2019;s equally uncomfortable to ask a colleague to rework a substantial portion of their code or to dedicate additional time to address issues you&#x2019;ve identified.</p><p>Leaving a non-blocking comment that points out the problem without demanding action might seem like a way to avoid difficult conversations. </p><p>However, this approach can be misleading &#x2014; it makes you think you&#x2019;ve contributed to enhancing the codebase when, in fact, you&#x2019;ve passed the responsibility to the author. It&#x2019;s a soft touch that can lead to hard issues down the line. True improvement comes from facing these challenges head-on, not from sidestepping them.</p><h2 id="strong-yet-supportive">Strong yet supportive</h2><p><em>Strong </em>opinion does not mean <em>harsh.</em> This isn&#x2019;t about tearing down code that doesn&#x2019;t match up to your expectations. Your real mission is to foster positive change, not just to flag errors or show off your expertise.</p><p>A good piece of advice I once received was to assume missing important context.</p><p>It will be true more often than not because as a reviewer, you&#x2019;re not privy to every detail of the author&#x2019;s challenges, their objectives, or why they chose one path over another. And even if you think you&#x2019;ve got the full picture, you can&#x2019;t possibly know every solution out there to be certain your suggestion is the best and should be implemented.</p><p>That said, assuming missing important context it&#x2019;s not just about acknowledging that you might not have all the answers &#x2014; it&#x2019;s also about showing that you&#x2019;re open to learning and considering different approaches, not pushing for something you came up with.</p><h2 id="start-with-yourself">Start with yourself</h2><p>If you&#x2019;re on the fence about making a comment, think about the ripple effect. What if every commit had the same issue? </p><p>Imagine every pull request with functions taking three screens, similar to the one you&apos;re approving right now. Or more of those clever bitwise operations. Or complex calculations with no tests to prove they&apos;re correct. </p><p>It might seem like an overstatement, but it&#x2019;s the reality. We often mirror the style of the existing code for consistency. We copy-paste code blocks. We gauge what&#x2019;s acceptable based on what&#x2019;s made it through reviews before.</p><p>So, if you&#x2019;re sure there&#x2019;s room for improvement, don&#x2019;t hold back &#x2014; suggest an action and make it explicit. Sometimes, that action might just be a question for the author to explain their reasoning, which could sway your perspective. </p><p>Remember, not every comment has to lead to a change.</p><h2 id="help-others">Help others</h2><p>When you&#x2019;re in the thick of a code review, you might spot weak opinions left by others.</p><p>In such cases, you can play a crucial role.</p><p>By adding your own insights and explicitly requesting an action, you can transform these weak opinions into strong, actionable items. Whether it&#x2019;s through asking probing questions or even rejecting a pull request that someone else has approved, your input can significantly enhance the review process.</p><h2 id="interpret-non-blocking-comments-to-your-code">Interpret non-blocking comments to your code</h2><p>Non-blocking comments are often seen as optional, merely providing information or sharing a reviewer&#x2019;s thoughts.</p><p>But now you can see that&#x2019;s not always the case. A comment like <em>&#x201C;by the way, this function you implemented already exists in the library we use&#x201D;</em> isn&#x2019;t just a passing remark. It&#x2019;s a hint from the reviewer aimed at preventing cluttering the codebase with redundant code.</p><p>When you come across such comments, consider the broader implications, similar to when you are the reviewer. If every commit introduced similar issues, how would that affect the codebase over time? Again &#x2013; once a commit is merged, it becomes a part of the standard others will follow, potentially leading to a pattern that could be detrimental to the project&#x2019;s health. So, treat these comments with the seriousness they deserve &#x2014;t hey&#x2019;re not just side notes; they&#x2019;re signposts for maintaining standards.</p>]]></content:encoded></item><item><title><![CDATA[Overcoming Inertia in Tasks and Projects]]></title><description><![CDATA[Tactics for overcoming inertia, recognising when to pivot, and a few words about the importance of collaboration and estimation. ]]></description><link>https://evgenii.info/inertia/</link><guid isPermaLink="false">65f76a3b54395704e01df0a7</guid><category><![CDATA[Resilient Teams]]></category><category><![CDATA[Resilient Individuals]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Mon, 25 Mar 2024 23:15:47 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1497005367839-6e852de72767?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE5fHxiYWxscyUyMGhpdHRpbmclMjBlYWNoJTIwb3RoZXJ8ZW58MHx8fHwxNzEwODA0MTI0fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1497005367839-6e852de72767?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDE5fHxiYWxscyUyMGhpdHRpbmclMjBlYWNoJTIwb3RoZXJ8ZW58MHx8fHwxNzEwODA0MTI0fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Overcoming Inertia in Tasks and Projects"><p>All projects face unexpected issues.</p><p>Ideally, when this happens, the team comes together, figures out what&#x2019;s going wrong, and adjusts their plan. Maybe they set a new deadline. Or, they may even decide to drop the project if the problem&#x2019;s too big and it&#x2019;s smarter to focus on something else.</p><p>But things don&#x2019;t always work out so neatly. Sometimes, a team runs into trouble and just keeps on going the same old way. No one stops to rethink the strategy or suggest a new timeline. Everyone just keeps on with their tasks by inertia.</p><p>Then, one issue leads to another, and before you know it, you&#x2019;re used to the chaos. And that&#x2019;s when you miss a big deadline and find yourself in a mess because it&#x2019;s not the first project that&#x2019;s been delayed.</p><p>Let&#x2019;s talk about why these things happen and how we can stop them before they begin.</p><hr><p>Starting with a simple example &#x2014; and it&#x2019;s not about coding. Say you&#x2019;ve got to cut 5 sweet potatoes (I always struggle with those). You grab your knife, not realising it&#x2019;s a bit blunt, and get to work.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1596097558091-548313ceb129?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI3fHxzd2VldCUyMHBvdGF0b3xlbnwwfHx8fDE3MTA4MDIzNjl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" class="kg-image" alt="Overcoming Inertia in Tasks and Projects" loading="lazy" width="5184" height="3456" srcset="https://images.unsplash.com/photo-1596097558091-548313ceb129?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI3fHxzd2VldCUyMHBvdGF0b3xlbnwwfHx8fDE3MTA4MDIzNjl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1596097558091-548313ceb129?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI3fHxzd2VldCUyMHBvdGF0b3xlbnwwfHx8fDE3MTA4MDIzNjl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1596097558091-548313ceb129?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI3fHxzd2VldCUyMHBvdGF0b3xlbnwwfHx8fDE3MTA4MDIzNjl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1596097558091-548313ceb129?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI3fHxzd2VldCUyMHBvdGF0b3xlbnwwfHx8fDE3MTA4MDIzNjl8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption>Sweet potatoes by <a href="https://unsplash.com/@louishansel?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Louis Hansel</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><p>You pick the first potato, and it&#x2019;s tougher than you expected. But maybe it&#x2019;s just a tough one. You try another, and nope, it&#x2019;s definitely the knife. By the time you&#x2019;re halfway through the third, you know you made a mistake.</p><p>Now, the wise would pause and sharpen the knife. Not me. I&#x2019;m thinking, &#x201C;I&#x2019;m over halfway already &#x2014; I can handle these last two potatoes.&#x201D; I don&#x2019;t even consider that it is <strong>my</strong> darn knife, I will be using it again at some point and I&#x2019;ll have to sharpen it eventually. I regret not checking it earlier, but hey, two more potatoes, right?</p><blockquote>The best time to <s>plant a tree</s> sharpen the knife was twenty years ago. <br>The second best time is today.<br><br>&#x2013;&#xA0;Chinese proverb (not sure, I saw it on Instagram) </blockquote><p>For those who can&#x2019;t connect with the sweet potato tale, here&#x2019;s a different scene.</p><p>Your colleague picks a task. A small one, supposed to be done in a day. The next day, they show up at the standup meeting, admitting they got stuck and spent a day trying to figure it out. They should&#x2019;ve asked for help, but it&#x2019;s only clear now in hindsight. Thankfully, they&#x2019;re back on track now.</p><p>Another day goes by, and at the next check-in, the task&#x2019;s still not done &#x2014; hit by a couple more surprises. In retrospect, teaming up with someone the day before would&#x2019;ve been smart, but they kept thinking the end was in sight, so they didn&#x2019;t ask. Had they known the struggle ahead, they&#x2019;d have reached out for sure.</p><p>The following day, the task&#x2019;s still hanging. Almost finished, then bam &#x2014; a strange edge-case causes a memory leak that eats up hours. They ponder getting help but figure it&#x2019;ll take longer to bring someone up to speed than to fix it alone. Looking back, it wasn&#x2019;t as quick as they thought, but the time&#x2019;s already spent. The team offers to help, but they decline &#x2014; it&#x2019;s nearly done, just some unit tests and docs to go. This time, they&#x2019;re sure they&#x2019;ve got it right.</p><hr><p>In both scenarios from above:</p><ul><li>The first hiccup seemed like a one-off.</li><li>Upon realizing their error, there was regret for not adjusting course.</li><li>Yet, future actions remained unchanged, either because the mistake was deemed a one-off or it felt too late for corrections.</li></ul><p>This pattern can unfold over any timescale&#x2014;from minutes (like with those potatoes) to days (like that small task) to even weeks and months. Here&#x2019;s a story of my own.</p><blockquote>Some time ago, my team took a <strong>small</strong> project. It was low-risk, a perfect fit for one or two people.<br><br>We quickly settled on a strategy, broke it down into tasks, and dove into coding. But as we hit the 80% mark, we realized it was far more complex than anticipated. And complex projects demand a different playbook: thorough design reviews, risk assessments, and heightened scrutiny&#x2014;none of which we had done.<br><br>We had two paths. One was to hit pause on development, draft a design proposal, arrange a review, gather feedback, and then either proceed (if the feedback was minor) or scrap everything and start anew (if the review demanded it). The other path was to keep on going as we were.<br><br>You can probably guess&#x2014;I opted for no change, convinced our initial plan was solid and that second-guessing it would be a waste of time. I also figured we&#x2019;d already encountered enough issues to have uncovered them all. No more surprises, right? Lol.<br><br>To cut a long story short, it took a few more unexpected twists (and sprints) before we circled back, documented everything, and brought more hands on deck.</blockquote><p>You might have lived through something similar&#x2014;like that time someone skipped writing tests for a new feature. Then it crashed production, and everyone thought, <em>&#x201C;a test would&#x2019;ve caught that.&#x201D;</em> You fix it but skip the tests again, thinking, why bother when you&#x2019;ve just checked it manually?</p><p>It&#x2019;s rather a common issue:</p><ul><li><em>We should&#x2019;ve documented it, but I&#x2019;ve already explained it in a call, and it&#x2019;s unlikely anyone will ask again soon.</em></li><li><em>We should&#x2019;ve automated that deployment, but I&#x2019;ve done it manually this time, and we don&#x2019;t update this product often.</em></li><li><em>We should&#x2019;ve seen that dependency coming, but now that we&#x2019;ve found it, surely it was the only one.</em></li></ul><p>So, what&#x2019;s the game plan to combat this inertia?</p><h3 id="set-the-expectations">Set the expectations</h3><p>Imagine you&apos;re setting off on a drive with no map and no clue how long it will take. You pick a direction, hoping the road itself will be your guide.</p><p>But what if you make a wrong turn?</p><p>You might pass a landmark you weren&#x2019;t meant to see, or notice that the distance to your destination isn&#x2019;t decreasing on the road signs. Or perhaps the setting sun raises a red flag because, even though you didn&#x2019;t know the exact duration, you certainly didn&#x2019;t expect to be on the road all day.</p><p>Discovering mistakes like this can be a slow and costly process.</p><p>That&#x2019;s where expectations come into play. And I&#x2019;m not just talking about the big-picture journey, but also the smaller, interim milestones along the way, and when they&#x2019;re supposed to happen. <br>Sure, you might wonder if a detailed roadmap is necessary with all the risks and uncertainties involved. <strong>But at the very least, you should have an idea of what the next leg of the trip looks like and when you expect to reach it.</strong></p><p>It&#x2019;s not about micromanaging every step; it&#x2019;s about having enough foresight to recognise if you&#x2019;re off course and need to adjust your trajectory.</p><h3 id="schedule-the-check-points">Schedule the check points</h3><p>Having a roadmap is one thing, but what&apos;s the point if you never check it?</p><p>Imagine you&#x2019;re working on something, heads down, deep in the zone. You&#x2019;ve got your code, you&apos;re progressing, all looks good. But if you never stop to ask, &#x201C;Are we still on track?&#x201D; you might miss the signs that you&#x2019;re going off course. </p><p>To prevent it, begin your day by outlining what you aim to achieve and how long you expect it to take. Then, set the rules on when you&#x2019;re going to assess the progress. If you expect something to take two hours &#x2013; put a timer to assess your work. Are you meeting your own expectations? If something&#x2019;s taking longer than anticipated, it&#x2019;s a prompt to reassess and consider adjustments.</p><p>This is exactly why many teams have stand-ups or some other form of checkin-in with each other. <em>&#x201C;How&#x2019;s it going?&#x201D; &#x201C;Hit any roadblocks?&#x201D; &#x201C;Need a hand with anything?&#x201D;</em> &#x2013; this is exactly how we make sure we&#x2019;re still on track to meet our expectations and the right questions are being asked.</p><h3 id="act-upon-surprises">Act upon surprises</h3><p>Every surprise, every deviation from what you expected, is a piece of new information. This new information should prompt you to update your knowledge and reassess your actions.</p><p>Think of it this way: you set an expectation that performing certain actions (<em>X</em>) over a period (<em>T</em>) will give you a result (<em>Y</em>):</p><!--kg-card-begin: markdown--><p style="text-align: center;">X &#xD7; T = Y</p>
<!--kg-card-end: markdown--><p>You follow through with your plan for the allotted time, but <em>Y</em> doesn&#x2019;t materialize. This is where the learning opportunity lies&#x2014;you&#x2019;ve just discovered that <em>X &#xD7; T &#x2260; Y</em>.</p><p><strong>If you continue doing <em>X</em> as if nothing has happened, you&#x2019;re throwing this learning opportunity away.</strong></p><p>Before deciding on your next steps, you need to understand exactly what happened:</p><ul><li>Did you carry out all the actions you planned?</li><li>Did you dedicate the amount of time you had allocated?</li><li>How does the result you&#x2019;ve achieved compare to what you expected?</li></ul><p>Let&#x2019;s take an example: suppose there&#x2019;s a bug in your software that needs fixing, but you can&#x2019;t figure out how to replicate it. You have a vague idea of which part of the program might be responsible, but you&#x2019;re not certain what triggers the it. You decide to try out some common scenarios to see if any replicate the issue. It&#x2019;s a lot of work, but you expect that by tomorrow you&#x2019;ll either find the cause or rule out your theories.</p><p>Tomorrow arrives, and you aren&#x2019;t there yet.</p><p>Per the algorithm above, you review your actions and realize you didn&#x2019;t stick to the plan. You tested a few scenarios, got sidetracked by a minor bug and fixed it, updated some outdated documentation while testing another scenario, and helped a colleague with a code review. In the end, you only completed a fraction of your original plan (<em>X&#x2081;</em>), along with other tasks that didn&#x2019;t contribute to solving the main issue.</p><p>You also notice that you didn&#x2019;t spend the entire day on the task. Between the work mentioned above (<em>T&#x2081;</em>), you attended four meetings, responded to questions on Slack, and installed a mandatory MacOS update.</p><p>Looking at the scenarios you tested, you see you&#x2019;ve only covered about a quarter of what you intended (&#xBC; Y).</p><p>In essence, you did X&#x2081; * T&#x2081;, where X&#x2081; and T&#x2081; are only subsets of initially planned X and T. With that, it comes with no surprise that you didn&#x2019;t achieve Y.</p><p><strong>This is the critical moment when inertia can take hold.</strong> </p><p>You might think the plan is still sound and you&#x2019;re on the right track. Yesterday was just a bad day, and you didn&#x2019;t put in the effort you intended. But today, you assure yourself, will be different&#x2014;you&#x2019;ll stick to the plan and identify the bug by day&#x2019;s end.</p><p>However, it&#x2019;s important to <strong>question what will make today more successful than yesterday</strong>. Weren&#x2019;t you just as committed to the plan as you are today? Didn&#x2019;t you intend to spend the whole day on the bug?</p><p>So, what will you do differently this time? How will you safeguard the time allocated for bug hunting? How will you stay focused and avoid distractions? If you still have three-quarters of the scenarios left to test, you&#x2019;ll need to find a way to accomplish three times as much as yesterday. And if you&#x2019;re not planning any adjustments, perhaps it&#x2019;s time to reconsider your estimates.</p><h3 id="create-a-safe-atmosphere">Create a safe atmosphere</h3><p>Safe atmosphere is essential because without it, the strategies we&#x2019;ve discussed are unworkable. People must feel free to make mistakes and admit when they&#x2019;re wrong.</p><p>In all places I worked, it was always okay to admit not knowing something, ask for help, or acknowledge a misstep. But I know that not all environments are like this. In places where blame is common, people might conceal their errors, perhaps by padding their estimates to create a buffer for unseen issues. This approach might work for self-detected errors, but it falls apart when others point out the mistakes, leading to defensiveness rather than constructive dialogue.</p><p>There&#x2019;s a wealth of advice for leaders on fostering a safe environment. You&#x2019;re likely familiar with the basics:</p><ul><li>Begin from admitting your own mistakes and knowledge gaps.</li><li>Practice blameless conversations.</li><li>Help people to see the value in feedback and how it helps them reach their goals, fostering a willingness to adjust.</li></ul><p>But what if you&#x2019;re not in a position to shape your team&#x2019;s culture?</p><p>It&#x2019;s a tough spot, but there are still ways to course-correct openly without casting it in a negative light. One method is to <strong>explicitly plan for problems</strong>.</p><p>Say you&#x2019;re assigned a task you expect to complete in a day. If that day passes without progress, asking for help can be scary in a blame-heavy atmosphere. It&#x2019;s easier if you&#x2019;ve set the stage for assistance by initially stating you&#x2019;ll assess the problem and involve others if it&#x2019;s more complex than anticipated. The same goes for larger projects &#x2013; schedule regular assessments with the intention of refining your approach if you find a better one.</p><p>Does this change the reality of the situation? Not really. But it reframes adjustments from being the result of failure to being an integral part of the plan. If the chosen approach doesn&#x2019;t pan out, that&#x2019;s precisely why you planned the assessment.</p><h3 id="help-others-out-of-the-progress-trap">Help others out of the progress trap</h3><p>When you&#x2019;re deep in work, it&#x2019;s hard to realise you might be off track. You&#x2019;re in the thick of it&#x2014;solving problems, slaying dragons, and pushing forward. It all happens so gradually, it feels like progress. But remember, just because you&#x2019;re moving doesn&#x2019;t mean you&#x2019;re heading in the right direction.</p><blockquote>The first principle is that you must not fool yourself&#x2014;and you are the easiest person to fool.<br><br>&#x2013; Richard Feynman (but I also saw it on Instagram) </blockquote><p>We set expectations and checkpoints to help us assess our progress and spot when we&#x2019;re going astray. But it&#x2019;s this very act of planning and assessment that can be uncomfortable. It&#x2019;s easier to avoid asking the tough questions and to keep on &#x2018;progressing.&#x2019; To jump into coding without a plan, because then, anything you do seems like progress. Or to make a plan but never really check your results against it, because &#x201C;plans are useless, planning is indispensable.&#x201D;</p><p>If you notice teammates falling into this trap, step in with some helpful questions:</p><ul><li>&#x201C;When do you expect to finish X?&#x201D;</li><li>&#x201C;Now that we&#x2019;ve had this setback, do you think X will still be done by Y date?&#x201D;</li><li>&#x201C;What&#x2019;s the goal for today?&#x201D;</li></ul><p>And don&#x2019;t forget to share your own plans and progress. It helps set a standard and encourages everyone to think about whether they&#x2019;re really moving forward, not just moving.</p><h2 id="final-words-know-when-to-stick-to-the-plan">Final words: know when to stick to the plan</h2><p>While it&#x2019;s important to be agile and responsive, there&#x2019;s also benefits in holding steady with your plan. Constantly changing directions can be just as counterproductive as not changing at all. It&#x2019;s about finding that sweet spot.</p><p>You&#x2019;ll face problems and delays; that&#x2019;s inevitable. The key is to know which issues are just bumps in the road and which ones signal a need for a real change in plans. And that&#x2019;s not easy.</p><p>Why? Because it all rests on how solid your estimates are. If you&#x2019;ve got a good handle on your timeline, you can tell whether a new problem is something you&#x2019;ve already accounted for in your plan. If it is, then keep calm and carry on.</p><p>But estimating is a task in itself. We start off optimistic, get a reality check, and then swing to overly cautious. To get better at it, consider these steps:</p><ol><li><strong>Estimate with probabilities</strong>: outline the best, worst, and most likely scenarios. This helps you stay grounded and prepares you for potential issues.</li><li><strong>Review after completion</strong>: once you finish a task, compare the outcome with your estimate. This reflection helps improve your future predictions.</li><li><strong>Respect the history</strong>: don&#x2019;t ignore your past performance. It&#x2019;s the most reliable data you have. Aim to do better, sure, but base your plans on what you&#x2019;ve actually achieved before.</li></ol><p>Remember, planning and doing are different modes of thinking. You need a wide lens for planning and a narrow one for doing. That means you&#x2019;re not always in the best position to question the plan when you&#x2019;re in the middle of the work.</p><p>The good news? If you&#x2019;ve set clear expectations, checkpoints, a plan for surprises, and fostered a safe environment, you&#x2019;ve built a strong defence against unnecessary changes. Stick to the plan, adjust when you must, and keep moving forward.</p>]]></content:encoded></item><item><title><![CDATA[The power of "I don't know"]]></title><description><![CDATA[When a colleague has a question, it can be tempting to stay quiet if you don't know the answer. But admitting that you don't know is more helpful]]></description><link>https://evgenii.info/i-dont-know/</link><guid isPermaLink="false">63aa3672a4bc440aa9f829e9</guid><category><![CDATA[Resilient Teams]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Tue, 27 Dec 2022 19:41:31 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1563986768609-322da13575f3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHNsYWNrfGVufDB8fHx8MTY3MjEwMTE3OA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1563986768609-322da13575f3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fHNsYWNrfGVufDB8fHx8MTY3MjEwMTE3OA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="The power of &quot;I don&apos;t know&quot;"><p>Imagine you have a colleague named Boris. And Boris has a problem: he&apos;s been working on a new feature for five days, but now it&apos;s all falling apart. The application starts up, runs for a few minutes, and then shuts down with some weird error message and a huge stack trace.</p><p>Boris tries googling the error, but no luck. It looks like it&apos;s related to one of the microservices the application uses, and it&apos;s too specific for anyone outside the company to know. So he copies the error and posts it in a team chat, asking if anyone knows what it means.</p><p>You see the question, but you have no idea. </p><p>What would you do?</p><hr><p>While you&apos;re thinking, let me tell you what most people would do: nothing. And that&apos;s totally reasonable: they saw the question, they don&apos;t know the answer, and they don&apos;t want to spam the chat, so they just carry on with what they were doing before. One person does it, then another, and then a few more. Soon, everyone has seen the question and hasn&apos;t said anything.</p><p>But Boris is completely unaware of this. Maybe people are just busy and he needs to wait a little longer?</p><p>So he waits, until someone posts something else in the chat - another unrelated question &#x2013; and gets a few responses. Now Boris has to wonder if people would see his question when they open the chat.</p><hr><p>The best thing to do in this situation would be to say &quot;I don&apos;t know&quot; or react with a &quot;&#x1F937;&#x200D;&#x2640;&#xFE0F;&quot; to keep the chat from getting too noisy.</p><p>This lets Boris (and others) know that they don&apos;t need to wait for an answer from you, and it can help bring more attention to the problem, potentially leading to a quicker resolution. Or at least, Boris won&apos;t have to wait unnecessarily.</p><p>Even though this isn&apos;t the biggest problem you may have (it&#x2019;s not like Boris is going to wait for an answer for eight months while the company goes bankrupt because he can&apos;t complete the feature), being blocked is annoying. &quot;I don&apos;t know&quot; may not solve the problem, but it&apos;s a step in the right direction.</p><blockquote class="kg-blockquote-alt">The more influential you are, the more valuable your &quot;I don&apos;t know&quot; is.</blockquote><p>Boris might think <em>&quot;Even the tech lead who wrote a half of all code doesn&apos;t know this error,&quot;</em> and feel a little better about being stuck. <br>A recently hired junior might think <em>&quot;Wow, it&apos;s okay to admit you don&apos;t have an answer,&quot;</em> with the sense of uplift. <br>And someone who was hesitant to speak up without a definite answer, might suggest a couple of things to try since nobody else has any ideas. </p>]]></content:encoded></item><item><title><![CDATA[Keeping meetings on track]]></title><description><![CDATA[A list of tips to help you keep meetings on track.]]></description><link>https://evgenii.info/keeping-meetings-on-track/</link><guid isPermaLink="false">62eae7008e16b847ebb6c4c1</guid><category><![CDATA[Resilient Individuals]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Wed, 03 Aug 2022 21:39:38 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1525011268546-bf3f9b007f6a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDQzfHxkaWZmZXJlbnQlMjBkaXJlY3Rpb25zfGVufDB8fHx8MTY1OTU2MjcwOA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1525011268546-bf3f9b007f6a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDQzfHxkaWZmZXJlbnQlMjBkaXJlY3Rpb25zfGVufDB8fHx8MTY1OTU2MjcwOA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Keeping meetings on track"><p>You organise a meeting to agree on use-cases for a new feature. It is going well, and then a colleague asks which database you plan to use.</p><p>You&#x2019;re preparing a response (because you haven&#x2019;t decided yet), but someone suggests MongoDB.</p><p><em>&#x201C;But why not PostgreSQL?&#x201D;</em> another person counters. <em>&#x201C;We have a similar service, and it only needs one instance of PostgreSQL &#x2013; I wonder why the same configuration wouldn&#x2019;t work for you&#x201D;.</em></p><p>It surprises a few people. <em>&#x201D;One instance?! What is your load?&#x201D;</em></p><p><em>&#x201C;It&#x2019;s not high at the moment. We may need to consider adding more capacity as we grow, but I think three or four instances will be enough&#x201D;.</em></p><p><em>&#x201C;Have you ever questioned why we have so many databases in the same company?&#x201D;</em></p><p><u>And now you understand that the meeting went off-track.</u></p><h2 id="how-do-you-prevent-it">How do you prevent it?</h2><p>Should you ignore the question about databases? <br>Or stop on the MongoDB suggestion? <br>Or cut off the PostgreSQL-guy? And if yes, why him? </p><p>And what if their points are not as irrelevant as you think?</p><p>Here is a list of tips to help you keep meetings on track.</p><h3 id="at-the-beginning-of-the-meeting">At the beginning of the meeting...</h3><ul><li><strong>... explicitly state the goals.</strong><br>Sometimes, people are unaware of the goals &#x2013; an additional reminder will not harm. Plus, it will help you return the meeting on track later; you&#x2019;ll need to remind everyone what you&#x2019;re trying to achieve.</li><li><strong>... make people aware of time constraints.</strong><br><em>We have 60 minutes, and I need about 40 for the presentation &#x2013; the rest is for the discussion and Q&amp;A</em> &#x2013; something like that is enough to make everyone conscious of time.</li><li><strong>... share what exactly you plan to cover.</strong><br>When people know the order of topics, they won&#x2019;t interrupt with questions you plan to handle later.</li></ul><h3 id="during-the-meeting">During the meeting...</h3><ul><li><strong>... watch out for side conversations.</strong><br>Irrelevant questions are usually not a problem because you choose how much time to spend answering them. Irrelevant comments are fine either &#x2013; you can acknowledge it and follow up later. <br>Most of the time waste is caused by <em>side conversations</em> &#x2013; when several people are engaged in a dialogue about something that does not contribute to the goal. But yes, they usually start from irrelevant questions or irrelevant comments.</li><li><strong>... timebox side conversations.</strong><br>It is hard to assess whether a conversation goes off-track or someone just needs more time to make a point. Decide how much time you should wait before stopping it.</li><li>.<strong>.. treat irrelevant conversations equally no matter how they start.</strong><br>It is common to say something like <em>&#x201C;it is probably irrelevant but &#x2026;&#x201D;</em> before making a point that is indeed irrelevant. If you have limited time and something does not contribute to the discussion &#x2013; stop it.</li></ul><h3 id="after-the-meeting">After the meeting...</h3><ul><li><strong>... follow up on what was left undiscussed.</strong><br>Irrelevant &#x2260; not valuable. You may need to stop some conversations during the meeting, but people still have ideas worth discussing. Reach out to the people whose comments or questions didn&#x2019;t get proper attention for a follow-up conversation.</li></ul>]]></content:encoded></item><item><title><![CDATA[What to do if you're a bottleneck]]></title><description><![CDATA[Jackson is a go-to person when it comes to MongoDB. You have a problem – you go to Jackson.]]></description><link>https://evgenii.info/bottleneck/</link><guid isPermaLink="false">61958f123a336f43891771ca</guid><category><![CDATA[Resilient Teams]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Thu, 18 Nov 2021 22:15:58 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1532779982778-887e05358431?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDd8fGJvdHRsZSUyMHNoaXB8ZW58MHx8fHwxNjM3MTkyNjc1&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1532779982778-887e05358431?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDd8fGJvdHRsZSUyMHNoaXB8ZW58MHx8fHwxNjM3MTkyNjc1&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="What to do if you&apos;re a bottleneck"><p>Jackson is a go-to person when it comes to MongoDB.</p><p>You have a problem &#x2014; you go to Jackson. He&#x2019;s an expert. Of course, you can go to anyone else &#x2013; it&#x2019;s a free world. You can go to Molly if you want. But you know what Molly would recommend, don&#x2019;t you? She&#x2019;ll tell you to ask Jackson, that overworked guy with a giant todo list.</p><p>Let&#x2019;s talk about what to do if you ended up being a Jackson and need a way out.</p><h2 id="what-kind-of-a-bottleneck-are-you">What kind of a bottleneck are you?</h2><p>There are two different kinds of overworked Jacksons: knowledge bottlenecks and expertise bottlenecks.</p><p>Knowledge bottlenecks are the ones who answer questions.</p><p><em>&#x201C;Who owns Payment API?&#x201D;</em><br><em>&#x201D;Which database has client emails?&#x201D; </em><br><em>&#x201D;When is our next release?&#x201D;</em></p><p>If you&apos;re one of those, write documentation. Sorry for such trivial advice, but boring problems need boring solutions.</p><p>It&apos;s worth writing docs even if people don&apos;t read them. Sounds stupid, but it will serve as your second brain from where you can quickly copy answers.</p><blockquote>Watch out for an urge to share your screen and demonstrate something. It&apos;s always better to record a video (or a gif) and share it instead &#x2013; this way, you will be able to reuse it later. </blockquote><p>That was all about knowledge bottlenecks.</p><p>Expertise bottlenecks are trickier. They don&apos;t just answer questions &#x2014; they solve problems.</p><p><em>&#x201C;This program crashes for Netherlands users.&#x201D; </em><br><em>&#x201D;My DB query is slow.&#x201D; </em><br><em>&#x201D;Our photo gallery page leaks memory.&#x201D;</em></p><p>This situation is much more complicated because you need more experts to share the load. But unfortunately, there are no books or tutorials you could give to somebody and turn them into an expert &#x2013; they need to build the expertise themselves. And it takes time.</p><p>But how to accelerate the process?</p><h2 id="limited-opportunities">Limited opportunities</h2><p>If someone wants to learn how to play the guitar, they need to practice playing the guitar. Likewise, if one wants to learn how to fix memory leaks, they need to fix memory leaks.</p><p>The tricky part is there are much more opportunities to play the guitar than memory leaks to fix. They don&apos;t happen every day.</p><p>Zoom out now and look where you ended up: people call you whenever a challenging problem arises because nobody else has a similar experience. And nobody else has a similar experience because you solve all the challenging problems. A chicken and egg situation.</p><h2 id="growing-new-experts">Growing new experts</h2><p>The naive advice would be to stop doing what you&apos;re doing so that others can practice and build necessary expertise in time. But, unfortunately, it&apos;s overly utopian &#x2013; a few companies have the luxury of accumulating unsolved problems while their best specialist sits idle and waits for new experts to emerge.</p><p>But I&apos;m not saying it&apos;s impossible &#x2013; there is a way to grow new experts without slowing down the process. Here it is:</p><ol><li>Pick <strong>one</strong> successor to mentor. <br><em>Learning opportunities are scarce resource, so resist the temptation to pick more than one.</em></li><li>Redirect all requests to this person. <br><em>Need help? Ping Nelson, he knows this stuff.</em></li><li>Be available for this person. <br><em>Answer all their questions as soon as possible, pair program or pair debug when necessary.</em></li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/11/overview.png" class="kg-image" alt="What to do if you&apos;re a bottleneck" loading="lazy" width="711" height="436" srcset="https://evgenii.info/content/images/size/w600/2021/11/overview.png 600w, https://evgenii.info/content/images/2021/11/overview.png 711w"><figcaption>Real-life mentorship</figcaption></figure><p>It works because:</p><ol><li>The company will not slow down in critical situations &#x2013; if the time is tight, the mentoree can ask you for help.</li><li>You can tune your involvement depending on the circumstances to manage risks and guide the learning.</li><li>This person starts earning credibility from day one, solving real problems with your invisible help.</li></ol><p>In the beginning, be prepared to play broken telephone answering proxied questions:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/11/image.png" class="kg-image" alt="What to do if you&apos;re a bottleneck" loading="lazy" width="761" height="507" srcset="https://evgenii.info/content/images/size/w600/2021/11/image.png 600w, https://evgenii.info/content/images/2021/11/image.png 761w" sizes="(min-width: 720px) 720px"><figcaption>Proxy IRL</figcaption></figure><p>It may look like a waste of time, but it&apos;s far from it. Yes, the future expert acts as a proxy, but they learn about the domain. Even if it&apos;s a proxy, it&apos;s a caching proxy:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/11/image-1.png" class="kg-image" alt="What to do if you&apos;re a bottleneck" loading="lazy" width="764" height="507" srcset="https://evgenii.info/content/images/size/w600/2021/11/image-1.png 600w, https://evgenii.info/content/images/2021/11/image-1.png 764w" sizes="(min-width: 720px) 720px"><figcaption>They learn!</figcaption></figure><p>As their experience grows, they will start asking more complex questions:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/11/image-2.png" class="kg-image" alt="What to do if you&apos;re a bottleneck" loading="lazy" width="764" height="507" srcset="https://evgenii.info/content/images/size/w600/2021/11/image-2.png 600w, https://evgenii.info/content/images/2021/11/image-2.png 764w" sizes="(min-width: 720px) 720px"><figcaption>Now we&apos;re talking</figcaption></figure><p>This is the point where you can return to your expert&apos;s duties, which you now can split with another person:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/11/image-3.png" class="kg-image" alt="What to do if you&apos;re a bottleneck" loading="lazy" width="671" height="462" srcset="https://evgenii.info/content/images/size/w600/2021/11/image-3.png 600w, https://evgenii.info/content/images/2021/11/image-3.png 671w"><figcaption>No bottleneck anymore</figcaption></figure>]]></content:encoded></item><item><title><![CDATA[[Video] A Practical Guide to Personal SLA]]></title><description><![CDATA[Personal SLAs: How to maintain balance at work (recording)]]></description><link>https://evgenii.info/video-personal-sla/</link><guid isPermaLink="false">615b4f3dec4f6b52304d909b</guid><category><![CDATA[Resilient Individuals]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Mon, 04 Oct 2021 19:32:29 GMT</pubDate><media:content url="https://evgenii.info/content/images/2021/10/FAhnREaWQAA7iQk-2.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2021/10/FAhnREaWQAA7iQk-2.jpeg" alt="[Video] A Practical Guide to Personal SLA"><p>Last week, I joined a meetup organized by <a href="https://skillsmatter.com/">Skills Matter</a> to talk about work/life balance, Personal SLA and how one can apply best practices from Tech in your daily life. </p><p>I hope you find this video useful. </p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/UBoyPvdNtE8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen title personal slas: how to maintain balance at work" with evgenii ponomarev"></iframe></figure><p>Just remember:</p><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Podcasters sound a lot smarter at 2x</p>&#x2014; William Lyon (@lyonwj) <a href="https://twitter.com/lyonwj/status/1444304431537815556?ref_src=twsrc%5Etfw">October 2, 2021</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</figure>]]></content:encoded></item><item><title><![CDATA[The Story About a Smart Boss]]></title><description><![CDATA[Some people are lucky to work with extremely smart bosses. Molly hit the jackpot.]]></description><link>https://evgenii.info/smart-boss/</link><guid isPermaLink="false">6109b1daec4f6b52304d901b</guid><category><![CDATA[Resilient Teams]]></category><category><![CDATA[Tech Fiction]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Thu, 12 Aug 2021 19:47:33 GMT</pubDate><media:content url="https://evgenii.info/content/images/2021/08/philippe-oursel-ZAF-rhUyESY-unsplash--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2021/08/philippe-oursel-ZAF-rhUyESY-unsplash--1-.jpg" alt="The Story About a Smart Boss"><p>Molly had a very smart boss.</p><p>Once, they had a system outage in the middle of the night, which nobody could solve until they called Molly. She logged in, scanned through all the changes from the day before, read the logs, did her own tests, and found the culprit &#x2013; some expired certificates on one of their production clusters.</p><p>When the boss saw it the following day, he gathered everyone in one place and praised her in front of the others.<br>&quot;Thanks to Molly, the outage persisted for only 45 minutes. She was quick, accurate, and she did the exact things I would do in this situation.<br>I had numerous incidents like this in my life, you know. And now it almost feels easy &#x2014; I see the symptoms, and the root cause becomes apparent. But even with all this experience, I&apos;m not sure I could have done it faster than Molly.&quot;</p><p>And everyone clapped him because he was very smart and humble, and they knew he would have found these expired certificates much quicker.</p><hr><p>Another time, the whole team were brainstorming how to reduce the latency of their API. </p><p>Molly knew one or two things about it and proposed to cache frequently used data in Redis.</p><p>&quot;I think it can be a huge success,&quot; the boss commented. &quot;It&apos;s great that you mentioned that because I&apos;ve been analyzing Redis myself and was just about to create the task to begin using it. Do you guys all agree about giving it a try?&quot;</p><p>And everyone nodded because he was very smart and always had excellent and well-thought-out ideas.</p><p>&quot;Actually,&quot; the boss pointed to Molly, &quot;considering you also proposed Redis, why wouldn&apos;t you create tasks yourself?&quot;</p><p>And everyone found it to be a good idea because wise leaders delegate work to their people.</p><hr><p>Later that day, Molly called her old friend. He was a manager in another company, and she knew they were hiring.</p><p>&quot;Is it what, my birthday?&quot; her friend laughed. &quot;But how is your team gonna take it?&quot;</p><p>She paused for a second. &quot;I&apos;ll miss them... but they don&apos;t need me much anyway. I don&apos;t think anything will change&quot;.</p><hr><p>Molly was right &#x2013; nothing has changed with her departure.</p><p>She had a chance to see this for herself a year later when she met her former boss.</p><p>&quot;We just talked about you yesterday! There was a huge outage because of some expired certificates &#x2014; put us down for 12 hours! I remember you were good at fixing those...&quot;</p><p>Molly was startled but chose to switch to something more positive. &quot;Those certificates are always tricky, don&apos;t even remind me&#x2026; So how&apos;s the cool stuff, huh? API?&quot;</p><p>&quot;A bit slow as always, you know. But we plan to fix it soon &#x2014; I think if we can implement some sort of a cache, or perhaps find an open-source thing.&quot;</p><p>&quot;Like Redis,&quot; Molly suggested.</p><p>&quot;Exactly! You know, I&apos;ve been looking at it myself recently &#x2014; my favourite option so far!&quot;</p>]]></content:encoded></item><item><title><![CDATA[When to Use Nested Functions]]></title><description><![CDATA[Functions inside other functions... Worth it? ]]></description><link>https://evgenii.info/nested-functions/</link><guid isPermaLink="false">60bff3c9ec4f6b52304d8ee6</guid><category><![CDATA[Resilient Software]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Thu, 10 Jun 2021 22:54:02 GMT</pubDate><media:content url="https://evgenii.info/content/images/2021/06/yash-jain-BCixU5xjRy0-unsplash--1-.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>Warning: the word function appears more often than you are probably used to. Sorry.</blockquote><img src="https://evgenii.info/content/images/2021/06/yash-jain-BCixU5xjRy0-unsplash--1-.jpg" alt="When to Use Nested Functions"><p>Alright, let&apos;s begin: nested <u>functions</u> are <u>functions</u> defined inside other <u>functions</u> (promised and delivered). You saw them in many forms, like this one:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/pow-1.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1244" height="668" srcset="https://evgenii.info/content/images/size/w600/2021/06/pow-1.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/pow-1.png 1000w, https://evgenii.info/content/images/2021/06/pow-1.png 1244w" sizes="(min-width: 720px) 720px"></figure><p>Here, the function <code>multiply</code> is defined inside its parent, <code>pow</code>, although it does not have to be this way.</p><p>Or does it? If nothing else uses multiply, are there any reasons to move it out?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/06/button.jpg" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="500" height="756"><figcaption>Tough choice</figcaption></figure><p>This topic regularly ignites lengthy bike-shedding conversations regardless of the programming language (<a href="https://stackoverflow.com/questions/4831680/is-nested-function-a-good-approach-when-required-by-only-one-function">stack overflow about python</a>, <a href="https://www.reddit.com/r/swift/comments/4f4kb5/does_nested_function_promote_clean_code/">reddit about swift</a>), so I want to jump in and list some more pros and cons which you can apply for your needs.</p><h2 id="why-you-should-not-use-nested-function">Why you should <strong><u>not</u></strong> use nested function</h2><h3 id="nested-functions-reduce-readability">Nested functions reduce readability</h3><p>The bigger a function is, the harder it is to read it.<br>Look at this example:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/show-news-1.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1116" height="1196" srcset="https://evgenii.info/content/images/size/w600/2021/06/show-news-1.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/show-news-1.png 1000w, https://evgenii.info/content/images/2021/06/show-news-1.png 1116w" sizes="(min-width: 720px) 720px"></figure><p>By defining three additional functions inside <code>showNews</code>, you make the reader&apos;s job harder: they have to scan all of them before reaching the part with actual logic.</p><p>It might be much shorter:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/show-news-2.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1116" height="712" srcset="https://evgenii.info/content/images/size/w600/2021/06/show-news-2.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/show-news-2.png 1000w, https://evgenii.info/content/images/2021/06/show-news-2.png 1116w" sizes="(min-width: 720px) 720px"></figure><p>The reader still can jump to any functions to see how they work, but now it&apos;s optional.</p><h3 id="nested-functions-influence-future-growth">Nested functions influence future growth</h3><p>One may argue that not all nested functions affect readability.</p><p>In the previous example, you had three big helpers &#x2014; pretty bad. What if there was only one?</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/with-error.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1096" height="624" srcset="https://evgenii.info/content/images/size/w600/2021/06/with-error.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/with-error.png 1000w, https://evgenii.info/content/images/2021/06/with-error.png 1096w" sizes="(min-width: 720px) 720px"></figure><p>Does having <code>loadNews</code> inside the primary function cause any harm? After all, it is just several extra lines.</p><p>The danger of this approach shows itself when someone needs to add more functionality. You should not be surprised when your colleagues follow the same style and add other nested functions next to the existing one. After all, they just follow the rules you defined as an author.</p><blockquote>All it takes to degrade a good codebase is one example of a poor pattern and people&apos;s intent to maintain the code style. <br><br>Check the article about &quot;<a href="https://evgenii.info/reckless-reuse/">Reckless Reuse&quot;</a> for more examples of how code becomes unmaintainable without anyone noticing. </blockquote><h2 id="when-nested-functions-are-good">When nested functions are <u>good</u></h2><p>Now you may have an idea that all nested functions are evil and should be avoided by any means.</p><p>This is not true. </p><p>In some cases, they bring some benefits that can outweigh the disadvantages.</p><h3 id="sometimes-you-do-not-want-others-to-use-your-functions">Sometimes you do not want others to use your functions</h3><p>Yes, functions are meant to be reused. But you may not want it, e.g. if a function handles your particular case but is not suitable for everyone:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/is-equal-1.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1262" height="712" srcset="https://evgenii.info/content/images/size/w600/2021/06/is-equal-1.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/is-equal-1.png 1000w, https://evgenii.info/content/images/2021/06/is-equal-1.png 1262w" sizes="(min-width: 720px) 720px"></figure><p>There are many cases in which <code>isEqual</code> returns an unexpected result:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/wow.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="968" height="492" srcset="https://evgenii.info/content/images/size/w600/2021/06/wow.png 600w, https://evgenii.info/content/images/2021/06/wow.png 968w" sizes="(min-width: 720px) 720px"></figure><p>But it may be the exact behaviour you need.</p><p>In this case, it will be safer to define this function inside <code>saveNews</code> so that nobody has to deal with its peculiarities.</p><h3 id="sometimes-you-need-access-to-an-outer-scope">Sometimes you need access to an outer scope</h3><p>Many languages give nested functions access to the variables from the parent scope and even allow to modify them. You may need to explicitly declare such variables (Python) or capture them by reference (C++), but the benefits are the same:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/handle-error.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1170" height="1020" srcset="https://evgenii.info/content/images/size/w600/2021/06/handle-error.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/handle-error.png 1000w, https://evgenii.info/content/images/2021/06/handle-error.png 1170w" sizes="(min-width: 720px) 720px"></figure><p>In this case, the alternative would be passing all arguments to <code>handleError</code> every time we call it, using <code>Function.prototype.bind</code> or wrapping it into a factory. While I prefer different things depending on the situation, I see why somebody may use nested functions here.</p><h3 id="some-implementation-details-are-helpful">Some implementation details are helpful</h3><p>From the reader&apos;s point of view, there are few things worse than jumping between functions to understand how the whole thing works.</p><p>Try to understand this piece:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/no-details.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1114" height="228" srcset="https://evgenii.info/content/images/size/w600/2021/06/no-details.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/no-details.png 1000w, https://evgenii.info/content/images/2021/06/no-details.png 1114w" sizes="(min-width: 720px) 720px"></figure><p>The functions <code>onSuccess</code> and <code>onError</code> do not only hide implementation details but also obscure their purpose. You know something happens, but you don&apos;t know what exactly.</p><p>In this case, it would be better to define <code>onSuccess</code> and <code>onError</code> within the primary function so that the reader knows <em>what</em> is happening without leaving it:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/06/more-context.png" class="kg-image" alt="When to Use Nested Functions" loading="lazy" width="1114" height="624" srcset="https://evgenii.info/content/images/size/w600/2021/06/more-context.png 600w, https://evgenii.info/content/images/size/w1000/2021/06/more-context.png 1000w, https://evgenii.info/content/images/2021/06/more-context.png 1114w" sizes="(min-width: 720px) 720px"></figure><p>Two things to note here:</p><ul><li>Implementation details are still hidden: you know <em>what</em> is happening but not <em>how</em></li><li>Try to avoid situations like this by better naming and defining better APIs. The downsides of nested functions are still there.</li></ul><h2 id="so-what-to-do">So, what to do?</h2><p>I usually try to avoid nested functions because they make their parents bigger and, as a result, harder to read. Even if a nested function is concise and the impact is negligible, it can potentially become a slippery slope and serve as a bad example for adding similar ones.</p><p>But, as you can see, there are some situations when going this path does worth the downsides.</p><p>I hope that now you can defend any side in this holy war and justify the style you prefer. Happy coding!</p><p></p>]]></content:encoded></item><item><title><![CDATA[Driving Changes: How to Deal with Pushbacks]]></title><description><![CDATA[Facing pushback while driving engineering initiatives: most common reasons, how to prevent and handle.]]></description><link>https://evgenii.info/pushback/</link><guid isPermaLink="false">6005f412bf274b06b563edba</guid><category><![CDATA[Resilient Individuals]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Mon, 05 Apr 2021 17:32:19 GMT</pubDate><media:content url="https://evgenii.info/content/images/2021/03/jeremy-bishop-QtIXL7C4bB0-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2021/03/jeremy-bishop-QtIXL7C4bB0-unsplash.jpg" alt="Driving Changes: How to Deal with Pushbacks"><p>You work on a Big Improvement: rewrite backend on Go, move services to AWS, change a task tracker &#x2014; something that affects multiple people&apos;s day-to-day work.</p><p>And then the initiative faces a pushback.</p><p>How much it hurts depends on when you encounter it: rejected proposals feel more bearable than having to throw away the nearly finished work you&apos;ve been doing for months.</p><p>How to prevent it?</p><p>I have repeatedly found myself on both sides of the fence &#x2014; as a proponent of innovations and as a member of the sceptical camp. Now, I am pretty sure that Big Improvement&apos;s future entirely depends on its author: how they prioritise different kinds of work, address concerns and adapt to feedback.</p><p>Let&apos;s figure out how to deal with yours</p><blockquote>For the purpose of this article, I assume that:<br>1) you did your homework and know that your company will benefit from this initiative<br>2) you are open to feedback and ready to adjust if needed</blockquote><hr><h2 id="why-technical-initiatives-fail">Why technical initiatives fail</h2><p>Ask yourself: why would anybody reject a <em>good</em> initiative? Assuming nobody is malicious, the answer is obvious &#x2013; they do not think it is <em>good</em>. But why?</p><p>There are many possible reasons:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/03/image-2.png" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy" width="1416" height="670" srcset="https://evgenii.info/content/images/size/w600/2021/03/image-2.png 600w, https://evgenii.info/content/images/size/w1000/2021/03/image-2.png 1000w, https://evgenii.info/content/images/2021/03/image-2.png 1416w" sizes="(min-width: 1200px) 1200px"><figcaption>Potential reasons for a pushback</figcaption></figure><p>Some of them are more frequent than others, and I want to highlight these three as the most common:</p><ol><li>People do not believe you can reach promised goals</li><li>People tried what you built and did not like it</li><li>People disagree that the problem is worth solving</li></ol><p>Let&apos;s see how you can prepare to face each of them.</p><h3 id="reason-1-people-do-not-believe-you-can-reach-promised-goals">Reason 1: People do not believe you can reach promised goals</h3><p>Imagine a medieval kingdom that has been terrorised by a gigantic dragon for centuries. The dragon mercilessly burns the fields with the best crops, devours cattle, and kidnaps the most beautiful (by dragon standards) princesses.</p><p>You, a foreign knight, come in armour and on a white horse and ask for thirty armed men and two bags of gold to finish off the dragon forever &#x2013; something that many have tried to do, but no one has yet succeeded.</p><p>What do you expect to hear back?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/03/strange-person-1.gif" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy" width="350" height="256"><figcaption>They look sceptical</figcaption></figure><p><strong>How it may sound to you</strong></p><blockquote>Why do you think it would be more performant and easier to maintain? Are you sure? I&apos;m not sure... <br><br>&#x2013; Carina</blockquote><p><strong>What the root cause is</strong></p><p>The longer a problem exists, the harder it is to believe that somebody can solve it.</p><p>Especially if there were many unsuccessful attempts in the past.</p><p>Psychologists call this effect <a href="https://en.wikipedia.org/wiki/Learned_helplessness">&quot;Learned helplessness&quot;</a> and suggest that it can spread like a virus, infecting individuals, teams and organisations. Collectives that catch it become inert and pessimistic &#x2014; it requires enormous effort to overcome the dominant belief that nothing can be done.</p><p><strong>How to deal with it</strong></p><p>Scepticism is contagious. Therefore, it is easier to prevent it than change many people&apos;s mind. But you cannot do it with bare arguments.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/03/rabbit.gif" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy" width="500" height="292"><figcaption>Never ending arguments</figcaption></figure><p>Instead, you can benefit from applying some principles of <a href="https://www.britannica.com/science/hypothetico-deductive-method">the hypothetico-deductive method</a>:</p><ol><li>First of all, you agree on a definition of the problem with those who already tried to tackle it</li><li>Then, you propose your idea &#x2013; something that should solve the problem</li><li>Together, you deduce the list of consequences: what would the solved problem look like.<br>The list may be pretty long, so it is worth focusing on the riskiest cases: if the hypothesis is incorrect, you want to know it as soon as possible</li><li>And finally, you agree on the list of experiments that may help you to disprove the consequences and fail fast</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/03/Presentation-5.001-2-2.jpg" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy"><figcaption>The shorter version of the method</figcaption></figure><p>If it looks too abstract, let me bring a more concrete example:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/03/Presentation-5.001-3.jpg" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy" width="644" height="973" srcset="https://evgenii.info/content/images/size/w600/2021/03/Presentation-5.001-3.jpg 600w, https://evgenii.info/content/images/2021/03/Presentation-5.001-3.jpg 644w"><figcaption>How to structure a refactoring</figcaption></figure><p>In the example above, we propose using Rust to solve existing performance problems. <br>Instead of reasoning whether it would work or not, we identify parts of the system with higher chances of performance problems, agree on how failure would look like and design the experiments that may reveal the shortcomings. </p><p>Even though it may sound straightforward, it is common to see two other approaches which do not end up well:</p><ul><li>a proposal faces reasonable scepticism and does not get through not being backed by solid evidence</li><li>engineers either do not identify or do not prioritise risky cases and then have to throw away a large amount of work</li></ul><p>But anyway, it was a pretty easy one &#x2013; time for the more interesting case!</p><h3 id="reason-2-people-tried-what-you-built-and-did-not-like-it">Reason 2: People tried what you built and did not like it</h3><p>This happens a little bit later, when you think you built something good enough for others to use.</p><p>You prepare a polished demo that fulfils all expectations and makes everyone&apos;s hands hurt because of incessant applause:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/03/first-demo-2.gif" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy" width="480" height="270"><figcaption>A well-rehearsed first demo</figcaption></figure><p>But when others start using it... well, this happens:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/03/real-demo.gif" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy" width="400" height="225"><figcaption>This guy does it all wrong!</figcaption></figure><p><strong>How it may sound to you</strong></p><blockquote>I like the old way better. <br>Yes, I needed to change the code in five places. <br>Yes, the code was hard to test. <br>Yes, it was less performant. <br>But at least I could get it working because I knew what to do. <br>Now, I have no idea what&apos;s going on, and it all keeps breaking!<br>Can you de-engineer it back? <br><br>&#x2014; Marcus, the early adopter</blockquote><p><strong>What the root cause is</strong></p><p>There are several possible causes, and in most cases, they occur together:</p><ul><li><u>Not enough documentation</u><br>Writing docs is never the top priority during a turbulent time of building something new</li><li><u>Unexpected bugs</u><br>After the flawless announcement, people may develop high expectations and forget that this is only the first version</li><li><u>Unfinished implementation</u><br>It may be frustrating for early adopters to start working with the new thing and then stumble upon a blocker</li><li><u>Rosy retrospection</u><br>In psychology, <a href="https://thedecisionlab.com/biases/rosy-retrospection/">rosy retrospection</a> is the tendency to recall the past more positively than the present (even when the facts suggest the opposite)</li></ul><p><strong>How to deal with it</strong></p><p>Ensure that people have the best possible experience working with a new system from day one.</p><p>It would be ideal if you provide:</p><ul><li>Documentation with exhaustive examples</li><li>A list of known bugs and the current state of the roadmap to manage expectations before people start using it</li><li>Support during development so that you can answer questions as they arise and unblock people</li></ul><p>If it is impossible to do all of this because you don&apos;t have many resources, I would recommend keeping other people away from this version until it meets all criteria. The quality of the first impression means much more than time.</p><p>You may have valid reasons not to wait, e.g. when other engineers want to start building something else on top of your system while it is in development. All situations are different, but my suggestion for this case would be to pair with them until they have necessary context.</p><h3 id="reason-3-people-disagree-that-the-problem-is-worth-solving">Reason 3: People disagree that the problem is worth solving</h3><p>Imagine yourself in a group of bright scientists trying to invent powerful yet affordable quantum computers.</p><p>At some point, your experiments pay off, and you find the way to manufacture inexpensive quantum chips &#x2013;&#x2013; with them, even smartphones would vastly outperform existing supercomputers from the IBM labs.</p><p>However, there is one minor drawback. Its architecture is absolutely incompatible with what we have nowadays, <em>making most of our computer science knowledge redundant</em>. Needless to say, some developers may find having to learn all from the beginning a little unfortunate.</p><p>To say the least.</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/03/burn-her.gif" class="kg-image" alt="Driving Changes: How to Deal with Pushbacks" loading="lazy" width="480" height="362"></figure><p><strong>How it may sound to you</strong></p><blockquote>What do you mean by &apos;automated releases&apos;? All you need to do is to log in to the production machine, download new code and run three commands &#x2013; I can tell you which ones. <br>You call it a problem just because you were not here 12 years ago! <br><br>&#x2013; Dr Nicolas Peter, PhD</blockquote><p><strong>What the root cause is</strong></p><p>To discuss the root cause, we need to consider two separate cohorts:</p><ul><li>Those who are used to the current way of doing things</li><li>Those who somehow benefit from it</li></ul><p>The first group&apos;s reasoning is pretty obvious (just make the transition smooth for them); therefore, I will focus on the second one.</p><p>Nobody introduces inefficient systems on purpose. At least, these situations are pretty rare.<br>Quite the opposite &#x2013;&#xA0;people usually have good intentions:</p><ul><li>They see a big problem (same as you!)</li><li>They implement a solution (similar to your Big Improvement!)</li><li>They become experts in it.</li></ul><p>In time, the solution loses its appeal: it does not satisfy new requirements, there are open source analogues which do the same, and so on. It is time to replace it with something better, but it will imply throwing away all hard-earned knowledge, taking off an expert hat and having to learn something new.</p><p>Besides, the experts know the current version like the back of their hands and see all arguments as exaggerated.</p><p><strong>How to deal with it</strong></p><p>The traditional way of constructing an argument almost guarantees resistance. This is what I call a traditional way:</p><ul><li>You state the problem</li><li>You demonstrate evidence of why this problem is vast and needs solving</li><li>You describe how bright the future would be if you solved this problem</li><li>You explain how you are going to do it</li></ul><p>For all its factuality, this approach is devoid of any compassion: you go to the people who built <em>the thing</em>, to the people who use <em>the thing</em>, and to the people who have become experts in <em>the thing</em> and tell them not only that <em>the thing</em> is terrible, but that it has become a huge problem and needs to be replaced immediately.</p><p>The alternative approach acknowledges the history of an existing system and focuses on what changed since it was initially created. This can help build a foundation for productive collaboration with the current group of experts and get them on board.</p><p>This list of questions can help have a constructive conversation with the experts:</p><ul><li>What were the initial goals of the system?</li><li>Does the system still satisfy all its initial requirements?</li><li>Which parts of the system are you (the expert) not happy with?</li><li>Which parts of the system have degraded in time due to technical debt and negligence?</li><li>Have we received new requirements that the system does not meet?</li><li>How can we make it right together?</li></ul><p>This approach allows you to join forces with knowledgeable people to find out much more about current and potential use cases, identify hidden problems, and not repeat old mistakes. Experts, in turn, can retain and update their experience after replacing the existing system. Win-win.</p><h2 id="one-final-tip">One final tip</h2><p>Rejection can be painful. Fear of rejection is real. </p><p>You may want to avoid this by not letting anyone into your plans until everything is perfect. </p><p>Do not fall into this trap because building what nobody needs is much worse than facing a pushback.</p><p>Instead, be wise in driving your initiative because its future depends on you: how you identify stakeholders, prioritise different kinds of work and adapt to feedback.</p><hr><blockquote>Credits for the cover photo go to <a href="https://unsplash.com/@mattwridley?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Matt Ridley</a> (photo from <a href="https://unsplash.com/s/photos/innovation?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>)</blockquote>]]></content:encoded></item><item><title><![CDATA[The Story about Algorithms in Interviews]]></title><description><![CDATA[Meet Jeremy: he doesn't like old-fashioned tech interviews, but what alternative does he choose?]]></description><link>https://evgenii.info/algorithms-interviews/</link><guid isPermaLink="false">5fe67c5abf274b06b563ebff</guid><category><![CDATA[Resilient Individuals]]></category><category><![CDATA[Tech Fiction]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Thu, 21 Jan 2021 22:36:30 GMT</pubDate><media:content url="https://evgenii.info/content/images/2020/12/mark-rabe-zCJrolkwRyE-unsplash--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2020/12/mark-rabe-zCJrolkwRyE-unsplash--1-.jpg" alt="The Story about Algorithms in Interviews"><p><em>Thursday, September 3</em></p><p>&quot;Our interview process is pretty standard. You will have five rounds: three technical, one with HR and the final one &#x2013; with a hiring manager, each lasting between 40-60 minutes&quot; Anna says on the phone. The script is open on her laptop, but she does not need it &#x2014; if you recite the same speech ten times a day, text remembers itself. &quot;The first round will be focused on algorithms and data structures, so be prepared to answer questions about time complexity and ...&quot;</p><p>&quot;Are you serious?&quot; Jeremy laughs, interrupting the recruiter.</p><p>&quot;I&apos;m sorry?&quot; Anna asks with undisguised surprise after a short pause.</p><p>&quot;Of course you are! Do your engineers spend time on calculating complexity? No, they reconfigure Kubernetes and move buttons around. That is exactly why you desperately need programmers &#x2014; because nobody wants to waste their time on your seven rounds&quot;.</p><p>&quot;Five rounds,&quot; Anna corrects reflexively, but the candidate has already hanged up.</p><hr><p><em>Friday, September 4</em></p><p>&quot;And then I tell her: go get another idiot to write code on a whiteboard,&quot; Jeremy laughed.</p><p>&quot;For real?&quot; Dave almost chokes on beer. &quot;And she?&quot;</p><p>&quot;No clue, mate. I&apos;ve already spent my time listening to how agile they are, that was enough&quot;.</p><p>Dave recently changed a job and had a completely different story: nobody asked him to reverse linked lists or calculate Big O of made up algorithms. All he got to do was prepare a take-home coding challenge and solve a few problems onsite, all of which were similar to what a programmer might face in their day-to-day work. That leaves Jeremy enough faith that sane companies exist.</p><p>&quot;By the way, do you need more developers?&quot;</p><hr><p><em>Monday, September 7</em></p><p><em>From: <a href="mailto:hr-do-not-exist@catsandchickens.io">hr@catsandchickens.io</a></em><br><em>To: <a href="mailto:jeremythewizarddoesnotexist@gmail.com">jeremythewizard@gmail.com</a></em><br><em>Subject: Coding test</em></p><p>Hi Jeremy, <br>Thanks for showing interest in our FrontEnd Engineer position at Cats and Chickens!<br>The first part of our process is a test project that will allow you to demonstrate your coding skills and knowledge of Javascript, CSS and one of the most popular frameworks.<br>To maximise the efficiency, we ask that you complete the project within 10 days. We understand that you may have a tight schedule, so please let us know if you need some extra time. You will receive a separate email with the details from one of our engineers &#x2013; they will also be available for you should you need any assistance. Most of our candidates spend 15-20 hours working on a project, but it is totally up to you &#x2014; there are no minimal or maximum requirements to meet.<br>I would like to thank you in advance for dedicating time to complete this project!</p><p>Wishing you all the best,<br>Nathan.</p><hr><p><em>Wednesday, September 23</em></p><p>&quot;Rahul, you were looking at his homework project, how was it?&quot; Nathan asks, starting a pre-brief meeting before the onsite interview.</p><p>&quot;It existed.&quot;</p><p>&quot;Sweet, anything else?&quot;</p><p>&quot;It was big.&quot;</p><p>&quot;Perfect.&quot;</p><p>Sophia, a developer who is about to interview for the first time, looks at Rahul in disbelief. &quot;Didn&apos;t you review the code?&quot;</p><p>&quot;I was about to&quot;, he says and gives a conspiratorial wink. &quot;But then I got an urgent task and had to reconfigure Kubernetes&quot;.</p><p>Nathan perks up as if remembering something. &quot;You are new, right? What do you plan to ask?&quot;</p><p>Sophia prepared a couple of problems, one of which was to merge two sorted arrays. It is a decent warm-up question with numerous potential follow-ups, but Nathan does not seem to like it.</p><p>&quot;We do not ask algorithms &#x2014; only real-world problems engineers face every day. Sorry, but the market dictates new requirements.&quot;</p><p>&quot;Don&apos;t worry, we can rephrase the question to make it work. How about this?..&quot; Rahul pauses for a few moments to formulate a new task. &quot;Our website uses five different APIs to fetch products, all of them ordered by price. Ask the candidate to show them in one list with the cheapest ones at the top.&quot;</p><p>&quot;Do you mean merging elements from five sorted arrays?&quot;</p><p>&quot;Not <em>elements &#x2013; </em>products. And not arrays &#x2013; API responses, that&apos;s important!&quot; Rahul replies. &quot;And one more thing &#x2013; never say the word <em>complexity</em>, candidates hate it.&quot;</p><p>&quot;What should I do then?&quot; Sophia still looks puzzled.</p><p>&quot;Ask how it scales.&quot;</p><hr><p>Credits for the cover photo go to <a href="https://unsplash.com/@itsrahbee?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Mark Rabe</a>.</p>]]></content:encoded></item><item><title><![CDATA[How to use console.log to simplify refactoring]]></title><description><![CDATA[How a simple trick with console.log can help you with refactoring]]></description><link>https://evgenii.info/console-log-refactoring/</link><guid isPermaLink="false">5ffe0668bf274b06b563ecbe</guid><category><![CDATA[Resilient Software]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Thu, 14 Jan 2021 19:52:09 GMT</pubDate><media:content url="https://evgenii.info/content/images/2021/01/etienne-girardet-T_fYMj6H-pE-unsplash--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2021/01/etienne-girardet-T_fYMj6H-pE-unsplash--1-.jpg" alt="How to use console.log to simplify refactoring"><p>The most common advice about refactoring is to cover old code with tests before changing anything. This is a good suggestion &#x2014; we cannot modify code if we do not have a way to validate its correctness, and tests are the best way of gaining confidence.<br>However, it is easier said than done. The code you need to refactor is likely to be different from the samples you saw in the unit test tutorials which usually look like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/carbon.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="754" height="492" srcset="https://evgenii.info/content/images/size/w600/2021/01/carbon.png 600w, https://evgenii.info/content/images/2021/01/carbon.png 754w" sizes="(min-width: 720px) 720px"><figcaption>A typical unit-test tutorial</figcaption></figure><p>If the code consisted solely of single-purpose pure functions, you wouldn&apos;t need to refactor it at all. Most of the time, to-be-refactored code is hard to understand, not to mention writing tests for it. It is usually full of giant functions that do dozens of different things at the same time, implicit state manipulations, and hard-to-trace callbacks.<br>How to preserve a behaviour when changing a shape of code?</p><h3 id="let-s-refactor-something-">Let&apos;s refactor something!</h3><p>Here is a piece of old code which I would like to change:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/user-profile-2.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="1096" height="1284" srcset="https://evgenii.info/content/images/size/w600/2021/01/user-profile-2.png 600w, https://evgenii.info/content/images/size/w1000/2021/01/user-profile-2.png 1000w, https://evgenii.info/content/images/2021/01/user-profile-2.png 1096w" sizes="(min-width: 720px) 720px"><figcaption>Render user profile</figcaption></figure><p>The primary purpose of this code is to render the profile page for a given user, but it does a couple of other things:</p><ul><li>It sends stats when somebody requests a profile and when the page is rendered</li><li>It caches previously constructed pages for up to one hour (3600000 milliseconds) to reduce the database load</li></ul><p>We want to preserve this behaviour, which means we need resilient tests for it.</p><h3 id="resilient-tests">Resilient tests?</h3><p>You want to write tests which will survive code refactoring. It is extremely unpleasant if you spend time writing them, then you change code and all your tests need to be fixed.</p><p>To demonstrate the problem, I will show how we can test that stats are being sent correctly:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/test-fetch.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="970" height="448" srcset="https://evgenii.info/content/images/size/w600/2021/01/test-fetch.png 600w, https://evgenii.info/content/images/2021/01/test-fetch.png 970w" sizes="(min-width: 720px) 720px"><figcaption>Asserting <code>fetch</code> in tests</figcaption></figure><p>Check again the piece of code that sends those stats:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2021/01/test-fetch-close-1.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="916" height="404" srcset="https://evgenii.info/content/images/size/w600/2021/01/test-fetch-close-1.png 600w, https://evgenii.info/content/images/2021/01/test-fetch-close-1.png 916w" sizes="(min-width: 720px) 720px"></figure><p>You can see several issues with this code:</p><ol><li><code>renderProfile</code> has to know how to send stats &#x2014; if we are to change it in the future, we will need to adjust this function</li><li>We do not handle errors &#x2014; nothing catches if a request fails</li><li>All events are sent independently &#x2013; it would be better to send stats in batches to reduce the number of requests</li></ol><p>A right approach would be to put stats-related functionality to the separate module and then use it in the main one:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/stats-module-1.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="916" height="976" srcset="https://evgenii.info/content/images/size/w600/2021/01/stats-module-1.png 600w, https://evgenii.info/content/images/2021/01/stats-module-1.png 916w" sizes="(min-width: 720px) 720px"><figcaption>Separate module for stats</figcaption></figure><p>If we run tests right now, they will fail because <code>renderUserProfile</code> does not send requests directly, it calls <code>stats.trackUserRequest</code> instead.</p><h3 id="using-console-log-to-strengthen-tests-during-refactoring">Using <code>console.log</code> to strengthen tests during refactoring</h3><p>When everything is hugely volatile, we may want to temporary sprinkle logs in important logical pieces:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/console-log-in-render-profile.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="1060" height="404" srcset="https://evgenii.info/content/images/size/w600/2021/01/console-log-in-render-profile.png 600w, https://evgenii.info/content/images/size/w1000/2021/01/console-log-in-render-profile.png 1000w, https://evgenii.info/content/images/2021/01/console-log-in-render-profile.png 1060w" sizes="(min-width: 720px) 720px"><figcaption><code>console.log</code> next to sending stats</figcaption></figure><p>On the next step, write tests asserting that correct data was logged:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/test-for-console-log.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="1024" height="448" srcset="https://evgenii.info/content/images/size/w600/2021/01/test-for-console-log.png 600w, https://evgenii.info/content/images/size/w1000/2021/01/test-for-console-log.png 1000w, https://evgenii.info/content/images/2021/01/test-for-console-log.png 1024w" sizes="(min-width: 720px) 720px"><figcaption>Checking if the correct string was logged</figcaption></figure><p>Then, make sure that those logs go to the right places during refactoring:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/logs-in-stats-1.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="1060" height="1020" srcset="https://evgenii.info/content/images/size/w600/2021/01/logs-in-stats-1.png 600w, https://evgenii.info/content/images/size/w1000/2021/01/logs-in-stats-1.png 1000w, https://evgenii.info/content/images/2021/01/logs-in-stats-1.png 1060w" sizes="(min-width: 720px) 720px"><figcaption>Logs stick with the relevant code</figcaption></figure><p>When refactoring is done, remove all useless logs and replace them with proper assertions in tests:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/final-stat-test.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="970" height="448" srcset="https://evgenii.info/content/images/size/w600/2021/01/final-stat-test.png 600w, https://evgenii.info/content/images/2021/01/final-stat-test.png 970w" sizes="(min-width: 720px) 720px"><figcaption>Logs did the job and can be removed</figcaption></figure><p>This simple trick will help you keep your tests green during refactoring no matter how much code you modify. Using this method, you can test very complex logic, such as caching:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2021/01/caching-test.png" class="kg-image" alt="How to use console.log to simplify refactoring" loading="lazy" width="1114" height="2076" srcset="https://evgenii.info/content/images/size/w600/2021/01/caching-test.png 600w, https://evgenii.info/content/images/size/w1000/2021/01/caching-test.png 1000w, https://evgenii.info/content/images/2021/01/caching-test.png 1114w" sizes="(min-width: 720px) 720px"><figcaption>Tests for caching logic</figcaption></figure><h3 id="final-words">Final words</h3><p>It is troublesome when you cannot rely on your tests when you need them the most. But it is much worse when your tests are green and code works incorrectly.</p><p>Use this method only as a temporary strengthening for tests during refactoring and replace all occurrences of console.log with the proper assertions as soon as you can.</p><p>Happy refactoring!</p><p></p>]]></content:encoded></item><item><title><![CDATA[The Story About the Boy Scout Rule]]></title><description><![CDATA[The Boy Scout rule (always leave the code in a better state than when you found it) is famous among developers, but does it have its pitfalls? Meet Simon and Andy, who have a lot to share.]]></description><link>https://evgenii.info/boy-scout-rule/</link><guid isPermaLink="false">5ff0ceb6bf274b06b563ec86</guid><category><![CDATA[Resilient Software]]></category><category><![CDATA[Tech Fiction]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Thu, 07 Jan 2021 21:21:31 GMT</pubDate><media:content url="https://evgenii.info/content/images/2021/01/jr-korpa-UmPCUdbjaOU-unsplash--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2021/01/jr-korpa-UmPCUdbjaOU-unsplash--1-.jpg" alt="The Story About the Boy Scout Rule"><p>The layout of Mr Meyer&apos;s office is more suitable for questioning than for productive conversation: a massive high-backed chair that looks more like a throne, a long desk intended to separate the host from guests, and odd portraits of old long-bearded men looking shrewdly at anyone who has to report to the boss.<br>Today, that honourable duty goes to Simon and Andy. Not that any of them are happy about this great opportunity, in part because of the office&apos;s oppressive atmosphere, but mainly because of the reason they are there.</p><p>Mr Mayer represents &quot;Chips Industrial&quot;, the company that outsources development to the firm where Simon and Andy work. After the recent release, their flagship product&apos;s revenue fell by 15% due to a software bug, the nature of which they were trying to explain for ten minutes.</p><p>&quot;Once again, what was that release for?&quot; Mr Meyer asks.</p><p>Simon, the project manager, is the one to answer: &quot;We added a new feature to the application, so users could find products by a bar-code&quot;.</p><p>&quot;And why did the money go down?&quot;</p><p>&quot;Unfortunately, this change had an accidental and undesirable effect &#x2014; all payments from PayPal stopped coming, and we have a fairly large set of PayPal users, hence the drop in revenue&quot;.</p><p>&quot;Undesirable effect,&quot; Mr Meyer repeats slowly and then pauses.</p><p>Andy, the developer, breaks silence: &quot;We&apos;ve already reverted this feature, and all metrics are back to normal. Now, we&apos;re working on a fix and then we&apos;ll re-land the change&quot;.</p><p>&quot;Oh, thank you!&quot; Mr Meyer exclaims. &quot;Why am I asking this when I must praise you two! We paid for two months of work so you could release the feature, drop money and heroically revert it. Why the hell did you have to break PayPal, bar-codes must have nothing to do with PayPal?!&quot;</p><p>&quot;They don&apos;t,&quot; Andy agrees. &quot;But we had to change the database, and we noticed some inefficiencies in the schema: unused tables, meaningless foreign keys, even typos in column names. As we worked on a migration script, we just followed the Boy Scout rule and did a cleanup&quot;.</p><p>&quot;But why?&quot;, Mr Meyer looks puzzled and annoyed at the same time.</p><p>&quot;One renamed field was still used by the payment system, and we missed it&quot;.</p><p>&quot;That&apos;s not what I ask,&quot; Mr Meyer interrupts. &quot;Why to touch something unrelated to the feature? To me it looks like somebody in your company sabotaged the project&quot;.</p><p>&quot;No-no-no!&quot; Simon hastily waves his hands in response to this accusation. &quot;Nobody tried to sabotage anything. Moreover, all our people worked to do their best to improve the codebase. Yes, accidents do happen sometimes, and we were prepared to quickly revert the feature and recover the database. As for your initial question, it is an industry&apos;s common practice to continuously improve parts that need improvement&quot;.</p><p>&quot;The Boy Scout rule &#x2014; always leave the campground cleaner than you found it,&quot; Andy adds.</p><p>&quot;Okay,&quot; Mr Mayer says and starts furiously typing something on his keyboard. <em>Clack-clack-clack click clack-clack.</em> Andy and Simon are at a loss to guess what he is up to, but they do not dare ask. After two minutes of laud clacking and clicking, he turns his laptop over to Simon: &quot;Read it to me&quot;.</p><p>The project manager comes to the screen, close enough to read from an excel spreadsheet. &quot;Product designers &#x2014; one,&quot; he begins and then looks blankly at the owner of the office.</p><p>&quot;The list of people who work on this project. For whose work I pay,&quot; Mr Meyer explains slowly and distinctly. &quot;Continue&quot;.</p><p>&quot;Project manager &#x2013; one. Senior developers &#x2014; two. Junior developers &#x2014; one. QA engineers &#x2014; two,&quot; Simon finished reading. &quot;I&apos;m not sure I understand...&quot;</p><p>&quot;Where are Boy Scouts? Where? Do I pay for Boy Scouts?!&quot; Mr Meyer breaks into a scream. &quot;Are you a Boy Scout?&quot;</p><p>Simon shakes his head.</p><p>&quot;You?&quot; Mr Meyer looks at Andy, but he cannot find what to answer. He opens the mouth to explain the nature of the boy scout rule and why it is reasonable for developers to use it, but Simon intervenes before he can start:</p><p>&quot;We are sorry, Mr Meyer, that was totally unacceptable. We are working hard to re-release the feature without the problematic cleanup, and we will make sure similar problems won&apos;t happen again.&quot;</p><p>&quot;You meant to add a new feature, not to break payments!&quot;</p><p>&quot;That is fair&quot;.</p><p>&quot;Why not to do your freaking clean up after the feature? We advertised it to users &#x2014; can you imagine how busy our support is right now?!&quot;</p><p>&quot;I understand, Mr Meyer, that was an oversight on our side, and we will do our best,&quot; Simon continues, seeing that despite heated atmosphere, Mr Meyer looks a bit calmer. &quot;It won&apos;t take too long &#x2014; end of the week the latest&quot;.</p><p>After a long stare at Simon, Mr Meyer sinks into a chair. He nods silently as if coming to a conclusion in his inner dialogue. Then he purses his lips and points to the door, much to Andy and Simon&apos;s relief.</p><p>&quot;And keep an eye on your damn Boy Scouts!&quot; </p>]]></content:encoded></item><item><title><![CDATA[New to the Project? Do Code Reviews!]]></title><description><![CDATA[Why all new developers should do code reviews, how to begin and get the most out of it]]></description><link>https://evgenii.info/new-developer-do-code-reviews/</link><guid isPermaLink="false">5fcea720bf274b06b563eb77</guid><category><![CDATA[Resilient Individuals]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Tue, 08 Dec 2020 22:57:43 GMT</pubDate><media:content url="https://evgenii.info/content/images/2020/12/code-review-beginner.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2020/12/code-review-beginner.jpg" alt="New to the Project? Do Code Reviews!"><p>I put it straight &#x2013; you do not need to have any prior knowledge about the codebase to start doing code reviews.</p><p>This article is going to be about why all new developers should review code, and how to get the most out of it. If you do not need any convincing or guidance, you may rather watch <a href="https://www.instagram.com/p/BwAa3I-hjkI/"><u>how I win a fight with my cat</u></a>.</p><blockquote>&quot;New developers&quot; in this context are not only people who have just started a career but also experienced developers working with the unfamiliar codebase.</blockquote><h2 id="benefits-of-doing-code-reviews">Benefits of doing code reviews</h2><p>First of all, it is going to speed up your onboarding. Right now, your learning is limited by the number of tasks you are directly involved in &#x2014; you learn from your own successes and mistakes.</p><p>Reviewing other solutions is a quick way to get around this limit. You can get to know various parts of code without touching them personally and see what works and what does not for different types of problems.</p><p>On the other hand, your feedback will be beneficial to the team because you have a crucial trait that no one else has &#x2014; fresh eyes with no prior context. <br>As writers cannot edit their own texts, programmers rarely can judge their code. We know too much about why it is written this way, and the more people share the same understanding, the harder it is to have an unbiased opinion. While you have limited knowledge, you are the only person who can give a fresh view and challenge what others take for granted.</p><h2 id="how-to-approach-code-reviews">How to approach code reviews</h2><h3 id="1-do-not-be-afraid">1. Do not be afraid</h3><p>All teams I worked with had a high demand for code reviews, which is quite common in the industry. Therefore, do not be afraid of starting &#x2014; nobody will mind having one more pair of eyes available.</p><p>It is quite common to fear not catching a bug or merging code that would need some improvements. A workaround is simple &#x2014; do not approve a pull request if you are not sure. Leave your comments, ask questions, and ping somebody else for a final verdict.</p><h3 id="2-understand-the-problem">2. Understand the problem</h3><p>Before looking closely at the code, familiarize yourself with the problem:</p><ul><li>What is the definition of done? </li><li>Is it complete? </li><li>Would you add anything else? </li><li>How would you test it?</li></ul><p>Think about all possible use-cases the author may need to implement. Then, either remember them or write them down &#x2014; this is going to be handy soon.</p><h3 id="3-draft-your-own-solution">3. Draft your own solution</h3><p>Remember, we are not reading code yet :-)</p><p>To get the most from this learning opportunity, think about how you would approach this task:</p><ul><li>How to structure data?</li><li>Where to put logic?</li><li>Is there anything in the codebase you should reuse? If unknown, how would you search for it?</li><li>Who is more knowledgeable in this area to advise you if you were the one picking this task?</li></ul><p>Once again, write it down or keep in your memory &#x2014; up to you.</p><h3 id="4-prove-that-the-problem-is-solved-fully">4. Prove that the problem is solved fully</h3><p>Now it is the time to start looking at implementation but only at a high-level. Focus on <em>what</em> rather than <em>how</em>.</p><p>Sometimes, clear and correct code does a wrong job:</p><ul><li>An author may misread or misinterpret requirements</li><li>They may implement some parts and forget the others</li></ul><p>Look at the list of possible use-cases you prepared earlier:</p><ul><li>Are all of them handled? <br>If not, ask whether they need to be &#x2014; it is safe to assume that you are the one who misunderstood the problem.</li><li>Are there any cases you did not consider? <br>If the author implemented something you did not even think about, it is excellent &#x2014; you already learned something new!</li></ul><h3 id="5-compare-your-solution-with-the-pull-request-">5. Compare your solution with the pull request.</h3><p>Now you know how you would approach this problem, but how did the author solve it?</p><p>Find differences between both approaches and try to understand the pros and cons of each. The best way to do it is to ask questions:</p><ul><li>Why was it preferred to put X and Y to the same database table, rather than keeping them separately?</li><li>Why was the primary logic put to module A, while module B has similar pieces that might be collocated?</li></ul><p>This way is how you learn the most &#x2014; not by reading the code and checking it for correctness, but by exercising your skills and validating proposed solutions.</p><h3 id="6-ask-questions-about-code-">6. Ask questions about code.</h3><p>When you get the answers to all high-level questions, it is time to zoom in and look deeply at code:</p><ul><li>Is it easy to understand or something needs further clarification? <br>Questions from new developers often mean that the code is not as self-explanatory as it could be. The author may consider adding comments or restructuring obscure fragments.</li><li>Are there ways to improve the code? <br>Even though you&apos;re new to the project, you can read and write code, right? Leave a suggestion when you see a room for improvement &#x2014; after all, it can only help.</li></ul><p>People frequently ask where is that line between giving useful comments and nitpicking. Is it appropriate to ask to rename a variable or to chase a negligible performance improvement?</p><p>As for me, everything is alright as soon as you communicate what is essential and what is not. I always prefix minor comments with the words &apos;minor&apos; or &apos;nit&apos;, so the author knows which are ok to ignore.</p><h3 id="come-back-later">Come back later</h3><p>If the pull request was not immediately merged &#x2014; make sure you check it for new comments later.</p><p>Someone may reject it despite your approval; someone may add fruitful comments &#x2014; this is just another piece of context that is never superfluous.</p>]]></content:encoded></item><item><title><![CDATA[Reckless Reuse: How Modules Grow Big]]></title><description><![CDATA[Does your project have an enormous module called something-manager or something-controller that grew beyond any possible limits and became completely unmaintainable? How to prevent it from happening?]]></description><link>https://evgenii.info/reckless-reuse/</link><guid isPermaLink="false">5fb7008abf274b06b563ea60</guid><category><![CDATA[Resilient Software]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Tue, 01 Dec 2020 20:10:56 GMT</pubDate><media:content url="https://evgenii.info/content/images/2020/11/wayne-robinson-O-TM2E-7cn4-unsplash--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://evgenii.info/content/images/2020/11/wayne-robinson-O-TM2E-7cn4-unsplash--1-.jpg" alt="Reckless Reuse: How Modules Grow Big"><p>Does your project have an enormous module called <em>something-manager</em> or <em>something-controller</em> that grew beyond any possible limits and became completely unmaintainable? How many do you have?</p><p>Usually, <a href="https://en.wikipedia.org/wiki/Code_smell">code smells</a> are the results of deliberate actions:</p><blockquote>We had a tight deadline and agreed to ship overcomplicated and unreadable code. We never prioritized writing tests, and now we little confidence in changing old logic.</blockquote><p>Large modules are a different story. They do not happen overnight, and I&apos;m yet to see a person suggesting to put a ton of random methods to one pile and call this pile <em>GlobalManager </em>or <em>Utils</em>. It is never a choice, but rather the result of many good intentions: small enough to attract attention, but still dangerous to cause harm.</p><h2 id="evolution-of-one-module">Evolution of one module</h2><p>Let me start from an oversimplified fictional example.<br>Imagine that you work on a piece of software for college students and their teachers.<br>First of all, we need to allow teachers to see all assignments that a particular student has. Let&apos;s write a module for it!</p><p>This is what we need to do:</p><ul><li>Check that a user is a teacher and hence has necessary permissions</li><li>Get all we need from the database</li><li>Format the result and show it to the user</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-5.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="426" height="600"><figcaption>One public <code>showAssignments</code> and some private functions</figcaption></figure><p>A work in progress, but nothing terrible is happening so far.</p><p>Time goes, and teachers request another feature: they also want to see which <em>books</em> their students have. Sounds like a weird request, but we can live with that.</p><p>For this feature, we can reuse several functions we wrote before (<em>getRole, formatResult</em> and <em>showContent</em>). All we need to do is to add this small change:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-6.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="411" height="334"><figcaption>A small change</figcaption></figure><p>At some point later, we get another request, but it is not about teachers anymore &#x2014; students also want to keep track of their books to know what they need to return to the library.<br>This one is even easier to implement:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-7.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="422" height="229"><figcaption>Another small change</figcaption></figure><p>tiny function that reuses previously implemented capabilities &#x2014; easy choice, easy code review.<br>But now students have one more request: they need more information about their books, i.e. the date when it should be returned. Something that <em>formatResult </em>cannot do. Luckily, we are programmers and can make them happy:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-8.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="495" height="232"><figcaption>Splitting <em>formatResult</em> and <em>formatBooksForStudents</em></figcaption></figure><p>Job is done!<br>The last piece of news for this example: teachers decided that the strange case about seeing students&apos; books was redundant, and there is no real situation for which it would be needed.<br>Who does not like removing code, huh?</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-9.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="395" height="230"><figcaption>Another simple change</figcaption></figure><h2 id="boiling-frogs">Boiling frogs</h2><p>We must be proud because we maximized code reuse and iteratively supported new use cases with minimal code changes. All commits were concise and sensible, at least at first glance.</p><p>However, it is worth checking the module once again &#x2014; not only the changes but full content:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-10.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="495" height="703"><figcaption>Two unrelated use-cases in one file</figcaption></figure><p>Two different types of content for two different types of users. Not much overlap.</p><p>What&apos;s much worse is that this module is prone to unlimited expansion. Every small change related to students, teachers, books or assignments is justifiable until at some time we wake up with a module so big that the only thing left to do is teach it how to make coffee. Fortunately, <a href="https://en.wikipedia.org/wiki/Boiling_frog">the water is already boiling</a>.</p><h2 id="why-it-happens">Why it happens</h2><p>Several factors are contributing to this process.</p><p>We, developers, love reusing code. It saves us a lot of effort &#x2014; can you imagine the world where we had to write everything from scratch?</p><p>At the same time, we do not like changing old code. Sometimes it is hard, sometimes it is unsafe, sometimes it just makes us think.</p><blockquote>Code that we can reuse &#x2014; investment.<br>Code that we have to change &#x2014; legacy.</blockquote><p>That leads to the thinking pattern which I call <em>Reckless Reuse</em>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-11.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="480" height="852"><figcaption>Reckless Reuse</figcaption></figure><h2 id="how-to-avoid">How to avoid</h2><p>To prevent <em>Reckless Reuse</em>, keep in mind the original purpose of a module you intend to change:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-12.png" class="kg-image" alt="Reckless Reuse: How Modules Grow Big" loading="lazy" width="480" height="908"><figcaption>Refactor before reuse</figcaption></figure><p>In our example, we could move the functions <em>getRole</em> and <em>showContent</em> outside of the module that serves teachers, so we still can reuse them from other places of the application without having to grow the teachers&apos; module.</p><p>Unfortunately, it is never enough to just do it yourself &#x2013; all collaborators should adopt the same practices. There are a couple of tricks that can help you with that:</p><ul><li>Invest in proper naming. <br>Make sure the names of your files reflect their purposes. If naming is hard, it may mean that you try to call something that should never exist.</li><li>Write comments about the goals of your modules. <br>If the name alone is not explanatory, consider adding a paragraph or two about which set of problems a given module is supposed to solve.</li></ul><p>It should help you to notice when modules start doing something beyond their initial scope. Even when a change is small and reasonable, it will raise questions when somebody adds the method <em>trackAttendance</em> into the module <em>book-data-provider.</em></p><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Not as Productive as Others?]]></title><description><![CDATA[Highly effective colleagues are invaluable for keeping oneself sharp. But what if it works the other way around and makes you lose heart?]]></description><link>https://evgenii.info/faster-pacers/</link><guid isPermaLink="false">5fa8516864f3f12f5fb1e4f1</guid><category><![CDATA[Resilient Individuals]]></category><dc:creator><![CDATA[Evgenii Ponomarev]]></dc:creator><pubDate>Tue, 24 Nov 2020 20:30:00 GMT</pubDate><media:content url="https://evgenii.info/content/images/2020/11/wolfgang-hasselmann-mBccivEQvlk-unsplash--1-.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>This is another article about pacers &#x2013; people whom we use as an example to adjust our behaviour, mostly unconsciously.</blockquote><h2 id="surrounded-by-faster-pacers">Surrounded by faster pacers</h2><img src="https://evgenii.info/content/images/2020/11/wolfgang-hasselmann-mBccivEQvlk-unsplash--1-.jpg" alt="Not as Productive as Others?"><p>In this part, we will talk about problems that may occur when <em>you feel </em>that a lot of people in your team are much more productive than you. <br>In many cases, it doesn&apos;t lead to any problems &#x2013; people happily work together and achieve great results. But sometimes their mutual influence can be destructive, and people would feel demotivated and discouraged.</p><p>Several symptoms are indicating that you&apos;re affected by faster pacers:</p><ul><li>You feel guilty seeing that colleagues have achieved more than you</li><li>You are afraid of taking challenging tasks which can make you stuck for a while</li><li>You feel like you have to work longer hours to keep up with others</li></ul><p>Daily standups or any other form of sync with colleagues is the perfect time to diagnose this problem:</p><ul><li>Are you nervous about sharing your progress?</li><li>Do those meetings make you feel like you have not done enough? </li><li>Do you find it challenging to describe your results and plans?</li></ul><p>If any of these describes you, a closer look is needed.</p><h2 id="five-actions-to-solve-the-problem">Five actions to solve the problem</h2><p>The most popular advice I heard in this situation is to take it easy. It is normal to have somebody more productive than you, left alone the fact that nobody can be a top performer in all situations.</p><p>Even though I fully understand the reasoning behind this suggestion, I do not think it is helpful. If somebody is nervous about attending standups, you cannot fix it by suggesting not to worry.</p><p>Instead, you can face this problem, find out the reasons and prepare an improvement plan, even if the problem exists only in your imagination. Then, it&apos;s going to be up to you whether to follow this plan or not, but at least you will take matters into your own hands &#x2013; that alone can be sufficient to address most of the symptoms.</p><p>Let&apos;s talk about the five things which you can do to get out of this unpleasant situation. </p><h3 id="action-one-demystify-top-performers">Action one: demystify top performers<br></h3><blockquote>no two writers are the same, like snowflakes and fingerprints. No one will ever write in just the way that you do, or in just the way that anyone else does. Because of this fact, there is no real competition between writers. &lt;...&gt; Writing is a matter strictly of developing oneself. You compete only with yourself. You develop yourself by writing.<br><br>&#x2013; John McPhee</blockquote><p>In time, everyone develops their areas of expertise. No matter how broad or narrow they are, one is the same &#x2014; people are much more productive when their job overlaps with those areas.</p><p>Before bringing up your own expertise, I would recommend you you to think about your more productive colleagues. <strong>Every time they do something great, ask yourself what helped them to achieve those results.</strong></p><p>Something that could sound self-deprecating at first:</p><blockquote>Mark finished this giant feature for a week. That one would take more than a month for me!</blockquote><p>Can be rephrased and cleansed of magic:</p><blockquote>Mark finished this giant feature in a week because he&apos;s been building similar ones for the past three years.<br>He did more than ten last year &#x2013; now he&apos;s extremely good at it.</blockquote><p>Now you can see that Mark&apos;s fast pace didn&apos;t appear overnight &#x2013; it required years of deliberate practice. Moreover, you know that doing more things in this area can help you to close this gap.</p><p>That is not the only way of reframing achievements. It could be something like this:</p><blockquote>Mark finished it in a week because he wrote the whole system since the beginning and he knows every line of code by heart.</blockquote><p>or even this:</p><blockquote>... because he did not have the internet at home and spent all his free time working in the office.</blockquote><p>No matter the situation, your goal should be to stop seeing people as <em>just productive</em> and start noticed the reasons behind their results. Most of the time, those reasons are ordinary and achievable by anybody.</p><h3 id="action-two-find-your-comfort-zone">Action two: find your comfort zone</h3><p>Simply put, there are three types of activities:</p><ul><li>Something you enjoy the most</li><li>Something you are good at</li><li>Most important things for the company at the moment</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/Three-types-niche.png" class="kg-image" alt="Not as Productive as Others?" loading="lazy"><figcaption>Three types of activities at work</figcaption></figure><p>The intersection of all three circles is your <em>niche </em>in the team, but finding and expanding your niche deserves a separate article. For this topic, I will focus only on the comfort zone (highlighted in green).</p><p>Everybody has ups and downs, and you will have many periods of not being at your best.<br>One of the smartest things you can do is to prepare something that can give you a little boost when needed &#x2014; a type of work you like to be doing or an area where you can be very productive.</p><p>If you do not have a comfort zone right now &#x2014; build one:</p><ul><li>Familiarize yourself with plans of your team.</li><li>Pick an area which will require work in the future.</li><li>Start building expertise there to capitalize on it when the time comes.</li></ul><h3 id="action-three-define-expectations-and-track-achievements">Action three: define expectations and track achievements</h3><p>The easiest way to not meet expectations is is to have no expectations at all. No matter what you achieve, you can always find a room for improvement.</p><p>The simplest way of coping with that is to formulate your goals before you start working towards them. I find daily plans most precise and helpful for this purpose; here is one of my recent ones:</p><figure class="kg-card kg-image-card"><img src="https://evgenii.info/content/images/2020/11/image.png" class="kg-image" alt="Not as Productive as Others?" loading="lazy"></figure><p>The expectations were clear and realistic, but I ended up not finishing half of what I planned to do.</p><p>Was it a problem? No, because I knew that I had done more important things instead, and there was absolutely no reason to feel sad about my initial plan.</p><h3 id="action-four-keep-expectations-reasonable">Action four: keep expectations reasonable</h3><p>Sometimes results are noticeably small in comparison to goals:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-1.png" class="kg-image" alt="Not as Productive as Others?" loading="lazy"><figcaption>planned: 7; finished: 1</figcaption></figure><p>While this is a call to think about what can be improved, I would recommend checking your expectations for feasibility first.</p><p>There is a simple exercise to figure out if you are unrealistic in your estimations:</p><ul><li>Take some tasks your team plans to work on and imagine how much time each of them would take for you. Can you complete a particular task one day? In a week? Or maybe you can do five of those in an hour?</li><li>Write it somewhere.</li><li>When <em>other people</em> complete those tasks, check how their results match your estimations. <br>Were they working within their niches or tried something new? How did it impact them?</li></ul><p>This exercise is also helpful when your plans are unambitious and require correction:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-2.png" class="kg-image" alt="Not as Productive as Others?" loading="lazy"><figcaption>100% done!</figcaption></figure><h3 id="action-five-analyse-and-improve">Action five: analyse and improve</h3><p>Detailed plans can be beneficial even when everything looks good:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-3.png" class="kg-image" alt="Not as Productive as Others?" loading="lazy"><figcaption>Perfect plan and execution</figcaption></figure><p>Even though the result matched your expectation, a picky perfectionist can find some food for reflection:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://evgenii.info/content/images/2020/11/image-4.png" class="kg-image" alt="Not as Productive as Others?" loading="lazy"><figcaption>Digging deeper</figcaption></figure><p>I rarely use this method &#x2013; maybe once every two or three months, but it always helps to take control and find something I can change.</p><h2 id="prove-it-works">Prove it works</h2><p>At the beginning of this article, I mentioned that the best way of noticing this problem is to pay attention to your behaviour when you need to share your progress and describe the plans.</p><p>Feeling that you have not done enough can contribute to the demotivation, which will prevent you from working at your best, which will cause dissatisfaction of not achieving enough, which will incur even more demotivation, which will further decrease your productivity, which will make it even harder to get out of this loop.</p><p>The good news is that the actions above can help you to</p><ul><li>Understand if your expectations are realistic and how to adjust them if they are not</li><li>Find the quick way to get back on track after a period of dissatisfaction</li><li>Figure out what is the exact reason for dissatisfaction and how to improve it</li></ul><p>If anything, it doesn&apos;t leave too many reasons to worry.</p>]]></content:encoded></item></channel></rss>