<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Ovidiu Bute on Medium]]></title>
        <description><![CDATA[Stories by Ovidiu Bute on Medium]]></description>
        <link>https://medium.com/@ovidiubute?source=rss-a48617974b32------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*DwchziQTTLvf-s_Ls7H4PA.jpeg</url>
            <title>Stories by Ovidiu Bute on Medium</title>
            <link>https://medium.com/@ovidiubute?source=rss-a48617974b32------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 07:41:29 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ovidiubute/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[AI Writes the Code Now. Learning to Program Just Got Harder.]]></title>
            <link>https://medium.com/@ovidiubute/ai-writes-the-code-now-learning-to-program-just-got-harder-724068ee96bd?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/724068ee96bd</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[junior-developer]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Fri, 23 Jan 2026 07:13:57 GMT</pubDate>
            <atom:updated>2026-01-23T07:13:57.025Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jff2gXtydmScGImr1Wm2gg.png" /></figure><p>For a long time, writing code was the hard part.</p><p>You had to remember syntax, internalize patterns, fight the compiler, and slowly build an intuition for what worked and what didn’t. The feedback loop was slow, sometimes brutal, but it was formative. You earned every small win.</p><p>That’s no longer true.</p><p>Today, code is cheap. Abundant. Almost disposable. AI can write entire features, refactor existing systems, generate tests, and explain unfamiliar codebases in seconds. In many cases, it does this faster — and often better — than a junior developer.</p><p>This isn’t a prediction. It’s already happening.</p><p>And while most of the conversation has focused on what this means for productivity, hiring, or the future of engineering jobs, there’s a quieter and more uncomfortable question underneath it all:</p><p>How are junior developers supposed to learn now?</p><h3>The bottleneck moved</h3><p>AI didn’t just automate a task. It moved the bottleneck.</p><p>In the past, the limiting factor was writing code. Today, the limiting factor is understanding what the code does, why it exists, and how it behaves when things go wrong.</p><p>That distinction matters — especially for juniors.</p><p>If outputting code is the metric, juniors can’t compete with AI. And honestly, they shouldn’t try. That’s a losing game from day one.</p><p>But most learning paths, tutorials, and even job expectations are still optimized for the old world — the one where typing code was the primary skill to develop.</p><p>The result is a dangerous mismatch: tools that make it easy to skip the very experiences that used to build intuition.</p><h3>How I learned (and why it mattered)</h3><p>Years ago, I wrote an article called “An approach to learning programming languages.” The core idea was simple: learning a language isn’t about syntax. It’s about learning how problems are expressed and solved within a set of constraints.</p><p>What I didn’t emphasize enough back then is how much of that learning came from struggle.</p><p>Not heroic struggle. Not romantic suffering. Just… friction.</p><ul><li>Code that compiled but behaved incorrectly</li><li>Bugs that took hours to isolate</li><li>Refactors that broke things in subtle ways</li><li>Patterns that only made sense after misusing them</li></ul><p>I learned slowly. Often painfully.</p><p>I didn’t just learn what to write — I learned what didn’t work, and more importantly, why. That “why” became instinct over time. Not because I memorized it, but because I had felt the cost of getting it wrong.</p><p>That process wasn’t efficient. But it worked.</p><h3>What AI changes for juniors</h3><p>AI makes it possible — even tempting — to bypass that entire phase.</p><p>You can now:</p><ul><li>Generate working solutions without fully understanding them</li><li>Fix errors without knowing their root cause</li><li>Ship features without forming a mental model of the system</li></ul><p>And here’s the dangerous part: this doesn’t fail immediately.</p><p>In fact, it often looks like success. The code works. The task is done. The PR gets approved. But the cost isn’t gone. It’s deferred.</p><p>It shows up later:</p><ul><li>When the system behaves unexpectedly</li><li>When performance degrades</li><li>When trade-offs matter</li><li>When debugging requires intuition, not syntax</li></ul><p>At that point, the gap is painful — not because AI was used, but because it replaced thinking instead of amplifying it.</p><h3>Skipping the struggle has consequences</h3><p>There are a few things juniors risk missing if AI becomes a permanent crutch early on:</p><ol><li><strong>Mental models</strong></li></ol><p>Without wrestling with problems yourself, it’s hard to build a clear picture of how things actually work. You can recognize patterns without understanding them — which breaks down fast at scale.</p><p>2. <strong>Debugging instincts</strong></p><p>Debugging isn’t a skill you read about. It’s pattern recognition built from past failures. If you’ve never been lost in a system, you won’t know how to find your way out.</p><p>3. <strong>Taste</strong></p><p>Good code isn’t just correct — it’s appropriate. Taste comes from seeing many bad solutions, including your own. AI can give you “working,” but it won’t give you taste unless you already have a baseline.</p><p>None of this means AI is harmful by default.</p><p>It means using it too early, in the wrong way, changes what you learn.</p><h3>But let’s be honest: the struggle is real</h3><p>It would be easy to stop here and say: “So just don’t use AI.”</p><p>That advice is useless.</p><p>The reality juniors are facing today is very different from the one I learned in:</p><ul><li>Faster expectations</li><li>More competition</li><li>Less tolerance for ramp-up time</li><li>Constant comparison to AI-level output</li></ul><p>AI doesn’t feel like cheating. It feels like relief.</p><p>It helps with impostor syndrome. It reduces anxiety. It keeps you moving forward. And when you’re trying to break into an industry that already feels hostile, “struggling more” sounds like terrible advice.</p><p>That context matters.</p><p>So the answer isn’t abstinence. It’s intentional use.</p><h3>A better way to use AI while learning</h3><p>Instead of asking “Should juniors use AI?”, a better question is:</p><p>What should AI replace — and what should it never replace?</p><p>Some principles that actually work:</p><h4>Use AI after you form a hypothesis</h4><p>Try to reason about the solution first. Even a bad attempt counts. Then use AI to compare approaches, spot gaps, or validate assumptions.</p><h4>Ask “why”, not just “what”</h4><p>Generated code is cheap. Explanations are valuable. Use AI to interrogate decisions, not just produce results.</p><h4>Rebuild small things without AI — on purpose</h4><p>Not everything. Just enough to stay sharp. Toy problems, utilities, small services. This is where intuition still forms.</p><h4>Treat AI like a senior reviewer, not a generator</h4><p>A good senior doesn’t write everything for you — they guide, challenge, and correct. That’s the mental model that scales.</p><p>The goal isn’t to slow yourself down artificially. It’s to make sure understanding keeps pace with output.</p><h3>The new apprenticeship</h3><p>AI didn’t eliminate the need to learn fundamentals. It made it easier to avoid them.</p><p>That’s the trap.</p><p>The juniors who will struggle most aren’t the ones using AI — they’re the ones who never learned how to think without it. The gap won’t show up on day one. It will show up when systems get messy, ambiguous, and unforgiving.</p><p>The path I took still works. It’s just easier to skip now.</p><p>And skipping it feels fine — until it doesn’t.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=724068ee96bd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Enablers and gatekeepers]]></title>
            <link>https://medium.com/@ovidiubute/enablers-and-gatekeepers-922af5716728?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/922af5716728</guid>
            <category><![CDATA[values]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[teamwork]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Thu, 09 Apr 2020 11:14:53 GMT</pubDate>
            <atom:updated>2020-04-09T11:14:53.936Z</atom:updated>
            <content:encoded><![CDATA[<p>Teams should set and uphold a set of <strong>values</strong>. These come in different shapes and forms. Whether it’s being honest, transparent, responsible, or blameless. The list just goes on. Values are only important if they’re connected to behaviors, i.e. how you typically act regardless of the situation. Nobody behaves erratically over an extended period of time. Given enough self-reflection patterns emerge, and those patterns can be associated with values. I’d like to focus on just two of them in this article.</p><p>Throughout my software engineering career I kept hearing the word <strong>enablement </strong>thrown out a lot<strong>. </strong>Now, first of all, enabling someone to do something can have both positive and negative connotations. I think it’s only in this industry that it’s acceptable to say you’re going to enable someone. In any other context you’d get some weird looks just for saying that. So what’s special about an enablement team? Typically that means developing and maintaining components that other teams can benefit from.</p><p>If you ship software to customers you’re probably dependent on a continuous integration system. If it goes down, then you’re pretty much dead in the water. So someone, or a team of people, have to maintain it and keep it running close to 24/7. Can you imagine your company right now shipping without your CI system? If not, then the team that owns it is <strong>enabling </strong>you to do your job.</p><p><strong>Gatekeeping </strong>is a word you don’t really hear much about. A gatekeeper is someone whose job is to not let anyone in to whatever they’re protecting. The CI team is on the hook for its availability, they upgrade it from time to time, implement new features, fix bugs, apply security patches, etc. Given that everyone in the company depends on their work, it’s only natural to expect that they will always have a lot of planned work ahead of them. It’s common in a lot of companies that developers from other teams may be interested in helping them even though it’s not exactly their job to do so.</p><p>Imagine you’re passionate about CI systems and you notice a problem with your company’s setup. It’s something you know how to fix, so you decide to just go ahead and do it. After you’ve prepared your patch for submission there are really two different scenarios that could play out, and they have to do with values. Let’s see how the next steps would play out given two totally different teams, A and B, who uphold different values.</p><p>You talk to team A and they accept to review your patch. They suggest some improvements based on their experience, and work with you to deliver it. You gain more insights into what it means to actually be on the team. You missed an edge-case and they point that out to you. You go back and fix it and re-submit, and your patch is finally accepted. They also let you know what’s coming down the road in the next months in case you find other issues.</p><p>You send your patch to team B. You don’t hear anything back for a couple of days, and decide to reach out in person. They tell you they’re swamped with work and don’t have time to look at your proposal. You keep trying to convince them that it’s a small fix which greatly improves developer experience, but they don’t want to hear about it and finally tell you flat out that it’s not your job to think about CI. You give up and go back to work. Six months later they fix the issue but you only find out about it by accident.</p><p>Team B is what I’d call a <strong>gatekeeper </strong>team, even though their official mission is to enable, just like team A. They don’t let people in if they don’t have to. This team rarely benefits from the expertise of outsiders. It’s basically like comparing proprietary to open source. But while I’m sure you’d rather interact with the former team, it may be useful to consider their perspective first before passing judgement.</p><p>It’s clear that team A values working together. If you bring an improvement to the table, they’ll take the time to review it, let you know if they were already planning on doing the same thing, or point out flaws in your solution. Team B assumes that since you’re not on the team, you really have no business thinking about their line of work and you shouldn’t even try. But is team B’s behavior <em>objectively </em>bad? Like in all things software, it depends.</p><p>What if team B is maintaining a critical banking software component? If you were in their shoes, would you be so eager to let outside contributors in? What if your improvement contains a bug? If that happens it’s not your responsibility, you’re not on the team. They’re the ones who have to fix it. Or perhaps their software is so complex there’s no way anyone on the outside would be capable of contributing without a lengthy on-boarding process.</p><p>You should also seriously consider that team A has to <strong>allocate time</strong> to work with you, so they’re making a call that you’re worth investing in. If it turns out your potential improvement would be a liability down the road, then they’re not getting that time back. It’s gone.</p><p>Team B in contrast is more draconian with their time. They consider themselves (perhaps rightfully so) experts in their field, and their assumption is, unless you’re on the team, you do not have enough context to suggest any improvements. You should only report problems to them and they’ll eventually get around to fixing them.</p><p>These are certainly extreme positions and I made them out to be so it’s easier to conceptualize. In reality teams are both enablers and gatekeepers from depending on the situation. But values always prevail, and it’s important to understand that when you need to work with other teams.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=922af5716728" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Essentials of monorepo development]]></title>
            <link>https://itnext.io/essentials-of-monorepo-development-53992471fa8?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/53992471fa8</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[monorepo]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[large-codebase]]></category>
            <category><![CDATA[software-tools]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Tue, 04 Jun 2019 14:18:25 GMT</pubDate>
            <atom:updated>2019-06-09T17:38:01.497Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KFAI4h18fLLiSnls" /><figcaption>Photo by <a href="https://unsplash.com/@dreamevile?utm_source=medium&amp;utm_medium=referral">Raphael Koh</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>The word monorepo is a combination between “<em>mono</em>”, as in the Greek word <em>mónos </em>(in translation, <strong>alone</strong>) and an abbreviation of the word <strong>repository</strong>. A simple concept if taken verbatim: one lonely repository. The domain is software engineering so we’re referring to a home for source code, multimedia assets, binary files, and so on. But this definition is just the tip of the iceberg, since a monorepo in practice is so much more.</p><p>In this article I plan to distill the pros and cons of having every piece of code your company owns in the same repository. At the end you should have a good idea about why you should consider working like this, what challenges you’ll face, what problems it’ll solve, and how much you’ll need to invest in it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pCRpcpi3mLE2I-e4FOnp5w.png" /><figcaption>Relative interest in the term “monorepo” since 2004, source: Google Trends</figcaption></figure><p>The term itself, as visible in the chart above, looks to be as new as 2017. However it would be a mistake to think that previously nobody was storing all of their code in one place. In fact during my first job back in 2009, the company I worked at stored every project in a single SVN repository, one directory per project. Indeed you may well be able to trace this practice back even further. But how can we explain the recent explosive popularity, then?</p><p>The reality is that storing code in a single spot is not the main selling point. In the past years the major tech companies — Google, Facebook, or Dropbox have been showing off their way of working together within the same repository at massive scale. Organizations of tens of thousands of engineers collaborating within one repository is an awesome sight. And a difficult engineering problem. So difficult in fact that these companies invest a lot of money into tools and systems that allow developers to work productively. These systems in turn have solved problems that you may not even realize you had. This is what fascinates people during tech talks. This is what’s been driving searches since 2017.</p><ul><li>Front-end development at Google, Alex Eagle: <a href="https://medium.com/@Jakeherringbone/you-too-can-love-the-monorepo-d95d1d6fcebe">https://medium.com/@Jakeherringbone/you-too-can-love-the-monorepo-d95d1d6fcebe</a></li><li>Google monorepo presentation, Rachel Potvin: <a href="https://www.youtube.com/watch?v=W71BTkUbdqE">https://www.youtube.com/watch?v=W71BTkUbdqE</a></li><li>Scaling Mercurial to the size of Facebook’s codebase, Durham Goode: <a href="https://code.fb.com/core-data/scaling-mercurial-at-facebook/">https://code.fb.com/core-data/scaling-mercurial-at-facebook/</a></li></ul><p>I’ve identified a few core features that a Google or a Facebook vetted monorepo offers. This is surely not an exhaustive list, but it’s a great starting point. When discussing each of one of these points, I took into consideration what life looks like without them, and what exactly do they solve. Certainly in our field of work everything is a trade-off, nothing’s free. For every pro that I list someone will find use-cases that directly contradict me, butI’m OK with that.</p><h4>All your code, regardless of language, is located in one repository</h4><p>The first advantage of storing everything in once place may not be immediately obvious, but as a developer, simply being able to freely browse through everything is of great impact. It helps foster a sort of team spirit and is also a very valuable and cheap way to distribute information. Have you ever asked yourself what projects are in development at your company? Past and present? Curious what a certain team is up to? How have they solved a particular engineering problem? How are they writing unit-tests?</p><p>In direct opposition to the monorepo we have the <strong>multirepo </strong>structure. Each project or module gets its own separate space. In such a system developers can spend quite a bit of time getting answers to the questions I listed above. The distributed nature of the work means there’s no single source of information that you can subscribe to.</p><p>There are companies that have transitioned from a multi to a monorepo layout by following only this feature from my list. Such a structure should not be confused with the topic of this article though. I’d define it instead as a<strong> collocated multirepo. </strong>Yes, everything is in one place, but the rest of the features on this list are far more interesting.</p><h4>You‘re able to organize dependencies between modules in a controlled and explicit way</h4><p>The traditional, battle tested way of handling dependencies is by publishing versions to a separate storage system from continuous integration systems, or even manually, from development machines. These are versioned (or tagged) to make it easier to search later on. Now in a multirepo setup, each project has a set of dependencies of external origins (third parties) or internal, as in, published from inside the same company.</p><p>In order for one team to depend on another one’s code, everything needs to pass through a dependency management storage system. Examples of this are npm, MavenCentral, or PyPi. I said earlier that you can easily build a collocated multirepo just by storing everything in one place. Such a system is<strong> indirectly observable. </strong>Let’s examine why that’s important.</p><p>As developers, our time is split very unequally between reading and writing code. Now imagine having to debug an issue that has its root cause inside of a dependency. We can rule out third parties here, since that’s a difficult problem as it is. No, this problem occurs in a package published by another team in your company. If your project depends on the latest version, you’re in luck! Just navigate to the respective directory and grab a cup of coffee.</p><blockquote>“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.”</blockquote><p>― Robert C. Martin, <a href="https://www.goodreads.com/work/quotes/3779106">Clean Code: A Handbook of Agile Software Craftsmanship</a></p><p>More often though you might depend on an older version. So now what do you do? Do you try and use your VCS to read through the older code? Do you try and read the actual artifact instead of the original code? What if it’s minified, as is usually the case with JavaScript?</p><p>Contrast this with Google’s system, for example — since code dependencies are direct, as in, there are essentially no versions anywhere, one can say the system is <strong>directly observable</strong>. The code you’re looking at is pretty much your entire world. I say mostly because of course there are always going to be minor exceptions to this rule, such as external dependencies that would be prohibitive to host yourself. But that shouldn’t take anything away from this discussion.</p><p>While we’re on the topic of dependency management we should touch upon the subject of restrictions. Imagine a project where you’re able to depend on any source file you need. Nothing is off limits, you can import anything. For those of you that started their careers at least 10 years ago, this sounds like business as usual for the time. This is an almost complete definition of a <strong>monolith</strong>.</p><p>The name implies grandeur, scale, but more importantly, singularity. Practically every source file inside of a monolith cannot live outside of it. There’s a fundamental reason for this is relevant to our discussion: you don’t have an explicit and audit-able way of managing dependencies inside of a monolith. Everything is up for grabs, and it feels free and cheap. So naturally, developers end up creating a complex graph of imports and includes.</p><p>Nowadays practically everyone is doing microservices, there can be little doubt about that. Given sufficient scale, a codebase becomes a beast, as everything is inexorably linked to each other. I’m sure many developers will provide counter-arguments that monoliths can be managed in a clean, reasonable way without falling into this trap. But exceptions simply reinforce the initial statement. Microservices solve this by defining clear boundaries and responsibilities, and a monorepo is a natural extension of this philosophy. Typically modules offer a set of public exports, or APIs, and other modules are only able to use those as part of their contracts.</p><h4>Software modules reuse common infrastructure</h4><p>This is a topic that’s very near and dear to my heart. I’ll define <em>infrastructure </em>in this context, that of a software codebase, as the essential tools necessary to ensure productivity and code quality.</p><p>One of the reasons why I think betting your company on multirepos is a mistake has to do with a set of basic requirements any software engineering project should meet:</p><ul><li>A build system to be able to reliably produce a deliverable artifact.</li><li>A way to run automated tests.</li><li>A way to statically analyze code for common mistakes, potential bugs, and enforce best practices.</li><li>A way to install and manage third party dependencies, i.e. software modules which are external to your company.</li></ul><p>If you have your code split in multiple repositories, <strong>you need to replicate this work everywhere</strong>. Don’t underestimate how much work this involves! All of the features listed above require at the very minimum a set of configuration files which need to be maintained in perpetuity. Having them copied across more than two places basically guarantees you will always generate technical debt.</p><p>I know that some companies go to extreme lengths to minimize the impact of this. They’ll have their configurations bundled as scaffolding (<em>a la</em> create-react-app or yeoman), and use them to setup new repositories. But as we’ve seen in the section before this one, there’s no way to enforce that everyone’s on the latest version of these boilerplate dependencies! The amount of time spent upgrading each repository individually increases linearly in large codebases. Given sufficient scale, practically all published versions of an internal package will be depended on at the same time!</p><p>There’s a quote I absolutely love that relates to this conundrum:</p><blockquote>At scale, statistics are not your friend. The more instances of anything you have, the higher the likelihood one or more of them will break. Probably at the same time.</blockquote><p>— <a href="https://thenewstack.io/distributed-systems-hard/">Anne Curie</a></p><p>If you think distributed systems just refers to web services, I would disagree. Your codebase is an interconnected, living system. Tens, hundreds, or thousands of engineers are racing to get their code into production each day, all the while struggling to keep the build green and the code quality up. If anything, to me this sounds even scarier than a set of microservices :)</p><h4>Changes are always reflected throughout the entire repository</h4><p>This is highly dependent on the rest of the features. It’s one of the benefits that’s easier to understand through example.</p><p>Let’s say I work at a company that builds web applications for customers all around the world. Everything is organized into modules, as is exemplified below via the popular open-source project <a href="https://github.com/babel/babel/">Babel</a>. At this company we all use ReactJS for front-end work, and out of pure coincidence, all of our projects are on the same version of it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SURhmpcSs3ZlS4AfRpBqSA.png" /><figcaption>Babel’s myriad of modules: <a href="https://github.com/babel/babel/tree/master/packages">https://github.com/babel/babel/tree/master/packages</a></figcaption></figure><p>But the folks at Facebook publish the latest version of React and we realize that upgrading to it is not trivial. To be more productive, we’ve built a library of reusable components that resides as a separate module. All projects depend on it. This new React version brings lots of breaking changes that affect it. What options do we have for doing the upgrade?</p><p>This is typically where monorepo adversaries would shoot down the entire concept. It’s easy to say that we’ve worked ourselves into a corner and that the multirepo structure would’ve been a superior choice given the circumstances. Indeed in the latter case what we would do is just gradually adopt the new React version in our projects one by one, preceded by a major version upgrade of our core components module.</p><p>But I would say this creates more problems than it solves. <strong>A core dependency breaking change release creates a schism in your engineering team</strong>. You now have two cores to maintain: the new one, which is used by a couple, brave teams in a few projects, and the older one, still depended on by almost the entire company.</p><p>Let’s take this problem to a bigger scale for further analysis. Our company may have some projects which are still in production, but are just in maintenance mode, and don’t have any active development teams assigned to them. These projects will probably be the last ones to migrate, extending the time window in which you keep working on two cores at the same time. The old version will still receive bugs or security fixes even though it’s deprecated, as you can’t risk your customers’ businesses.</p><p>All of this is to say that <strong>a multirepo solution promotes and enables a constant state of technical debt</strong>. There are lots of migrations going on, modules that depend on older versions of other modules, and many, many deprecation policies which may or may not be enforceable.</p><p>Let’s now consider an alternative solution to the React upgrade problem. By having all of the code in one place, and dependent on each other directly, without versioning, we’re left with one option: we have to do all of the work upfront, in all modules simultaneously.</p><p>If that sounds like a scary proposition, I don’t blame you. It’s terrifying to think about, at first. However the advantage is clear: no migrations, no technical debt, less confusion around the state of our codebase. In practical terms, there is one obstacle to overcome with this solution — there may be hundreds, thousands, or millions of lines of code that need to be changed all at once. By having separate projects we avoid the sheer volume of work by doing it piece by piece. It’s still the same total amount of changes, but we’re naturally inclined to think it would be easier to do that over time, rather than in one push.</p><p>To solve this last problem large companies have turned to <em>codemods </em>— programmatic transformations of source code that can run at very large scale. There are numerous tutorials out there if you’re interested, but the gist of it is — you write code that first detects certain patterns in your source code, and then applies specific changes to it. To take our React example further, you could write a codemod that replaces a deprecated API with a newer one, and even apply logic changes if necessary. Indeed this is how Facebook recommends you migrate from one version of their library to the next. It’s how they’re doing it internally. Check out their <a href="https://github.com/reactjs/react-codemod">open-source examples</a>.</p><p>Viewed from this angle, a migration doesn’t seem as scary as before. You do all of your research upfront, you define how you want to essentially rewrite the affected code, and apply the changes more or less all at once. This to me is a robust solution. I’ve seen it in action, it can be done. It’s indeed amazing when it works and lately more and more companies are adopting it.</p><h4>Drawbacks</h4><p>The old adage of <em>“there’s no such thing as a free lunch”</em> certainly applies here, as well. I’ve talked about a lot of pros, but there are some cons which you need to think about.</p><p>Given that everyone is working in the same place, and everything is interconnected, <strong>tests </strong>become the blood of the whole system. Trying to make a change that impacts potentially thousands of lines of code (or more) without the safety net of automated tests is simply not possible.</p><p>Why is this any different from traditional ways of storing code? I’d say that versioned modules hide this particular problem, at the expense of creating technical debt. If you own a module that depends on another team’s code, by way of a strict version number, then you’re in charge of upgrading it. If you don’t have sufficient test coverage, you’ll err on the side of caution and simply <strong>delay upgrading </strong>until you’re confident the module doesn’t affect your own project. As we’ve discussed earlier, this has a serious long term consequences, but it’s a viable strategy nonetheless. Especially if your business doesn’t actually promote long term projects.</p><p>We mentioned the benefit of every contributor being able to access all of the source code in your organization. If we flip that around, this can also be a problem for some types of work. There’s no easy way you can restrict access to projects. This is important if you consider government or military contracts as they typically have strict security requirements.</p><p>Finally let’s consider continuous integration. You may be using a system such as Jenkins, Travis, or CircleCI, to manage the way your code is tested and delivered to customers. When you have more than one repository you typically set up one pipeline for each. Some teams even go further and have one dedicated CI instance per project. This is a flexible system that can adapt to the needs of each team. Your billing team may deploy to production once a week, while your web team would move faster and deploy multiple times a day.</p><p>If you’re considering moving to a monorepo, be wary of your CI system’s capabilities. It will have to do <strong>a lot of work</strong>. Simple tasks such as checking out the code, or building an artifact may become long running tasks which impact productivity. Google developed and runs its own custom CI solution, and for good reason. Nothing available on the market was good enough.</p><p>Now before you conclude that this is a blocker, I’d recommend you carefully analyse your project and the tools you use. If you’re using git, for example, there’s a myth going around that it can’t handle big repositories. This is demonstrably inaccurate, as best exemplified by the project that inspired git in the first place, the Linux Kernel.</p><p>Make your own research and see how many files and lines of code you have, and try to predict how much your project will grow. If you’re nowhere near the scale of the Kernel, then you’re OK. You could also make the point that git isn’t very good at storing binaries. <a href="https://git-lfs.github.com/">LFS </a>aims to solve that. You can also rewrite your history to delete old binaries in order to optimize performance.</p><p>In a similar vein, open-source CI systems are much more powerful than you think. Jenkins for example can scale to hundreds of jobs, dozens of workers, and can serve the needs of a large team with ease. Can it do Google scale? Absolutely not! But do you have <strong>tens of thousands</strong> of engineers pushing to production every day? The plateau at which these tools stop performing is so high, it’s not worth thinking about until you’re close to it. And chances are, you’ll know when you’re getting close.</p><p>And finally, there’s cost. You’ll need at least one dedicated team to pull this off. Because the amount of work is certainly not trivial, and it demands passion and focus. This team will need to, and I’m just summarizing here, build and maintain in perpetuity what is essentially a platform that stores code, assets, build artifacts, reusable development infrastructure for running tests or static analysis, and a CI system able to withstand large workloads and traffic. If this sounds scary, it’s because it is. But you’ll have no problems convincing developers to join such a team, it’s the type of experience that’s hard to accumulate by doing side-projects at home.</p><h4>In closing</h4><p>I’ve talked about the many advantages of working in a monorepo, the drawbacks, and touched upon the costs. This setup is not for everyone. I wouldn’t encourage you to try it out without first evaluating exactly what your problems and your business requirements look like. And of course, do go through all of the possible alternatives before deciding.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=53992471fa8" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/essentials-of-monorepo-development-53992471fa8">Essentials of monorepo development</a> was originally published in <a href="https://itnext.io/">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Books that every engineering manager should read]]></title>
            <link>https://medium.com/free-code-camp/books-that-every-engineering-manager-should-read-7a053e296d11?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/7a053e296d11</guid>
            <category><![CDATA[personal-development]]></category>
            <category><![CDATA[management]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[reading]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Fri, 19 Apr 2019 21:47:48 GMT</pubDate>
            <atom:updated>2019-04-19T21:47:48.642Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oFSvYTAQb1Ph7yVSzQPZVw.jpeg" /></figure><p>It’s a rare occasion that companies provide leadership training <strong>before</strong> you become a manager. A few days or weeks after what was probably one of the happiest days in your recent memory, the day you were offered a position outside of the individual contributor track, you find yourself with a million questions. You feel that you were tricked into signing something without reading the fine print.</p><p>That feeling you’re experiencing isn’t new, it’s just that you’ve all but forgotten it. It’s not knowing what you’re supposed to do. It’s being clueless. Because if you think years of writing software trained you to become a manager, research states the contrary. But it’s not the end of the world. Even though your company most likely doesn’t understand the need for formal management training, there is a plethora of information available to you that will make your job easier, and maybe even enjoyable.</p><p>When I became a manager I did what I typically do when faced with a challenge I know almost nothing about: I started reading. I’ve read a lot of books, some were good, a few of them were amazing. All of them shaped the way I do my job, and so I thought I would share them for other aspiring or active managers out there.</p><p>I’ve curated this list based on several factors:</p><ul><li>The books should cover a broad set of engineering management and leadership topics. It’s easy to find overlapping books. It is much harder to find a diversity of information when you’re very new to leadership.</li><li>They should be written in different eras. The software industry is constantly evolving. It doesn’t make sense to only read about what was happening in the 1980s or 90s.</li><li>Reading order matters a lot. Some books are more specialized than others. The information provided can be thought of as layers that stack on top of each other. If you’re inexperienced, you may start in the middle or the end, and that will basically ruin other books for you.</li><li>Finally, I put a hard limit of 7, just because I think this list is enough to build a foundation layer on top of which you can continue reading and maybe even doing your own research further on.</li></ul><p>But enough introduction, let’s see the list :)</p><h4><a href="https://www.amazon.com/Peopleware-Productive-Projects-Teams-3rd/dp/0321934113/ref=sr_1_1?keywords=peopleware&amp;qid=1554043754&amp;s=books&amp;sr=1-1">Peopleware: Productive Projects and Teams, by Tom DeMarco &amp; Tim Lister</a></h4><p>This should be mandatory reading for everyone. Period. No, not just everyone in software, everyone working in a private company should read this book. It’s amazing to me how pretty much all of the problems that people deal with it on a daily basis have already been solved. In the 1980s. If you read just one book from this list, let it be this one.</p><h4><a href="https://www.amazon.com/High-Output-Management-Andrew-Grove/dp/0679762884">High Output Management, by Andrew S. Grove</a></h4><p>Soon after you make the switch from the individual contributor track to the leadership track you will ask yourself a basic question.</p><blockquote>How do I measure my own success?</blockquote><p>You used to be able to answer that easily. Now that you’re writing code less and less, and dealing with team dynamics and people problems, how will you or your boss measure your progress and success? This book provides a now universally accepted answer: you are measured through the success of the people reporting to you. That is to say, if your team is successful, then you’re successful. I’m over-simplifying of course but that was my biggest take away from this book.</p><p>There are more insightful bits of information such as a walk-through of a production pipeline, how to run meetings, or how to conduct one on ones. This is a classic book that everyone should read even if they’re not interested in leadership roles. It’s that good.</p><p>I will say though that this book was written a long time ago. The impression I got was that leaders from that age were more authoritative than what you see in companies these days. This is not a critique, it’s a fair warning. You may read a few chapters and conclude that there’s no way anyone could get away with doing that in a company. There’s a certain nuance to the leadership style described in this book and it is important to understand it.</p><h4><a href="https://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996">Influence: Science and Practice, by Robert B. Cialdini</a></h4><p>An engineering manager’s job is to ensure their team has everything it needs to succeed. This means managing the interaction between multiple groups of people towards an agreeable outcome.</p><p>If you’ve ever tried to convince a friend to move from WhatsApp to Telegram and failed, you’ve made an attempt at exerting influence. You’ll need to do that basically every day, and in my experience, this is a very hard skill to learn. It takes a lot of practice, and there’s really no sandbox mode in which you can fail and it’ll be OK. You will try to talk to someone at some point into doing something, and you will fail, and you or your team will suffer for it.</p><p>This book is the definitive guide on how to approach the problem scientifically. A lot of managers seem to think they don’t need to learn how to influence others, particularly their direct reports, as rank is the ultimate influencer. Thinking that will keep you from ever becoming a great leader, in my opinion. Yes, you will probably overrule someone at some point and it will feel terrific while you do it. But if that person ends up hating you for it, you’ve just lost their trust and you will see the consequences of that later on.</p><h4><a href="https://www.amazon.com/Rapid-Development-Taming-Software-Schedules/dp/1556159005">Rapid Development: Taming Wild Software Schedules, by Steve McConnell</a></h4><p>This is another classic textbook that I wish everyone in software would read. If you’re currently in a company who’s <em>agile </em>and are struggling with unproductive meetings, poor quality code, team members that can’t get along with each other, or stakeholders who push you to leave the office late at night, you will find at least one solution within this book. It’s also a good leadership book as it describes, in what is probably my favorite chapter, a list of things you definitely should <strong>not </strong>do if you want to have a great team. I still refer to that chapter from time to time, it’s just really good and insightful.</p><h4><a href="https://www.amazon.com/Managing-Humans-Humorous-Software-Engineering/dp/1484221575/ref=sr_1_1?keywords=managing+humans&amp;qid=1554043292&amp;s=books&amp;sr=1-1">Managing Humans, by Michael Lopp</a></h4><p>I loved this book for its humor and insights into some of the biggest tech companies’ cultures. It doesn’t feel like a textbook compared to the others on this list, but that’s what makes it a great fit.</p><p>You need to understand that leaders are still human, they’re going to screw up, and the end result may be tragic or hilarious. Or both. That’s a very important lesson to learn, one that took me the longest time, to be honest.</p><p>It’s very easy to get caught up in theory while trying to learn how to be a leader. But reality often is so insane that no book can offer you the solution you need. You will end up in situations where you will do everything by the book, and people will still be unhappy. And that’s OK. The stories from Managing Humans will help you understand that.</p><h4><a href="https://www.amazon.com/Managers-Path-Leaders-Navigating-Growth/dp/1491973897">The Manager’s Path, by Camille Fournier</a></h4><p>What makes this book awesome is that it offers a clear and simple description of your responsibilities and goals at every step in the leadership ladder. Most companies don’t even have that information for their own leadership track.</p><p>It starts by describing what an entry-level leader should focus on, such as mentoring junior developers. It moves on to engineering managers, senior managers, and even covers what a VP of software should do. I personally have always wondered what a day in a VP’s shoes looks like, and if you have as well, this book is for you.</p><p>Beyond just taming your curiosity of what the upper echelons look like, I love this book because it is so realistic. There’s no utopian view of teams and processes here. It’s all ground in the experience of the author. That makes the information within highly applicable in your work environment.</p><h4><a href="https://www.goodreads.com/book/show/763362.The_One_Minute_Manager">The one minute manager, by Kenneth H. Blanchard</a></h4><p>I initially didn’t want to read this after I found it, but I’m glad I changed my mind about it. It’s basically a short story about a manager who is very good at his job, particularly in one area.</p><p>I won’t spoil it for you. The information you get out of this story isn’t particularly innovative. There are other books that dive into its topic in more detail. But there’s something really satisfying about it that I can’t really explain. It’s like a GitHub gist that solves a problem in under 100 lines of code.</p><p>You can be dismissive of it — there’s no way it could be that simple, right? Or you can read through it carefully and appreciate its simplicity, knowing that it’s not a generalized solution, but still good enough that it’s worth having in your toolbox. It is entirely possible you’ll read this book and think I’m exaggerating, but hey, it’s my list ;)</p><h4><a href="https://www.amazon.com/Radical-Candor-Kim-Scott/dp/B01KTIEFEE">Radical Candor, by Kim Scott</a></h4><p>I can count to 7 just fine, but I really wanted to offer this book as sort of a special addition to my list. I wouldn’t say it’s mandatory reading. Once you’ve gone through all the books above, you should pick this up for a very striking alternative view.</p><p>Basically, Radical Candor is a framework on how to relate to people. It’s not really related to software development. You can apply this anywhere, with your friends, with your family, it’s frankly very abstract in that regard.</p><p>The author, Kim Scott, has worked both at Google and Apple. She recalls some of her experiences while working there. I found those chapters to be extremely enjoyable, but do take them with a grain of salt. Some of the more recent reports in the media directly contradict some stories from this book. This is why I’m hesitant to recommend it to everyone.</p><p>The framework itself makes sense but it’s so hard to actually put in practice. I know that’s not the author’s fault. I wish the world would work in the way she describes, but I don’t think it ever will. Nonetheless striving to achieve even 50% of Radical Candor will make you a better leader. If you have the stomach for 100% then I’d like to meet you in person.</p><h4>Is that it?</h4><p>This list is a solid foundation for newbie managers or people who are thinking of becoming team leads or managers. There is so much more to learn. I would’ve appreciated a simple and short list like this myself when I made the step towards leadership. Hopefully you do as well.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7a053e296d11" width="1" height="1" alt=""><hr><p><a href="https://medium.com/free-code-camp/books-that-every-engineering-manager-should-read-7a053e296d11">Books that every engineering manager should read</a> was originally published in <a href="https://medium.com/free-code-camp">We’ve moved to freeCodeCamp.org/news</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The need for algorithms and data structures]]></title>
            <link>https://medium.com/@ovidiubute/the-need-for-algorithms-and-data-structures-c80b4f5fdbdc?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/c80b4f5fdbdc</guid>
            <category><![CDATA[personal-development]]></category>
            <category><![CDATA[developer]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[computer-science]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Tue, 26 Mar 2019 07:01:01 GMT</pubDate>
            <atom:updated>2019-03-30T21:04:36.912Z</atom:updated>
            <content:encoded><![CDATA[<p>Solving programming exercises that require algorithms and data structure knowledge has never been my strong point. Despite this fact, I’ve had a relatively successful career in software development for the past ten years. I never needed to be very good at algorithms because I never needed them at the companies I worked for. But the past few years have taught me a hard lesson.</p><p><strong>Computer science fundamentals is not something you should avoid or ignore.</strong></p><h4>Simpler times</h4><p>Let me back up a bit. In high school I was part of a class that was specialized in computer science and English — I’m Romanian, so foreign languages is something we need to get good at to succeed. The curricula was decent. We wrote code in Pascal, which wasn’t the best choice maybe compared to C or C++, but it wasn’t a hindrance in solving programming problems. I learned the imperative paradigm, sorting algorithms, data structures such as arrays, graphs, and trees, techniques such as <em>backtracking </em>and <em>divide et impera</em>, and more.</p><p>By the 12th grade, which is senior year in Romanian high school, I thought I had a good command of CS fundamentals. I enjoyed writing code, even though I was pretty bored of not being able to visualize output in any graphical way. This is what eventually drove me towards front-end development years later.</p><p>I never participated in <a href="https://en.wikipedia.org/wiki/International_Olympiad_in_Informatics">olympiads </a>or other competitive events. Somehow, even though I liked programming, I didn’t see the point of them. Thinking back I now realize this was a mistake, and it probably affected my career more than I’d care to admit.</p><p>I took an entrance exam and was admitted to the <a href="http://csie.ase.ro/home">Academy of Economic Studies in Bucharest</a>, majoring in computer science and economics. This particular bachelor’s degree helped me with knowledge regarding several programming languages such as C++, Java or C#, however in the area of algorithms and data structures, the curricula was pretty light. I would say it was on par with senior high-school year. Which basically for me meant that I couldn’t progress just by doing course work.</p><p>In my 2nd year of university I decided to get a part-time job as a software developer in test. I wasn’t really applying anything I had learned in school though (what a shocker, right?). I continued my career at a few startups, and I gradually forgot everything I ever knew about algorithms and data structures. My jobs didn’t really demand it. The tasks were always related to using frameworks, writing code without any performance constraints, or maintaining legacy systems. But I was growing as a developer. I was being promoted, praised in yearly reviews, and I got good at applying design patterns and writing clean, testable code.</p><h4>Success</h4><p>How exactly do you measure your success as a software developer? If you work for a company that produces software, and you’re constantly solving your tasks ahead of schedule, getting promoted up the individual contributor track, would you think you’re actually stagnating?</p><p>Yet most business software development is built in such a way that developers are interchangeable and the ramp up is cheap and fast. This is advantageous for companies, and enthusiastic for most developers, especially junior ones. You don’t need a CS degree to write code using frameworks such as Spring or Django. You just need to be able to read documentation, use a modern IDE, and get through some on the job training on how to write tests and contribute to the project.</p><p>I have never once had to think about the complexity of the code I was writing. Most systems I was working on did not have that much traffic, and the ones that did — they worked around it by throwing money at the problem via over-provisioned servers.</p><p>I stated that CS fundamentals is a topic you absolutely need to get good at. Let me explain why. There are limits to how far you can go career wise without ever learning seemingly boring stuff like what is a self balancing tree, or what it means for a sorting algorithm to be stable. I think the fact that you can progress so far and so quickly in software without this knowledge is a big problem. It can lure you into a sense of false security which will hit you painfully at some point.</p><p>For me that point was when I started working at <a href="https://hootsuite.com/">Hootsuite</a>. The nature of the problems I faced immediately after I was hired were exponentially more difficult than anything I’ve ever seen before. Performance was at the heart of everything we had to do. And this is where algorithms and data structures become increasingly relevant. You can certainly take a matrix sized 50x1000 and loop through all of it once per each item you’re searching for. This is made insanely easy by using libraries such as <a href="https://lodash.com/">Lodash </a>or <a href="https://underscorejs.org/">Underscore</a>. You may even get away with it in most cases. But if you’re dealing with a large piece of software, with lots of things happening all at once either on screen or behind the scenes, in your back-end code, efficiency is mandatory. Caring about it will also distinguish you from other developers.</p><p>Working in a performance oriented team is extremely challenging, but it can also be the most rewarding experience in your career. I figured that out eventually, but I spent years in companies that never pushed me hard enough to become a better software developer. I spent time reading and applying design and testability patterns, which certainly helped. But the reality is you can have a beautifully architected system that just isn’t scalable. And you can’t Google how to get there. You can’t Stack Overflow your way to writing efficient code.</p><p>After I was hired I decided that I needed to freshen up my CS fundamentals fast. So I devised a plan.</p><h4>The Goal</h4><p>I’m still a bit old fashioned when it comes to studying material, so I bought “<a href="https://algs4.cs.princeton.edu/home/"><em>Algorithms Fourth Edition</em></a>”, by Sedgewick &amp; Wayne. I wish I had this book when I was still in school. It is very different than any textbook I’ve ever used. It doesn’t just force feed you algorithms, it offers so much context around why we even have algorithms, or how to measure them. It also presents a real world problem before presenting the solutions, which is contrary to pretty much how my entire education system was (and still is) designed. By structuring the chapters like this I finally understood the importance of starting with a basic algorithm, which may not be very good, and evolving it until you get to an optimal solution. This is also how major companies run their technical interviews.</p><p>I felt pretty good as I progressed through the chapters, there were a lot of things that I had previously read but forgot, and there were certain algorithms which I had never even heard about. It was starting to make sense, and I was happy with my progress.</p><p>Then I decided that I needed some coding practice. It’s one thing to read about a tree, but quite a different one to be able to solve a programming problem involving one. I discovered <a href="https://leetcode.com/">leetcode.com</a>, a competitive programming platform which is free to join (with an optional premium tier) and offers hundreds of problems.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ra5JGXrmr7YoqOuxICYf-A.png" /><figcaption>Merging intervals in JavaScript</figcaption></figure><p>I decided on the spot that I had to set a goal for myself, otherwise this would just end up like my list of GitHub repositories. Exciting at first, but ultimately abandoned in my endless to-do list of ideas and projects. I thought I had to make the goal very easy to measure, and ambitious enough such that it would force me to work hard enough to achieve it.</p><p>So I settled on solving 100 Leetcode problems by mid 2019. This number felt high enough that I’d need to work for it, but still low enough such that I didn’t have to go out of my way and pull all-nighters. The only time I could work on this was from home, and that pretty much means just the weekends.</p><h4>Tracking</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HK6IXyvejD0XtxZvJYk4Uw.png" /><figcaption>Leetcode’s stats page</figcaption></figure><p>Leetcode makes it trivial to measure your progress with a pie chart of completed versus total number of problems. But the profile page is a bit hidden, and you need an account to be able to even access someone else’s stats. This was mildly annoying, but the second problem I found was much worse. Your solutions in the platform are not easily searchable after the fact. You need to either have the code in your browser’s local storage, or go to the submissions page of each problem and find it. As I was still struggling with problems, I needed a fast way to go back to a previously solved solution for help, and Leetcode wasn’t making this easy.</p><p>So I decided I was going to host all of my solutions in a GitHub repository. I figured it was OK to do that since I would only be publishing the accepted solutions source code, not the problem description, which rightfully belongs to Leetcode under a license.</p><p>The repository is located at <a href="https://github.com/ovidiubute/leetcode-js">https://github.com/ovidiubute/leetcode-js</a></p><p>All of the solutions are located in a single directory, and I used a simple naming scheme to track problem IDs and titles. This maintains a certain tidiness and it also makes it easy to search for solutions directly in GitHub.</p><p>I used JavaScript as my language. This could be an article topic on its own, as there are many caveats to using JS for this type of work. But it’s been too long since I’ve written C or Java and I write code in TypeScript every day at work, so it seemed like a logical choice. The main drawback is you have none of the advanced data structures such as HashSets, Heaps, or Queues. When faced with a problem that requires them you’re pretty much on your own and have to re-implement them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hGKFWRsWFVB2mBudbIcq3A.png" /><figcaption><a href="https://github.com/ovidiubute/leetcode-js">https://github.com/ovidiubute/leetcode-js</a></figcaption></figure><p>I also implemented a badge on the repository’s Readme that tracks progress as a percentage. This was a fun little side project that meant learning how the <a href="https://shields.io/endpoint">shields.io endpoint system</a> worked. Whenever I contribute a solution, I run a Node.js program that updates a JSON file in my repo. This is then accessed by shields.io and their systems read the badge, text, colors, and percentage, rendering an SVG similar to the one below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/422/1*_X9e1jQ_3oQga9YeKLPEbw.png" /><figcaption>My custom GitHub Leetcode progress badge</figcaption></figure><h4>Results</h4><p>I hit my milestone way before my target deadline. This was both good and bad for me, as on one hand, I was completely stocked that I was able to solve 100 problems given my years of neglecting algorithms and data structures. But on the other hand, I had aimed way too low, which felt a bit disappointing.</p><p>Setting a tangible goal forced me to take this task seriously. Measuring it made it easy and also comforting as I could see my progress from one week to another. However I made two mistakes when defining the goal. I didn’t think to split the goal by difficulty of the problems. Leetcode offers problems in three difficulties, and I gamed my own system by solving a lot more easy problems than medium, or difficult. Granted, it’s ironic for me to say that given that when I started a few months ago, the easy level felt impossible. I had forgotten so much from school that it felt like my goal was a cruel joke I had made myself suffer through.</p><p>Gradually it got better, though. Had I not been so dismissive of my own skills, I would’ve set a harder goal. Something like solve 80/30/15 problems, split by difficulty. I also should’ve pushed myself for a tighter deadline.</p><p>Did it matter that I spent this time remembering things that I only rarely use in my day to day job? Well, from what I can tell, I’m much more attuned to how my code performs now. Writing efficient code is something you don’t just get good at by solving a few coding tasks, but the difference between my mindset now and how I used to think six months ago is significant.</p><p>I also appreciated the exercise. Coding is not just thinking about ways of solving problems. There’s a mechanical element to it. By writing a lot of code your muscle memory improves, leading to faster typing of repetitive patterns. You shouldn’t have to think about how to traverse the diagonal of a matrix, or how to remove duplicates from an array.</p><h4>Recap</h4><p>So I went from studying computer science in high school, to sort of continuing to study it in university, to rarely applying what I had learned on the job, to a new job demanding I get good at it again. A typical week-end day for me looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p0ePqR-6T0sPujym403jhA.png" /></figure><p>But I absolutely enjoy working on it! I got into programming because of the exhilarating feeling of asking a computer to do something. At first it was printing text on the screen. Then answering an HTTP request. Then animating a sprite on a mobile phone. The feeling is still there, but it took me a long time to realize that everything is built on top of the same foundation. Languages and frameworks are transient. They change, they die, they get replaced. As a junior developer I was convinced that keeping up with these changes was a sure way to achieve success. I worked for many companies that rewarded this behavior. I had never worked for one that rewarded being good at the foundation layer. Now I do and I need to catch up on some wasted time.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c80b4f5fdbdc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Thoughts on migrating to TypeScript]]></title>
            <link>https://medium.com/hootsuite-engineering/thoughts-on-migrating-to-typescript-5e1a04288202?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/5e1a04288202</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[refactoring]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Thu, 27 Dec 2018 19:37:00 GMT</pubDate>
            <atom:updated>2019-01-03T07:35:03.354Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/364/1*4qsnMc9hrlF-KpgsTfuLiA.png" /></figure><p>I’m going to go into the why and how of migrating a large JavaScript code base to TypeScript. Our team has concluded a fifteen month long journey of revamping our front-end stack. To up the difficulty, we had to did this in parallel with delivering new features to our customers. At the end I will also talk about whether it was worth the effort or not, and how it affected our development.</p><h3>Start with “why?”</h3><p><a href="https://hootsuite.com/pages/analytics">Hootsuite Analytics</a> is a single page app built from the ground up in JavaScript. We rely on the <a href="https://reactjs.org/">React</a> library, of which we were very early adopters. At a very high level, our app consumes data from our set of backend APIs. It then transforms that data into several types of visualisations. We render rich tables that display social media posts, charts, graphs, maps, and more.</p><p>Over time our app has grown quite a bit, and is now sitting somewhere at 150 thousand lines of code. At Hootsuite we invest a lot in the technical aspects of our products. We do that by always assessing whether what we are doing is sound from a technical point of view. Any major project must start from a problem definition, so let’s talk about what were our technical challenges.</p><p>JavaScript is a difficult language to model data transformations in. It is a dynamic language, and, without going too much into the specifics of what that means, it requires developers to make a trade-off. They don’t need to specify what data looks like before hand, which makes initial development very fast. The flip side is that, as a project grows both in lines of code and number of contributors, it becomes exponentially more difficult to reason about the data flow throughout the various layers of the application.</p><p>This problem is somewhat compounded by using React. Since it is built on functional programming principles such as immutability and composition over inheritance, it encourages developers to treat components as small, reusable functions. In a medium or large application it’s typical to have hundreds, thousands (or even <a href="https://github.com/facebook/react/issues/9463#issuecomment-295643228">tens of thousands</a>) of components. Data can flow through tens of components at a time.</p><p>Imagine having to read through a tree of a dozen React components with no information on what the data looks like at each step. This was what the world looked like in 2015 to us. Now, as astute readers will point out, React offers a feature that helps with this: <a href="https://reactjs.org/docs/typechecking-with-proptypes.html">PropTypes</a>. But they are optional and quite difficult to maintain. We didn’t use them from the beginning, we adopted them a year later and started adding them to new components. In our experience they did not deliver enough information to balance the maintenance effort required. There are also more practical concerns: most IDEs do not attempt to parse PropTypes to offer hints, you need tools to enforce their correctness, and it is a limited type system, not robust enough for our needs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gAPtMDxo2047PtcYP1d9hQ.png" /><figcaption>VSCode trying to be useful but lacking context to provide relevant autocomplete</figcaption></figure><p>Another problem we experienced was that, due to a lack of information about the data flow, it was difficult to perform basic refactoring. Moving files around, splitting large components into smaller ones, or renaming files — these operations were both time consuming and risky. Our team embraced unit-testing since the very beginning, so we could not crash our app by moving files around. But it was still time consuming.</p><p>This led to an interesting realisation: developers rarely refactor code unless it is cheap and safe to do so. The reality was that our code base was in a dire <a href="https://www.techopedia.com/definition/27913/technical-debt">technical debt</a> state. Developers were wary of making major changes for fear of breaking functionality or spending too much time on what they initially thought to be basic tasks.</p><p>The lack of code completion and contextual hints was the third, and most annoying problem of all. Myself and a few members of our team come from a back-end development background, working with strongly typed languages such as Java or C++. I still remember the first time I wrote JavaScript code in an IDE. As I was working, all I could think of was…</p><blockquote>Wow, writing code without any IDE suggestions is hard!</blockquote><p>You do get used to it after a while, but in my opinion, you will never be quite as productive as in typed languages. There is too much going on at any given moment within a JavaScript program. There are too many possibilities, data can have any shape and can mutate at any time without warning.</p><p>So to sum it up, we were facing three major challenges:</p><ul><li><strong>Difficulty in following the data flow</strong></li><li><strong>Expensive refactoring</strong></li><li><strong>Lack of contextual information in IDEs</strong></li></ul><p>We decided to start the search for a solution, and we realised we had to go outside the bounds of the JavaScript ecosystem to find one. We took a look at what the open-source community offered as options for front-end development. It is an amazing time to be building web apps as there are many, many choices beyond JavaScript.</p><p>We did have a very critical restriction. Hootsuite is a business, millions of customers across the world depend on us, so we couldn’t stop development while we migrated our code to another language. The migration had to be gradual. We would write new code in our new language, while slowly rewriting older code, without interfering with the product roadmap we had to ship. So we made a shortlist of options, and debated them one by one.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*det1Qq0ENAzVLO_l6nI3Gg.png" /><figcaption>Hootsuite Analytics Report</figcaption></figure><p>One of the first languages we took a look at was <a href="https://elm-lang.org/">Elm</a>. Bogdan Zaharia, a member of our team, is a huge proponent of functional programming in its purest form. He was the one that introduced this language to our team. Elm was inspired by Haskell, and offers a robust, typed alternative to JavaScript. While attractive, we couldn’t make the transition to it easily. We could not find a simple way to gradually adopt Elm into our code base. Additionally, it’s not very newbie friendly. It requires developers to understand some non-trivial concepts from the functional programming world. We also had to consider how easy it would be to onboard new developers in our team to Elm. After weighing in all these drawbacks, we decided to keep looking.</p><p>Other options that we analysed:</p><ul><li><a href="https://www.dartlang.org/">Dart</a>: this language is becoming popular again due to Google investing in <a href="https://en.wikipedia.org/wiki/Google_Fuchsia">Fuchsia</a>. Dart is its de-facto UI tech stack. The lack of a transparent roadmap and uncertain future meant a very clear no go.</li><li><a href="http://www.purescript.org/">PureScript</a>: this is Haskell for front-end development. Same arguments as using Elm. To be honest, it has an even steeper learning curve than Elm.</li></ul><p>We had two candidates left on our list: <a href="https://flow.org/"><strong>Flow</strong></a> and <a href="https://www.typescriptlang.org/"><strong>TypeScript</strong></a>.</p><p>It was not easy to choose between these two given their similarities. We invested some time in research spikes to see first hand what development looked like in both cases. What we found was that Flow was more difficult to set up than TypeScript, and that the developer experience felt sluggish. This has improved though in the last year, so if we were to analyse them again today, this wouldn’t have made such a big difference.</p><p>Both type systems are solid, yet very different. TypeScript uses a structural<em> </em>type system. Flow’<em>s</em> system is both structural <em>and </em>nominal. The difference is key to how they integrate with the greater JavaScript ecosystem. I will summarise what that means, but if you’re interested, <a href="http://wiki.c2.com/?NominativeAndStructuralTyping">this article</a> goes into much more depth. A nominal type system implies that two types, <em>Foo </em>and <em>Bar</em>, are never equal, regardless of their definitions. TypeScript, using only the structural alternative, doesn’t care about what the types are called. It analyses their structure and determines whether it should act like they are equal. In practice this means writing code is less demanding on you. You can easily reuse types and interfaces and you can even define them inline without naming them.</p><p>We also looked at the communities around these two projects. Flow is a language that, at least a year ago when we ran this analysis, was being driven by Facebook in a very closed manner. Development was never transparent, there was no public roadmap, and very few people outside of Facebook were contributing to the project. TypeScript, in contrast, embraced open-source development since moving to GitHub a few years ago. They keep an up-to-date roadmap, accept outside contributions, and generally keep a very close relationship to the community. <a href="https://twitter.com/ahejlsberg?lang=en">Anders Hejlsberg</a>, a Microsoft fellow and chief architect, speaks at conferences (such as <a href="https://tsconf.io/">TSConf</a>) throughout the year, keeping everyone in the loop on what features are coming next and how the project is performing.</p><p>So as you might have guessed, we chose to go with TypeScript. This was a pretty long intro on why we did it, but it serves as a good template for other teams when deciding to change tech stacks. I’ve seen too many teams do tech switches by starting with the “how”, rather than the “why”. Rather than stating that your team wants to switch over to another language (or stack), start by understanding your problems.</p><ol><li>What are our current difficulties?</li><li>How do we prioritise them?</li><li>Are they solvable within the current stack?</li></ol><p>You should always go through these steps so that you may reach the best possible solution.</p><h3>Continue with “how?”</h3><p>At this point we had reached a consensus that we wanted to begin rewriting our code base in TypeScript. The first step we took was to ensure that we could actually write TypeScript code.</p><p>We built Hootsuite Analytics on top of modern software practices. We have a continuous integration pipeline that helps us deliver code to production only after changesets pass several checks:</p><ul><li>Linting</li><li>Formatting (using Prettier)</li><li>Unit-tests</li><li>Code coverage</li><li>Acceptance tests</li></ul><p>We have three different environments: development, staging, and, of course, production. When thinking about adding TypeScript, we had to make sure it didn’t interfere with the pipeline. And we also had to make it seamless for developers.</p><p>I won’t go too much into the specific technical details of how we integrated TypeScript into our code base. There are far too many excellent articles and tutorials out there that describe the process better than I can, and I suggest you check them out:</p><ul><li><a href="https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html">https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html</a></li><li><a href="https://medium.com/pleo/migrating-a-babel-project-to-typescript-af6cd0b451f4">https://medium.com/pleo/migrating-a-babel-project-to-typescript-af6cd0b451f4</a></li><li><a href="https://medium.com/@clayallsopp/incrementally-migrating-javascript-to-typescript-565020e49c88">https://medium.com/@clayallsopp/incrementally-migrating-javascript-to-typescript-565020e49c88</a></li></ul><p>I will, however, describe our philosophy, our pain points, and what we’ve learned along the way.</p><p>One of the most important decisions we made at the beginning was to enforce <a href="https://blog.mariusschulz.com/2017/06/09/typescript-2-3-the-strict-compiler-option"><strong>strict mode</strong></a>. Strict mode is a combination of several compiler flags that, when turned on, perform extra type safety checks on your code. I would recommend any team that starts a TypeScript project to use strict mode from the get-go. Moving code written in non-strict mode over to strict mode is actually really difficult, and you’ll save yourself time in the long term by enabling this mode early.</p><p>One of the potential downsides of strict mode is that you can no longer import JavaScript code unless it provides a TypeScript declaration file. If you’re not familiar with that term, it’s like a C/C++ header. You need to write types for your data structures, classes, methods, and functions. A lot of projects include declaration files written by the maintainers. However we depended on a few that did not.</p><p>To solve this issue the community has done an amazing job with the <a href="https://github.com/DefinitelyTyped/DefinitelyTyped">DefinitelyTyped</a> repository, filling in for authors who have neither the time, interest, or expertise to write and maintain their own declaration files. We didn’t have any problems finding declarations for all of our dependencies after consulting it. Unfortunately we did run into a few problems upgrading them down the line. For reasons better explained <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/issues/7719#issuecomment-299393764">in this GitHub issue</a>, it can be challenging to find the right combination of versions. With projects such as <a href="https://redux.js.org/">Redux</a> (which we use and love), there’s an entire ecosystem of dependent projects, each with their own community driven declaration files. You usually need to upgrade all of them at once so as you can imagine, it can get frustrating.</p><p>To make matters worse, our app depended on a few in-house written and hosted packages, and they were all JavaScript. As a result importing them would break under strict mode, so we had a new problem on our hands. We had two options: either ignore the compiler errors (using @ts-ignore), or write the declaration files ourselves.</p><p>To not get stuck on this particular problem we ignored the import errors. We made a commitment to go back and write the declaration files (which we did, in time). I would recommend this approach to other teams as well, since if you’re just getting started with TypeScript, it’s a strain to write declaration files. Depending on how dynamic your APIs are, it could require intricate knowledge of the type system to finish. In the early adoption days when you’re getting the hang of things, you don’t want to be spread too thin.</p><p>Another challenge we had was linting. During our research we found two ways of linting TypeScript code: <a href="https://palantir.github.io/tslint/">TSlint</a>, a tool developed in-house at Palantir and subsequently open-sourced, and <a href="https://eslint.org/">ESlint</a>, the de-facto linting tool for JavaScript, together with <a href="https://github.com/eslint/typescript-eslint-parser">typescript-eslint-parser</a>.</p><p>We were already using ESLint in our pipeline, so our solution was to adopt a dual setup of ESlint to check JavaScript code, and TSlint for the new code. This felt right at the time since we thought about using the best tools for the job, but it brought a lot of downsides. We had to maintain two linting configuration files, two lists of rules, we had more dependencies we needed to keep track of, and we had two different linting outputs whenever there were errors.</p><p>Fast forward a couple of months we consolidated on ESlint for checking both JavaScript and TypeScript code. We accepted that, even though we lost some more advanced TSlint specific rules, it was not worth the effort of keeping both tools in our pipeline.</p><p>With tooling solved, we had to decide how to approach the code migration. Like I mentioned earlier, there would be no huge one time rewrite, we had to continue supporting our product roadmap, which meant delivering features and maintaining the application. We ended up with two rules that would guide our work.</p><ul><li>New code must <em>always </em>be written in TypeScript. No exceptions.</li><li>The code base will be treated as a copy-on-write data structure. If your task requires you to change JavaScript code, you need to rewrite it.</li></ul><p>As you can imagine, this didn’t always go smoothly. While writing new code was fun in TypeScript, importing legacy code remained an issue. Our first few pull requests were unusually large, and thus difficult to peer review. We tried to get to the bottom of the problem during our weekly JavaScript Guild meetings. It turned out that often developers needed to go into the legacy modules and fix problems that were just then being uncovered by the compiler. So pull requests that should’ve included one or two files were now hundreds or even thousands of lines in size because of our second migration rule.</p><p>We still wanted to uphold the vision, so we decided to take a look at the major offenders that were causing the large changesets. These were mostly older core React components or utility functions. These modules had been reused across the entire project, so changes made to them cascaded across the entire codebase. Rather than spend time upfront in rewriting them, which would have potentially caused delays in our product roadmap, we wrote declaration files for them. This helped a lot in reducing the size of subsequent pull requests. We delayed rewriting these modules until we were further along with the migration.</p><p>If your team does this, word of warning — you are, in effect, adding <strong>technical debt</strong>. You will need to maintain these files, which is not simple. It is very easy to change JavaScript code without updating the corresponding declaration files. Your app will compile but crash and burn at runtime. In practice, we very rarely had this problem, due to our decent unit-test coverage. Try not to keep the declaration files forever, though, and commit to rewrite your code at some point.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OatljkoWxfBZzz8eyBBhkA.png" /><figcaption>Better — autocomplete for React props, and documentation on React internals!</figcaption></figure><p>Of course we also <em>shipped</em> some bugs in production during rewrites. The amazing value in type systems is that you can catch so many bugs at compile time instead of runtime. That was never the case for us before the migration, though, so we had a lot of lingering bugs waiting for the right conditions to manifest themselves.</p><h3>Was it worth it?</h3><p>The best measure of success that we have so far is the number of production deployments. We built our pipeline in such a way that any merged pull requests trigger a production release. This means we push new releases out to customers on a daily basis. Our hunch was that, due to the uncertainty that governed our code base before the migration, we never deployed as often as we could have. And we were right.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lnikyf8B3gbUxxni2YoUPA.png" /><figcaption>The number of production deployments per work day</figcaption></figure><p>The number of times we release to production has doubled compared to 2017.</p><p>It’s never easy to attribute statistical success, so I am going to eliminate the usual suspects that may have influenced this chart.</p><p>The number of front-end developers on our team has largely remained constant. So while there is some correlation between headcount and production pushes, it is not enough to explain the trend.</p><p>We did not put Analytics as a product on pause, our roadmap has been a constant flux of features, so that’s also out of the question. There are some seasonality influences. We enjoy a peaceful code freeze during Christmas holidays each year. During that time we cannot push any code to production. This explains the low activity at the end of each year.</p><p>We are still early in analysing the impact this migration has had on our code base. Quantitative data suggests we are shipping more often than ever before. Qualitative information is also very valuable. Our developers love the contextual information that the types offer (especially now that everyone in the team uses <a href="https://code.visualstudio.com/">VSCode</a> or WebStorm). They are writing less tests because bugs are now uncovered during compilation. They are generally happier about the quality of their code. On-boarding new developers into the project, which historically has been very difficult, is now faster. We plan to do another check-up in six months and see if these initial results still hold up.</p><p>You would think that this migration affected our product roadmap, due to all the refactoring work. That was not the case for us. We managed to deliver all our projects on time. The caveat of this is that at Hootsuite we never work under the pressure of fixed, non-negotiable deadlines. I can also attest to the fact that certain features we delivered would have taken much longer had we needed to work in JavaScript. Parts of our code base are approaching four years of age. New features around them would have certainly driven up estimations.</p><h3>In closing</h3><p>This migration would not have been possible without the passion, grit, attention to detail, and hard work by our developers in Hootsuite’s Bucharest office. I’d like to thank <a href="https://github.com/zaboco/">Bogdan Zaharia</a>, <a href="https://github.com/flaviusone">Flavius Tîrnăcop</a>, <a href="https://www.linkedin.com/in/gabriel-ilie-a2429364/">Gabriel Ilie</a>, <a href="https://www.linkedin.com/in/sergiubuciuc/">Sergiu Buciuc</a>, <a href="https://www.linkedin.com/in/sinziana-nicolae-80516a5b/">and Sînziana Nicolae</a> for keeping the TypeScript dream alive, and in general for an amazing past year. I’m happy and proud to be working on a team that can get motivated when faced with a project like this. Looking forward to our next achievements.</p><p>Have you ever migrated a code base to another language? Share your experience in the comments, and let us know if you found this article useful.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5e1a04288202" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hootsuite-engineering/thoughts-on-migrating-to-typescript-5e1a04288202">Thoughts on migrating to TypeScript</a> was originally published in <a href="https://medium.com/hootsuite-engineering">Hootsuite Engineering</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[An approach to learning programming languages]]></title>
            <link>https://medium.com/@ovidiubute/an-approach-to-learning-programming-languages-6bc93ae429bb?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/6bc93ae429bb</guid>
            <category><![CDATA[programming-languages]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[self-improvement]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Wed, 12 Apr 2017 19:45:06 GMT</pubDate>
            <atom:updated>2019-01-02T21:18:09.700Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vf9mIwrF73WT3lZnddxMgA.png" /></figure><p>Learning to write code in a new programming language is similar to learning a foreign language.</p><p>You may have been driven to study it by a tangible need such as moving to a different country, or creating new business connections. Or you may simply have decided it’s a challenge worth taking on. Regardless, it felt intimidating at first. Maybe you could already understand some words because they were similar to your maiden language. Maybe you could even read a newspaper and get the gist of it. But writing and speaking felt very difficult when you first started out.</p><p>The advantage programming languages have over foreign ones is that they have comparatively smaller grammars. An experienced developer can pick up all of the syntax rules within days. It’s a great feeling to be able to read and write code within a week of starting, and it may even seem productive, at first.</p><p>Don’t be fooled, though, because it’s not really as simple as I’m making it out to be. Because knowing syntax and being able to get a program to run is not really at the same level as being able to read and write in a foreign language. Imagine not knowing any Spanish but still being able to read a restaurant menu and ordering something. Maybe you don’t recognize the subtleties needed to have a conversation with a native speaker, yet you can perform trivial tasks with little effort. In the same vein, you’re sure to be able to read and understand source code, up to a point, in an unknown language, especially if it’s similar to something you’re already familiar with. As an example, if a developer has experience in C++, he/she will feel right at home with any of the languages that have a similar syntax such as Java, Rust, C#, or PHP.</p><p>What’s most important in a programming language is not syntax, though. It’s actually finding its utility, knowing the type of problems that can be solved with it, and following the design patterns that it enforces. Learning to write idiomatic code should be your ultimate goal, and this is what this article is about: understanding the need to track your journey towards mastery.</p><p>As a developer, you absolutely should invest time in learning new programming languages. It doesn’t matter if you‘re at a junior, mid, or senior level, or if you’re currently writing code full time in a particular tech and will never switch to anything else (even though this is highly unlikely). The experience alone will make you a better coder, because you will find different ways to tackle problems and you will be able to import patterns from other languages into the one you’re already using (most of the time, and I’m thinking functional vs imperative).</p><p>To be able to reach a certain level of proficiency, you should define for yourself a set of metrics. Tangible goals towards which you can track your progress. If you don’t, you may end up in a situation where you’re unable to ascertain if you’re ready to start a project using a particular technology stack.</p><p>I’ve written code at least once in over a dozen languages. By no means does this entail that I am comfortable with all of them. I’ve already set my own metrics by which I can judge my ability. Allow me to list them and explain my motivations for each of them.</p><h4>Excellent command of syntax</h4><p>You should not be surprised why your program does not compile if the error is purely syntactic, nor should you spend any significant time trying to solve it. A good metric for this is whether you’re able to write code without an IDE and it will pass the compilation or interpretation stage without syntax errors. I’m generally an advocate for using an IDE because we, as developers, usually have more work to do than we can get through in a usual day, so any productivity boost should be welcomed, not excluded for any subjective reasons. However if you <em>always</em> use an IDE you may miss out on learning how to correctly write code by yourself. An IDE also may have shortcuts for repetitive and boring code (commonly named “<em>boilerplate</em>”) and you may be tempted to use them simply because they’re available.</p><p>I need to make a note here; languages evolve over time. If you check out the latest standard of JavaScript, <a href="http://www.ecma-international.org/ecma-262/6.0/">ECMAScript 6</a>, and the <a href="http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf">first edition ever published</a>, you will notice there are many, many changes. This begs the question of should you feel that because you’ve mastered the syntax of a language at some point in time, but you haven’t worked with it at all for months or years, does that mean you’re no longer knowledgeable? I’m going to answer no, and here’s why.</p><p>Everything changes in software development. The landscape is shifting constantly, new languages are added every year, and the sector is probably one of the most dynamic and competitive in the world. If you have invested time to learn a programming language, and consider yourself productive, no amount of time can cancel that out. Imagine you’ve spent working 5 or 6 years in C++. You can’t even remember the standard that was in place at that time. It doesn’t really matter. You have a huge advantage over everyone starting out with <a href="https://meetingcpp.com/index.php/br/items/final-features-of-c17.html">C++ 17</a> (the latest revision of the standard at the time I’m writing this), because you’ve taken the time to master it at one point, and you will be able to approach the design changes with a lot more confidence than a novice. Myself, I wrote a lot of PHP years ago, starting out with version 4 (for the nostalgic among you, remember writing <em>almost</em> OOP code?), then moved on to 5. Version 6 does not exist, for reasons <a href="https://ma.ttias.be/php6-missing-version-number/">that would take too much time to explain</a>. Now, PHP is at version 7. Because I haven’t kept up with it, I obviously have no idea what has changed in the language, from a syntactic point of view (I did hear that lambdas were added, which is awesome). One thing is certain, though, I’m confident in my ability to pick up PHP 7 if I had to, because I invested a lot of time to work with it in the past.</p><h4>Understanding its strengths and weaknesses</h4><p>This requirement is very important because it enables you to use the right tool for the job. You will have to know and accept the limitations of the language and not try and coerce it into doing something that’s not idiomatic. Think of trying to write a triple A game engine in Pascal, or a CRUD backend in Bash. Think that’s too contrived? How about writing a library that enables static type annotations in Python, a language that is designed to be dynamically typed, and is one of its strongest features. I actually wrote this while working at a startup, and it took me some time to understand why it was a terrible idea.</p><p>It helps to know that some languages are so called “general purpose”, which means they can be depended on to solve problems across all of the domains within computing. The prime examples are C and C++. Other languages are more niched, and they wouldn’t make good candidates for solving certain problems, such as Swift or R. There is however a lot of power in specialization.</p><h4>Good knowledge of the standard library</h4><p>I cannot stress this enough. You will never truly master a language unless you learn how to use its standard APIs.</p><p>Be mindful of the fact that you will not be able to fully understand and work with all of them, though. Some languages such as Objective-C come with a frankly huge set of APIs associated with the iOS operating system (even though you can write Objective-C code anywhere, it is most often associated with iOS and macOS development).</p><p>Try not to focus too much on memorizing functions and packages though, this does not scale well at all as you progress through your career. I remember obsessively reading the <a href="https://docs.oracle.com/javase/7/docs/api/">Java API spec</a> years ago trying to learn as many APIs as I could by heart in case I’ll ever use them. Guess what? I only used a handful on a regular basis.</p><p>There are also some languages, such as JavaScript, that come with a fairly limited standard library. Historically this has been the reason why so many third-party libraries stepped in to fill the gaps, leading to an incredibly fragmented and fragile ecosystem. Consider the fact that most JavaScript developers started out by learning jQuery, a library that, at one point, had become so pervasive, you could be forgiven for thinking that it was a programming language in and of itself. This doesn’t mean you get a pass, though. Regardless of how badly written or unintuitive these APIs may be, they are the building blocks with which every library and framework is built, and ignoring them will relegate you to a downstream user of them. Besides that, the limited APIs may be a temporary situation. Java’s Collections API, for example, has received numerous updates in its 8th version, and the Calendar API, once one of the most hated aspects of writing date/time focused code, has also been massively improved (with the help of a third-party lib called <a href="http://www.joda.org/joda-time/">Joda Time</a>).</p><p>Once you’ve mastered this requirement you will be able to author your own libraries to solve very specific problems that you encounter. Don’t take this into consideration, though, when evaluating your skills. You don’t need to be the author and maintainer of a popular library or framework to be able to say you’re proficient. The reverse is also true.</p><p>So these are my preconditions on how to evaluate programming language expertise. You’re probably wondering if I follow my own advice. Am I honest about my own skills? And you may also be thinking whether it pays off to be this honest, and what happens if your resume looks less impressive if you follow this methodology and starting removing certain skills?</p><p>I cannot stress this enough: you need to be honest with yourself if you want to evolve as a software developer. It’s going to be a long journey until you learn enough to be proficient, there are no short-cuts. You need to treat your career as you would a platform with millions of users: it needs to be monitored carefully, constantly, and with a very objective attitude towards performance. This entails having tangible metrics that you can observe daily to track your progress. If you decide to start learning a programming language, no matter if it’s low-level, high-level, imperative or functional, take time off to evaluate how you’re doing. Ask yourself these three questions:</p><ul><li>Can you read and write a program without compile errors and without the help of an IDE?</li><li>Are you aware of the pros and cons of this particular language?</li><li>Do you have a firm grasp over its standard APIs?</li></ul><p>As for myself, following the aforementioned conditions, I’m knowledgeable (or have been in the past) in four languages:</p><ul><li>PHP, which was my entry in the world of web development; as I said I’m no longer developing any software using it</li><li>Java, judging by the years I’ve worked as a backend developer; no longer using it, I’ve switched to JVM hosted languages because they tend to be functional</li><li>Python, which is still my go-to language for small projects</li><li>JavaScript, the language in which I’m currently most involved in</li></ul><p>I’m hopeful I’ll be able to add Elm to that list by the end of this year (still a long way to go), and maybe Clojure (I’ve worked with it before, but not enough to feel proficient). I’ve chosen them because they’re extremely different from what I’m familiar with. Elm is a purely functional language similar and written in Haskell, and Clojure is a <a href="https://en.wikipedia.org/wiki/Lisp_(programming_language)">Lisp</a>. Even though proficiency is something that I won’t reach soon, the journey there will be worth it, because the architecture of apps made possible by these technologies is vastly different from the ones I’m used to working with in imperative languages.</p><p>I would advise you to do the same when picking what to invest your time in. If you love C++, I wouldn’t recommend choosing D as your next language. Not because D isn’t any good, it’s objectively very well designed, but you won’t learn any new patterns, and you won’t learn new ways to solve problems. You’ll write more efficient code, but it will look and feel very similar to what you’ve been writing all your life. Try to push yourself outside your comfort zone.</p><p>Let me know in the feedback section how your experience with learning programming languages has been so far.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6bc93ae429bb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why do we test?]]></title>
            <link>https://medium.com/@ovidiubute/why-do-we-test-67c00c5bfe37?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/67c00c5bfe37</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[software-testing]]></category>
            <category><![CDATA[software]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[documentation]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Mon, 26 Dec 2016 13:50:07 GMT</pubDate>
            <atom:updated>2019-01-02T21:15:00.055Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>“What is the point of software testing?”</blockquote><p>My first reaction upon hearing this was of dismissal. Later on it got me thinking as to how I could convincingly present the advantages of testing. Because the usual arguments of <em>“it’s the right thing to do”,</em> or <em>“you can’t scale a project without tests”</em> can actually be countered pretty easily. We now live in an era of micro-frameworks, IDEs with integrated linters, and extremely short feedback loops provided by hot reloading technologies. It’s getting easier and easier to prove to someone that your code works even in the absence of unit or integration tests.</p><p>Let’s say you lend a friend a $100 bill, and at the end of the day, he reimburses you with ten $10 bills. Ask yourself this: do you count the bills before putting them back in your wallet? He is, after all, your friend, you implicitly trust him. But could he have made a mistake and given you nine bills instead of ten? Maybe eleven?</p><p>Suppose you answered yes, now consider the following: <strong>does counting the money make you distrustful of your friend?</strong> Do you believe that, even if he is your friend, it is your responsibility to protect yourself, and your money, from his mistakes, even if you don’t recall him ever making one?</p><p>If you don’t count them right then and there, when the transfer is made, do you count them later and get back to him if you find he’s made an error? What if it’s two days later and your friend no longer remembers what happened? <strong>What if it’s two years later and he’s already left the country?</strong></p><p>These are questions that get asked daily across organizations of all sizes. They are particularly harder to answer in software companies, though, and that’s because of a little thing called bureaucracy. <strong>Few things anger us, developers, more than bureaucracy.</strong> It’s why we pay everything online, why we don’t understand the long queues at the Post Office, or the people refusing to exchange their printed meal tickets with meal cards. It’s an established cultural trait, one that has allowed our economic sector to be so innovative in the past thirty years.</p><p>There is, however, one drawback, and it should be apparent to us all: without oversight and paper trails, software can be easily mutated, redesigned, rewritten, changed beyond recognition. But what about the people actually working on the product? How do they keep up with the ever changing landscape? This is a subject that everyone gets asked about during technical interviews: <em>“Do you document your code? How do you go about it?”</em>, <em>“What is a comment block?”</em>, <em>“How do you generate documentation from code?”</em>, <em>“How do you keep your documentation up to date?”</em>.</p><p>That last question resonates with me a lot. After working in several companies of different profiles, ranging from telecom, social networking, to mobile gaming, I can say without a shadow of a doubt that trying to write documentation, and keeping it up to date, is humanly impossible.</p><p><strong>Maintaining a test suite</strong> <strong>is the only infallible method of tracking and understanding the shifting complexities of a software product. </strong>Anything else is not worth investing in. This is the real reason that we write tests. It’s not that we don’t trust each other, it’s not because we believe everyone else is stupid and doesn’t warrant our trust, it’s simply because human memory is a fragile and finite resource. You should not have to memorize source code in the eventuality that someone reports a bug. You should not have to track the changes made by a colleague just in case a problem pops up two days after release.</p><p>If you’ve ever asked yourself what’s the point of testing your code, simply step back and imagine yourself in a few years time. Is it reasonable to think you’ll still remember the source code you’ve written, if any one of your users (code without users other than yourself is not the type of project that I’m talking about) reports a problem? Would you be comfortable handing over the project to someone else? How much time would he have to spend to understand the code at the same level as you?</p><p>It may take you a minute or so to prove to someone that your product still works today, but could you still do it in two or three years time? If the answer’s no, it may be time to invest in a test suite.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=67c00c5bfe37" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Thoughts on Zabbix]]></title>
            <link>https://medium.com/@ovidiubute/thoughts-on-zabbix-8bcb7d693104?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/8bcb7d693104</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Sun, 21 Aug 2016 15:24:35 GMT</pubDate>
            <atom:updated>2019-04-13T19:11:56.641Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*QrkyKocziugotjNq0kwU7A.png" /></figure><p>I’d like to spend some time analysing the state of a very powerful, but somehow little known, at least outside of sysops/devops circles, solution to monitor your production environment.</p><p>Zabbix, according to the Wikipedia entry, started as an internal project around the year 1998. Three years later, it was released under the GPL license to the world, but took an additional three more years to reach a milestone 1.0 release, in 2004.</p><p>The project has now been going for almost 18 years, which is amazing considering the typical lifespan of most open source projects. Development seems to be split between two branches, an LTS, bearing the 2.x version template, and a new 3.0 branch which, at the time of this article, is in beta.</p><p>Why is it then, that so few developers are familiar with Zabbix as a product? 1998 is the year Google was founded, after all. There aren’t really many examples of open source products founded during the 90’s that are still alive and kicking.</p><p>Well, I’ll be frank. If you are a sysadmin, Zabbix is an awesome tool. The distributed architecture of agents deployed on host machines, the templating, the frankly unlimited number of servers it can manage, the alerts, it’s all a great improvement over the somewhat ageing Nagios.</p><p>But if you’re a developer, and you’ve successfully deployed your backend app somewhere (managed or cloud), you should <em>not</em> be thinking about Zabbix, not in the year 2016. There are <em>so many </em>competitors these days that outdo Zabbix in the application monitoring space, it’s frankly absurd how some of Zabbix’s issues have not been addressed in almost 18 years.</p><p>Allow me to just list some of my biggest grievances with Zabbix.</p><h3>No dynamic items.</h3><p>Honestly, you don’t fully appreciate this until you use something like Graphite. No dynamic items means, before you can see your data plotted on a graph, actually scratch that, before you can <em>add</em> your data to the Zabbix database, you need to carefully, meticulously, and painstakingly add every single item definition in your application to Zabbix’s configuration.</p><p>So let’s just assume you’re running a REST based application. You have something like 20 endpoints, and you’d like to know how are these endpoints performing. So you add an atomic counter in every controller that just increments on each hit. Obviously, that won’t get you too far, so you also add a Histogram to each controller that saves the distribution of response time to the clients. Let’s suppose you’re running an app that needs to respond very quickly to requests (such as a Trading or Ad related middleware app). You’re going to set the distribution to something like this:</p><ul><li>0..50 milliseconds</li><li>50..75 ms</li><li>75..100 ms</li><li>100..125 ms</li><li>125..150 ms</li><li>150..300 ms</li><li>300..500 ms</li><li>500..750 ms</li><li>750..1000 ms</li><li>1000..1500 ms</li><li>1500..Infinity ms</li></ul><p>Seems like a reasonable setup. We can graph how many hits we have per endpoint, and how quickly our backend is responding to clients.</p><p>But can you guess how many Zabbix items we have to add to completely monitor our app? Well, one hit counter per controller plus <em>eleven</em> histogram related items per controller gives us a grand total of <em>two hundred and forty</em> items. And this is still a very small scale app. Remember we’re not really monitoring anything inside the controllers, just how fast they respond and how are they doing so. You’ll obviously need a lot more items to get a sense of how your app is doing.</p><p>But who’s going to add 240 items manually into what is obviously my second biggest grievance with Zabbix (its interface)? Nobody wants to do it, so either you trick the new guy into doing manual work for a day or two, or you do what everybody else using Zabbix does: you write a script to add the items for you.</p><p>So wait, let’s back up a bit. You’re writing this super cool backend app with all the latest tech, maybe you’re in a startup and one of the tasks for your next sprint reads:</p><blockquote><em>Find a way to automate adding Zabbix items (5 story points)</em></blockquote><p>Obviously, if you have worked with Zabbix before you know that an item is really more complex than I make it out to be in this article. And I’ll be fair, I understand why items can’t just be duck typed in like Graphite, StatsD, or pretty much any project at this stage. But is it annoying to have to configure them? Yes. It most definitely is.</p><p>How does any other backend manage this problem? Simple. By offering no configuration whatsoever. You want to add a metric to OpenTSDB? Sure, just send it. Graphite? No problem. The caveat is Zabbix’s items are more advanced from an operational standpoint. But like I said, if you’re a developer, you don’t care.</p><h3>The GUI</h3><p>Where do I begin with the interface? It really does seem that Zabbix’s GUI was designed for sysadmins to monitor the iowait and open sockets of Apache, not for developers to graph their JMX counters.</p><p>It’s just so tedious to do anything. That’s all I can say. The interface is at least 10 years past its prime, and if you’ve ever looked at dashboards such as Kibana, you’d be forgiven for mistaking Zabbix for a dead project.</p><h3>The graphs</h3><p>I refuse to criticize an image library that is about as old as the Internet. And yes I’m talking about libgd. Let’s just say that the Internet has evolved, and websites these days tend to have a wow factor them. Zabbix’s graphs have a ‘meh’ factor to them, and what I mean is that they are so bland and so unattractive to look at, you will not want them on that big screen next to the fancy Kibana screen that other team has been working on.</p><h3>Conclusion</h3><p>Enjoy Zabbix, if you’re a sysadmin, that is. For us developers, we’d very much like a bit more flexibility and visual appeal to our monitoring.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8bcb7d693104" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Does clean code matter?]]></title>
            <link>https://medium.com/@ovidiubute/does-clean-code-matter-1fb14c8f1c5b?source=rss-a48617974b32------2</link>
            <guid isPermaLink="false">https://medium.com/p/1fb14c8f1c5b</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Ovidiu Bute]]></dc:creator>
            <pubDate>Sun, 21 Aug 2016 15:22:35 GMT</pubDate>
            <atom:updated>2019-04-13T19:08:50.325Z</atom:updated>
            <content:encoded><![CDATA[<p>A question I see often thrown around when discussing software development is:</p><blockquote><em>“What is clean code?”</em></blockquote><p>The question always struck me as audacious. It’s like asking a painter to explain how to paint properly. But hold on, a painter works alone, and the finished product does not have to conform to a rigid specification. A painter doesn’t have deadlines either, at least, I’ve never heard of any. So that comparison doesn’t work at all. Hmm. How about asking a bridge builder? He’s part of a team, and the project’s deliverable is met with extraordinary technical scrutiny. I wonder what he would answer when asked:</p><blockquote><em>“How do you build a clean bridge?”</em></blockquote><p>On second thought, bridges are not built with the same methodology as software. Sure, there’s maintenance, but you rarely decide mid-way to scrap everything and start over. And you don’t really have the option to hot-fix your bridge at 3 A.M. on a Sunday because one of the structural elements has started to collapse.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GC_R18LJnsJSPO5X-6yfnw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/-gS54SWrHMg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">chuttersnap</a> on <a href="https://unsplash.com/search/photos/bridge?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Could it be that the clean code question actually has more depth to it than we think?</p><p>I’d say that the question needs to have a bit more context for it to be fair to the person answering it. A more honest question would be something like:</p><blockquote><em>“What is clean code to you, if you’re going to be working on a 5–10 man team?”</em></blockquote><p>When was the last time you wrote code that you absolutely knew would hit production and stay there for at least 2 years? Have you ever known that in advance?</p><p>The real irony is that, if you’re writing code all by yourself, you simply do not care about any of that. Does that mean you don’t write clean code? Maybe. Or maybe you want to get the job done as quickly as possible and move on.</p><p>Does knowing the answers to the above questions make you write “clean” code? I believe people want to write the best software that they can, but is it fair to say that, under peer pressure, they’d do a better job?</p><p>And after all, how clean can code be? How do you measure it? It might be tempting to answer with a phrase containing the word “bugs” in it, but I think everyone knows how that one plays out in the real world.</p><p>Perhaps you could measure the cleanliness factor of a particular block of code by measuring how much time it takes you to change it. But that also needs some context. Was the code written by you a week ago? A month? 2 years? Are you a Junior level software developer or a seasoned vet? Are you new to the project?</p><p>And how about business value? Is it profitable for your company to write clean code? Does a start-up exit faster if its code was written in such a way that it allowed a 20–50 man team to rapidly iterate on it and pivot according to market fluctuations?</p><p>I’m going to stop with the questions now, though, let’s draw up some conclusions.</p><p>It seems to me that measuring cleanliness of our code is hard. Writing clean code is even harder, of course. Talking about clean code, on the other hand, is surprisingly easy. Almost anyone can talk for hours about it.</p><p>And this is where I think the irony is: most people love the idea of clean code, would definitely write clean code given the opportunity, but have no idea how to measure code cleanliness or if this endeavor has any tangible business value.</p><p>I propose a new topic of discussion to everyone out there tackling the idea of clean code:</p><blockquote><em>“How do we measure clean code, and what’s the threshold at which it starts generating business value?”</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1fb14c8f1c5b" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>