<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Horia Coman</title>
    <description>The latest articles on Forem by Horia Coman (@horia141).</description>
    <link>https://forem.com/horia141</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F32555%2Fad9f9449-9224-414d-bb22-b90e641a6696.png</url>
      <title>Forem: Horia Coman</title>
      <link>https://forem.com/horia141</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/horia141"/>
    <language>en</language>
    <item>
      <title>Seven Anti-Patterns For Your Job Search</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Sun, 17 Oct 2021 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/seven-anti-patterns-for-your-job-search-1je</link>
      <guid>https://forem.com/horia141/seven-anti-patterns-for-your-job-search-1je</guid>
      <description>&lt;p&gt;Over the last year, I’ve reached out to almost 1000 engineers trying to get them to interview for Bolt. I’ve had some success and plenty of failures. &lt;strong&gt;But I have learned a lot about how people approach interviews and career development. And I’ve identified seven “anti-patterns” that I think are detrimental to a successful career.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In this article, I want to share these anti-patterns with you. I also want to share my approach to effective “job searches”.&lt;/strong&gt; I hope these will prove useful to you.&lt;/p&gt;

&lt;p&gt;I’m gonna work off some assumptions. You’re a software engineer with some years of experience. You want to get the most out of your career. You’re based somewhere in Europe, the US, LatAm, or so. Life is going OK for you and you want to optimize your long-term career. If this is not you, then you may or may not get something out of all this.&lt;/p&gt;

&lt;p&gt;Now it’s no secret that we are living in a golden age for software engineers. Software is eating the world, and demand for devs is far outstripping supply. Developers have their pick of projects, high compensation, and cushy jobs. If you’re looking to have a great career it’s never been easier. But it still requires work, planning, keeping your ear to the ground, avoiding some common mistakes, and even taking a &lt;a href="https://lethain.com/forty-year-career/"&gt;40-year view of it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And as some of us know, it wasn’t always like this. The .com crash was a situation opposite to what we have right now. And things have only &lt;em&gt;really&lt;/em&gt; gotten good since the 2010s. A reversal to the mean is still within the realm of possibility. That’s why I think it’s important to make the most out of this situation and strike the iron while it’s hot. Avoiding the following anti-patterns is a good start.&lt;/p&gt;

&lt;h1&gt;
  
  
  My Background Doesn’t Match The Position
&lt;/h1&gt;

&lt;p&gt;I was looking for backend engineers to work on our microservices-based systems. But I cast a wide net when reaching out. I wanted to speak with folks from embedded, security, low level, and kernels. And I was also keen on people working in compilers, networking, or automotive. &lt;strong&gt;But I got a lot of pushback and even questioning of my approach.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But “backend” development is different. It’s the place where “business logic” resides. Often, it is not so much about the technology as it is about describing the laws that govern the business. As such, any developer can be a backend dev! There are still notions of architecting and scaling a system that does require expertise. But that’s not a day-to-day thing. And in general, engineers help by solving problems. Not by knowing technologies or being experts in this or that tool. There’s great value in mastering tools, but only as a means to solving problems. Knowledge for its own sake is an anti-pattern too!&lt;/p&gt;

&lt;p&gt;At Bolt, we have folks from a classical backend background, of course. But we also have former mobile devs, embedded ones, or ML people. They’re doing great and their previous experience comes in handy often. And they gravitate towards the projects that highlight their strengths.&lt;/p&gt;

&lt;h1&gt;
  
  
  I’m A &lt;a href="http://www.paulgraham.com/avg.html"&gt;Blub&lt;/a&gt; Developer And You’re Using Blab
&lt;/h1&gt;

&lt;p&gt;Even when I reached out to backend developers &lt;strong&gt;I got way too many “I’m a Java/C#/C++ dev, so I’m not sure I’m what you’re looking for” answers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The skillset you developed is being able to solve problems, having engineering maturity, and understanding what’s needed in large-scale software projects. That’s why we want to talk to you. That’s what companies value, in the end. Regardless of language or ecosystem, you’re going to need to solve problems. And you’re going to need to build reliable and scalable solutions. Or take part in code reviews, write tests, ensure the quality of your solution, etc.&lt;/p&gt;

&lt;p&gt;Again, speaking from experience, very few of our devs have used Node+TypeScript before. Yet they still do their first release in their first or second week of working with us. And pick up the rest and become proficient in a matter of months.&lt;/p&gt;

&lt;h1&gt;
  
  
  I Have A Fancy Title And I Don’t Wanna Give That Up
&lt;/h1&gt;

&lt;p&gt;This came up a bunch too. Folks had Architect, Staff, or Principal titles. But I was hiring “just” for a Senior Software Engineer. &lt;strong&gt;So I got a bunch of quick nopes. And a bunch of longer nopes from folks who wanted to understand a bit more but decided against a “downgrade”.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://staffeng.com/guides/does-the-title-even-matter"&gt;Titles do matter&lt;/a&gt;. But titles are very company-specific too. For example, product companies usually don’t have the Architect position. As a famous example, none of the FAANGs do. Likewise, startups usually don’t have more than “Engineer” or “Senior Engineer”. Even in established product companies, there’s a wide variety of post-senior role structures. There’s also&lt;a href="https://charity.wtf/2020/11/01/questionable-advice-the-trap-of-the-premature-senior/"&gt;title inflation&lt;/a&gt; to consider. And different companies have different expectations. These things become more of a way to express something internal to the company and not some global truth. You’re limiting the kinds of cool companies you can work for by focusing too much on the title.&lt;/p&gt;

&lt;p&gt;We’ve had many folks join as regular engineers who were Staff engineers, or Architects, or Tech Leads, or even managers. They’ve all thrived, managed to put their experience to good use, and then “got back” the title in our context too. And of course, even their compensation increased as a result of the move.&lt;/p&gt;

&lt;h1&gt;
  
  
  There Are Too Many Senior People
&lt;/h1&gt;

&lt;p&gt;This one caught me off guard. &lt;strong&gt;Some folks worried that there would be too many other senior people in the engineering teams. And there would not be enough room to get to those limited leadership opportunities.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But this approach is counterproductive. You never want to be the best in the group. You rather want to surround yourself with people you have things to learn from. If it’s a good collective then it’s bound to also have success. And then at least you’ll catch the rising tide that lifts all boats. But most likely the organization will expand, and you’ll get that chance you were looking for, in the end. Being in a higher-performance team will reflect better on you at the end of the day.&lt;/p&gt;

&lt;p&gt;At Bolt, there’s no limit to ownership or leadership. It’s more about the things you do, and not the position you are in. The same holds for managers and individual contributors. Case in point, a lot of the critical processes at Bolt are run by folks who took an interest in them. Our hiring pipelines, our coding interview process, etc. are good examples.&lt;/p&gt;

&lt;h1&gt;
  
  
  I’m Not Good For The Interviews Or For Bolt
&lt;/h1&gt;

&lt;p&gt;Again, this one caught me off guard. &lt;strong&gt;Some folks found the position attractive. Yet they didn’t want to apply because they didn’t see themselves as ready or good enough.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is an insidious anti-pattern. You might be judging yourself harshly, or us too well. You might be viewing the situation through the lens of impostor syndrome. Or of perfectionism. Even if the technical skills aren’t there yet, a company might still see enough potential to make an offer. Or the internal context is such that something can happen. It’s not all black and white, even at bigger companies.&lt;/p&gt;

&lt;p&gt;We have folks from very diverse companies. Ex-&lt;a href="https://en.wikipedia.org/wiki/Big_Tech"&gt;FAANG&lt;/a&gt; engineers as well as 3-person shops. Product companies and outsourcing companies. Competitive programmers and self-taught devs. I’d dare say success is orthogonal to this sort of background.&lt;/p&gt;

&lt;h1&gt;
  
  
  I’m Looking For An Upward Move
&lt;/h1&gt;

&lt;p&gt;A fair number of folks were looking for an upgrade to their current position. &lt;strong&gt;They were junior devs seeking a particular senior title. Or inexperienced managers seeking to transition to a full manager role. Or even folks without any management experience seeking to gain it via a move.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The truth is the scope of your work rarely increases when changing jobs. The salary - sure. Especially in the first part of your career. It’s even expected every job change has a comp increase. The “title” can change too. You can get an upgrade when moving to a startup or smaller company. Or a downgrade when going to a bigger company. But companies tend to be conservative on the experience side. They will look for “demonstrated experience”. And there’s no&lt;a href="https://medium.com/thg-tech-blog/understanding-the-experience-algorithm-b5e0890a566d"&gt;compression algorithm for experience&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A common pattern at Bolt is for someone to join and take on more ownership and responsibility. They’re then swiftly promoted. We’ve even done promotions during the probation period for folks who were clearly next-level. It is not just the transition, but the growth that can happen after.&lt;/p&gt;

&lt;h1&gt;
  
  
  I’m Happy Where I Am / I’m Not Ready For A Change
&lt;/h1&gt;

&lt;p&gt;This one is gonna ruffle some feathers. &lt;strong&gt;A fair number of folks didn’t want to talk because they were happy with their current gig. And not looking for a change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finding a place with great colleagues, challenging projects, and good compensation is hard. You don’t wanna lose that if you have it. But the number of these employers keeps increasing. Even in the outsourcing-dominated Eastern Europe where I’ve got the most context. And what was great a couple of years ago, might be OKish today.&lt;/p&gt;

&lt;p&gt;In the end, leaving a company might not be the irreversible move it’s made out to be. I’ve seen enough folks jump from Company A to Company B and back to Company A. Sometimes in a month.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion &amp;amp; Next Steps
&lt;/h1&gt;

&lt;p&gt;Thanks for coming to my TED talk. You now know some things to avoid. But the tone so far has been sorta’ negative and I don’t feel good ending it like this. So I want to give a small “job searching” framework you can use as a guide. It consists of three rules to replace the anti-patterns form above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, look at the team and project you’ll be working on as well as the wider product you’ll be embedded in.&lt;/strong&gt; Think about the future growth of the company you’ll be helping out and how that can affect you. Tie all these to whatever career plans you have. Only then consider technology-specific reasons. Especially avoid going for one thing - playing with Scala, or using K8S.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, aim to find the highest performing collective that will have you.&lt;/strong&gt; This is very important in your early career. The dividends it will pay off will more than offset “title deflation”. Once there, take on responsibility and ownership and try to grow as fast as the company at least.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finally, treat interviews as a skill to practice and as a tool for exploring the “market”.&lt;/strong&gt; Not as a chore to only do when you’re forced to switch jobs. Rather you should do them even when you’re not “actively” looking. You want to get good at them. And you want to use them to better understand the market.&lt;/p&gt;

&lt;p&gt;Anyway, that’s enough from me. Thank you for reading this far! If I’ve managed to get you excited you should know that&lt;a href="https://careers.bolt.eu/"&gt;Bolt is hiring&lt;/a&gt;. If you’re an engineer who wants to avoid the career anti-patterns - or know one who does - then come our way at &lt;a href="https://careers.bolt.eu/"&gt;careers.bolt.eu&lt;/a&gt;. Or DM me on LinkedIn and I’ll sort things out.&lt;/p&gt;

&lt;p&gt;Thanks to Mihnea DB, Mihai S, Radu V, Liviu C, Foti C, Radu S, Tomasz R, Sergey Z, Lauri L, Andreea C, and Nick G for tearing the first draft of this to shreds and forcing me to write a leaner and meaner text.&lt;/p&gt;

</description>
      <category>career</category>
      <category>post</category>
    </item>
    <item>
      <title>Jupiter Dev Log 5 - Architecture</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Tue, 08 Dec 2020 07:20:05 +0000</pubDate>
      <link>https://forem.com/horia141/jupiter-dev-log-5-architecture-318b</link>
      <guid>https://forem.com/horia141/jupiter-dev-log-5-architecture-318b</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yq8_dxIh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://horia141.com/assets/jupiter-docs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yq8_dxIh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://horia141.com/assets/jupiter-docs.jpg" alt="Docs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo credit &lt;a href="https://unsplash.com/@jimo?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content%20=creditCopyText"&gt;James Barnett&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/script?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this latest post in the &lt;a href="https://jupiter-goals.readthedocs.io/"&gt;Jupiter&lt;/a&gt; dev log series I want to speak about the software architecture of Jupiter. It’s a topic I’ve wanted to write about for a while actually, but somehow never got the will to do it. With the limited time, I have for working on this, writing a new feature always trumped writing about writing a new feature. But I’ve finally decided to bite the bullet and commit to something because I recently finished reading and reviewing &lt;a href="https://dev.to/horia141/clean-architecture-review-2pji"&gt;Clean Architecture&lt;/a&gt;. It has made quite an impression on me and made me think in a new light about some of the design decisions I made with Jupiter. So this post will be equal parts presentation and critique. The project has also reached a &lt;em&gt;respectable&lt;/em&gt; &lt;code&gt;15 KLOC&lt;/code&gt; of code, so it has enough heft that the discussion isn’t strictly academic, and might prove useful to other folks too!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8JTflBM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://horia141.com/assets/jupiter-tutorial-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8JTflBM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://horia141.com/assets/jupiter-tutorial-3.png" alt="Pictures of jupiter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Cornerstones
&lt;/h2&gt;

&lt;p&gt;I find the term “architecture” quite fluid. I’ve seen it mean everything from the choice of what patterns are used in the source code of a project, to building a system as a webapp, to using a microservices “architecture”. Clean Architecture focused a lot on “architecture in the small”: codebase level organization of classes within components and dependencies between components. But I liked the very general notion that &lt;a href="https://martinfowler.com/architecture/"&gt;“architecture is the important decisions”&lt;/a&gt; so I’ll cover the &lt;em&gt;big decisions&lt;/em&gt; or &lt;em&gt;cornerstones&lt;/em&gt; too.&lt;/p&gt;

&lt;p&gt;Some of the choices I made will raise some eyebrows. They aren’t ones one would usually make for a &lt;em&gt;product&lt;/em&gt;. They even seem both explicitly tailored at &lt;em&gt;programmers&lt;/em&gt; and actively &lt;em&gt;hostile&lt;/em&gt; to non-programmers. The underlying theme is that they made my life easier, and allowed Jupiter to quickly become usable and useful. Indeed, I started making use of it as my main tool as soon as a week after the &lt;code&gt;git init&lt;/code&gt; was done. Had I went with a more &lt;em&gt;traditional&lt;/em&gt; approach I would have statistically speaking never finished it and never used it. I’m happy with the outcome of these choices, but I realize they aren’t and cannot be final if I ever want user #2! Anyway, that’s about all for justification - take the choices as they are henceforth.&lt;/p&gt;

&lt;p&gt;The first architecture cornerstone is that Jupiter is a self-hosted and locally operating CLI application. This means that a user (me) downloads a &lt;em&gt;packaged and versioned release&lt;/em&gt; of the application and uses it locally to manage local data. I use Docker as packaging and releasing infrastructure, even if this sort of use-case isn’t its main one. Of course, &lt;a href="https://notion.so"&gt;Notion.so&lt;/a&gt; plays a big role as the nice user-interface. Jupiter interacts with Notion as a client which periodically checks to see if there’s something to be &lt;em&gt;done&lt;/em&gt;. When I’ll add other integrations - with Google Calendar, Spotify, etc, the same interaction patterns will be followed. But for now, there isn’t an “always-on” component to Jupiter to act as a counterpart to these services. Rather a user’s install of Jupiter does something only as a result of the user asking it to!&lt;/p&gt;

&lt;p&gt;The second architecture cornerstone is the use of text files as storage and reliance on git for persistence and cloud sync up. Storage itself - whether text files, or databases, or in the cloud, is an implementation detail in the end. Though it is a very &lt;em&gt;visible&lt;/em&gt; one. But relying on mechanisms outside the control of the app for persistence and sync up is what essentially makes the app a “local” application rather than a “cloud” one.&lt;/p&gt;

&lt;p&gt;The third architecture cornerstone is that the CLI application has a command-driven interface. It essentially presents a lot of commands to the user through which they do their work. Think &lt;code&gt;git&lt;/code&gt; here. So there are commands like &lt;code&gt;jupiter sync&lt;/code&gt; or &lt;code&gt;jupiter smart-lists-create&lt;/code&gt;, etc. Jupiter is running only when such a command is invoked. If you run &lt;code&gt;jupiter --help&lt;/code&gt; you’ll see a lot of commands. Suspiciously looking like a REST or RPC API even.&lt;/p&gt;

&lt;p&gt;The fourth architecture cornerstone is that there are multiple ways of interacting with the system - the CLI and Notion. And they have separate storages, which need to be explicitly synchronized. Indeed, most of the interaction will occur through Notion. But any change made there won’t be &lt;em&gt;seen&lt;/em&gt; by the local install. You need to run a &lt;code&gt;jupiter sync&lt;/code&gt; command for that to happen. At first glance, this seems like simply a functional concern, but it does end up influencing several architectural aspects. From how code is organized to allow abstracting away the need for synchronization, to a focus on idempotence which permeates the codebase. I run the command about once a week, therefore the &lt;a href="https://en.wikipedia.org/wiki/Eventual_consistency"&gt;eventual consistency&lt;/a&gt; reconciliation window can get quite big!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;This draws us down into the code for the first time. Commands imply a great deal of regularity in the way one interacts with the application - issue a command, wait for processing, observe results, repeat. And this indeed translates to the code. The app looks like any system for answering requests. Which in computer parlance we call &lt;em&gt;a server&lt;/em&gt;! It’s not a &lt;em&gt;web server&lt;/em&gt; like most things are these days. And it’s not always running like them. But it’s the same kind of thing in the end, and to a user it is transparent. As a historical aside - the first web applications were built with a server feature called &lt;a href="https://en.wikipedia.org/wiki/Common_Gateway_Interface"&gt;CGI&lt;/a&gt; - which allowed it to invoke a binary on the same machine. Naturally, a new process was spawned for each request, much like we’re doing here&lt;/p&gt;

&lt;p&gt;In the prehistory of the project, there was no code architecture to speak of. Or rather it was the venerable &lt;a href="https://en.wikipedia.org/wiki/Big_ball_of_mud"&gt;big ball of mud&lt;/a&gt;. The first-ever tagged commit &lt;a href="https://github.com/horia141/jupiter/tree/v0.0.1/src"&gt;v0.0.1&lt;/a&gt; still had a lot of this. There were a bunch of files, all independent, all entry points, and with a very minimal structure around it.&lt;/p&gt;

&lt;p&gt;But things have evolved quite a lot. And as of release &lt;a href="https://github.com/horia141/jupiter/tree/v0.6.1/src"&gt;v0.6.1&lt;/a&gt; things look &lt;em&gt;much&lt;/em&gt; different. For better or worse we have this component structure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5_I3gvTL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://horia141.com/assets/jupiter-architecture.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5_I3gvTL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://horia141.com/assets/jupiter-architecture.jpg" alt="Jupiter Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A listing of the source tree hints at this too, but it isn’t a 1:1 mapping with the above image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ tree -L 3 src
src
├── command
│ ├── __init__.py
│ ├── command.py
│ ├── garbage_collect.py
│ ├── generate_inbox_tasks.py
│ ├── inbox_tasks_archive.py
│ ├── ...
│ └── workspace_show.py
├── controllers
│ ├── big_plans.py
│ ├── common.py
│ ├── garbage_collect_notion.py
│ ├── ...
│ ├── vacations.py
│ └── workspaces.py
├── jupiter.py
├── models
│ ├── basic.py
│ └── schedules.py
├── remote
│ └── notion
│ ├── big_plans.py
│ ├── common.py
│ ├── inbox_tasks.py
│ ├── infra
│ ├── projects.py
│ ├── recurring_tasks.py
│ ├── smart_lists_manager.py
│ ├── vacations_manager.py
│ └── workspaces.py
├── repository
│ ├── big_plans.py
│ ├── common.py
│ ├── ...
│ └── workspace.py
├── service
│ ├── big_plans.py
│ ├── ...
│ └── workspaces.py
└── utils

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ll go into a bit more details around what’s happening. There are three large components to the system, each split up into several sub-components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI: 

&lt;ul&gt;
&lt;li&gt;This component handles the CLI functionality of the application. It concerns itself with arguments parsing , outputting things to the console, etc. It’s in fact the only component aware that this is a command-line app, as opposed to a web or desktop one.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Main&lt;/code&gt; subcomponent is the entry point to the application - the uncleanest of unclean components. It’s actually the &lt;code&gt;src/jupiter.py&lt;/code&gt; file. This essentially handles wiring everything up together in the application - all repositories, commands, etc - and dispatching from the user’s intent to a command to execute.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Command&lt;/code&gt; subcomponent contains classes for handling each of the commands for the application. Here we’ll find a class like &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/command/garbage_collect.py#L14"&gt;&lt;code&gt;GarbageCollect&lt;/code&gt;&lt;/a&gt; which implements the &lt;code&gt;jupiter gc&lt;/code&gt; command, and indeed, one for each command. The logic is very thin, however. A command simply parses arguments and invokes an appropriate domain-level controller with the required data.&lt;/li&gt;
&lt;li&gt;There’s even a small home-brewed framework of sorts since each command is so regular. Checkout &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/command/command.py"&gt;&lt;code&gt;command.py&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/jupiter.py"&gt;&lt;code&gt;jupiter.py&lt;/code&gt;&lt;/a&gt; for details.&lt;/li&gt;
&lt;li&gt;Overall I’m pretty happy with this part of the codebase. It’s self-contained, modular, and deals with exactly what it needs to.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Domain: 

&lt;ul&gt;
&lt;li&gt;This component handles the business logic of the application. It’s split across entities lines - projects, inbox tasks, big plans, smart lists, etc.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Controller&lt;/code&gt; subcomponent contains the so-called use-cases of the application. Here is where the magic happens many times - the business logic itself resides here. Here we’ll find a class like &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/controllers/inbox_tasks.py#L31"&gt;&lt;code&gt;InboxTasksController&lt;/code&gt;&lt;/a&gt; which implements the CRUD operations on inbox tasks. There are also some specialized controllers like &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/controllers/garbage_collect_notion.py"&gt;&lt;code&gt;GarbageCollectNotionController&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/controllers/sync_local_and_notion.py"&gt;&lt;code&gt;SyncLocalAndNotionController&lt;/code&gt;&lt;/a&gt; which frankly do the &lt;em&gt;core&lt;/em&gt; and logic-heavy work. These are the reasons why the application was built in the first place - all the other controllers offer support.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Service&lt;/code&gt; subcomponent contains the lower-level entity-specific logic. There’s one service class - like &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/service/inbox_tasks.py#L22"&gt;&lt;code&gt;InboxTasksService&lt;/code&gt;&lt;/a&gt; - for each entity. This is not exactly business-logic, nor is it storage or infrastructure code. What happens here usually is that mutations are applied to both the local storage and to the Notion storage. Similarly, the critical synchronization code between Notion and the local storage resides here. The need for such a layer - an architectural thing - is pushed by the functional choices. Though I admit the naming of &lt;em&gt;service&lt;/em&gt; isn’t quite right.&lt;/li&gt;
&lt;li&gt;I’m not 100% happy with the &lt;code&gt;Controller &amp;lt;&amp;gt; Service&lt;/code&gt; separation. In the future, I’ll probably merge the two, reify each use-case as a separate controller class, and figure out some better abstractions for Notion to local syncing.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Infra 

&lt;ul&gt;
&lt;li&gt;This component handles the interaction with the “outside” world. It’s split across entity lines - with projects, inbox tasks, etc. getting their own classes here, and along the local vs Notion divide.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Local&lt;/code&gt; subcomponent contains the classical repositories that code in the domain component uses to interact with persistent storage - for now text files on disk. It’s what you would expect these be. For example, there is an &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/repository/inbox_tasks.py#L47"&gt;&lt;code&gt;InboxTasksRepository&lt;/code&gt;&lt;/a&gt; class with methods such as &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;load&lt;/code&gt; (by id), &lt;code&gt;save&lt;/code&gt;, &lt;code&gt;find_all&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Remote&lt;/code&gt; subcomponent contains code for interacting with Notion in a principled way. There are a bunch of utility classes that abstract away the raw Notion client and provide some shielding for when the official SDK will need to replace the current one. But the main abstraction is the Notion “collection”. For example, there is an &lt;a href="https://github.com/horia141/jupiter/blob/v0.6.1/src/remote/notion/inbox_tasks.py#L50"&gt;&lt;code&gt;InboxTasksCollection&lt;/code&gt;&lt;/a&gt; class which deals with both setting up the Notion-side page structures and collections, but also mapping between Notion rows and in-memory data.&lt;/li&gt;
&lt;li&gt;Overall I’m decently happy with the architecture of this part of the code. But the actual code-quality could be improved. There’s some lower-level code here which could be made better, more generic, and more robust. But the biggest issue is probably that there’s a lot of business logic about Notion such as what pages there are, how collections are formed, and what views they have, which are coded at this lower level, rather than in the “Domain” component.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you invoke a command such as &lt;code&gt;jupiter inbox-task-set-name --id 10 --name “Foo”&lt;/code&gt;, the following happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;src/jupiter.py&lt;/code&gt; script is invoked and all the repositories, collections, services, controllers, and commands get initialized and wired together. The program decides which command to invoke based on the name of the command.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;InboxTasksSetName&lt;/code&gt; classes’ &lt;code&gt;run&lt;/code&gt; command gets executed, which parses and validates command line arguments, and passes control over to the &lt;code&gt;InboxTaskController&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;InboxTaskController&lt;/code&gt;’s &lt;code&gt;set_inbox_task_name&lt;/code&gt; method gets invoked, which simply forwards the call to the &lt;code&gt;InboxTaskService&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;InboxTasksService&lt;/code&gt;’s &lt;code&gt;set_inbox_task_name&lt;/code&gt; method gets invoked. This loads the respective inbox tasks via the repository then applies the change to the entity, then saves the change locally. Finally, it applies the change remotely on Notion side.&lt;/li&gt;
&lt;li&gt;The operation is not transactional between the local and Notion side. The latter change might fail, and a &lt;code&gt;jupiter sync&lt;/code&gt; will be needed to reconcile the two.&lt;/li&gt;
&lt;li&gt;This is an example of a simple CRUD operation. More complex &lt;code&gt;sync&lt;/code&gt;, or &lt;code&gt;gc&lt;/code&gt; commands have most of their logic in the controller, which orchestrates the changes across multiple entities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some Nice Things
&lt;/h2&gt;

&lt;p&gt;To wrap the previous section off, there are some unambiguously good things about how the system as it is currently organized.&lt;/p&gt;

&lt;p&gt;It is “layered”, and each layer deals with a specific thing. The directories structure better represents these layers, but each layer also is a specific component. There are no cycles between the layers.&lt;/p&gt;

&lt;p&gt;It has a notion of controllers which capture the use-cases of the application. The logic is shared with services, and it’s quite clear what the application is about and can do.&lt;/p&gt;

&lt;p&gt;It uses dependency injection quite heavily. Not IoC though, as the flow of control still follows the flow of dependencies. Regardless, the &lt;code&gt;src/jupiter.py&lt;/code&gt; looks like a regular modern web application’s setup code.&lt;/p&gt;

&lt;p&gt;It isn’t tied too hard to the CLI app paradigm and can relatively easily be extended to any “request-handling” interaction mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Principled Critique
&lt;/h2&gt;

&lt;p&gt;Let’s look now at the component-level principles presented in the book, and how the current system stacks against them.&lt;/p&gt;

&lt;p&gt;The release/reuse equivalence principle is weakly followed. The application is monolithic, hence we can’t speak of reuse, and releases happen for the whole thing. In a future in which we have multiple notions of clients, the controllers, services, and other parts can be packaged independently, and various clients (or servers) could make use of them. It is versioned, however, and it’s using &lt;a href="https://semver.org/"&gt;semantic versioning&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The common closure principle is quite well followed, by virtue of separating things into layers. Big changes have tended to affect things across layers, but once the thing becomes more mature I’ll expect the bigger chunk of work to be localized to a layer.&lt;/p&gt;

&lt;p&gt;The common reuse principle is quite well followed, by virtue of separating things into layers. Again, it’s not a situation of reuse we’re looking at so far. However, because dependencies flow from more abstract to more concrete, rather than the other way around, reuse will be tricky for certain situations if future improvements aren’t done.&lt;/p&gt;

&lt;p&gt;The acyclic dependencies principle is quite well followed. There are no loops in the dependencies.&lt;/p&gt;

&lt;p&gt;The stable dependencies principle is weakly followed. Business logic classes routinely depend on infrastructure level concerns, which tend to change for various reasons (Notion API changes, updates in storage, etc.). Where it’s most hurting is the dependence on data-types exported by these packages, but functionality tends to be neatly abstracted.&lt;/p&gt;

&lt;p&gt;The stable abstractions principle is weakly followed. Abstractions aren’t well-reified in the code - there’s a lot of dependencies expressed in terms of concrete classes. Since this is Python it still allows for decent substitution if we wanted, even though the type-checker would complain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Improvements
&lt;/h2&gt;

&lt;p&gt;In this section, let’s look at some architectural improvements which flow naturally from the previous discussion.&lt;/p&gt;

&lt;p&gt;The biggest future improvements are around implementing more of the clean architecture as given in the book. This means at the minimum inverting the flow of dependencies. We can add a bunch of interfaces and types in the domain part, that the other more “concrete” components depend on and implement. &lt;code&gt;src/jupiter.py&lt;/code&gt; can still wire them up well.&lt;/p&gt;

&lt;p&gt;There are very few clear “Entities” encapsulating the clear and profound business logic. And that’s a shame because there are so many such concepts - from ids to schedules. I’d like to separate this sort of central logic and reify entities and what can be done with them better.&lt;/p&gt;

&lt;p&gt;All of the major objects are somehow containers of objects and singletons. Even in the business logic layers, it’s all about “repositories” doing things rather than entities themselves doing the things. For example, a smart list item doesn’t get to add its own tag, rather the smart list service adds a tag to a smart list item entity. It’s all very “procedural”. I’d like to change this and move some of the logic to the entity classes themselves.&lt;/p&gt;

&lt;p&gt;Controller/use-case logic is kind of thin, and I think some of it can be centralized there instead of “services”. Some better abstraction for syncing between Notion and local will be needed to avoid repetition and/or missing out on some cases.&lt;/p&gt;

&lt;p&gt;Too much business-logic about Notion is embedded in the lower-level &lt;code&gt;Infra/Remote&lt;/code&gt; subcomponent. It should offer a more flexible interface, which the &lt;code&gt;Domain&lt;/code&gt; component uses to build the appropriate structures.&lt;/p&gt;

&lt;p&gt;Changes tend to be quite vertical, from the smallest to the largest. I’d prefer it if only larger changes - those warranting a minor version bump - would be thus, and smaller changes would completely be isolated in a component.&lt;/p&gt;

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

&lt;p&gt;This about wraps it. Hopefully, it’s been an interesting and useful read. I expect the doc to reflect the reality of the codebase for quite some time. But as with everything, the &lt;em&gt;truthness&lt;/em&gt; of this document will slowly start to erode as I make improvements, extend functionality, and refactor the codebase. However, the major elements I expect to stay in place for a long-long time, and everything else to gradually move in the direction highlighted in the “to improve” sections of the doc.&lt;/p&gt;

&lt;p&gt;Stay safe and see you next time!&lt;/p&gt;

</description>
      <category>jupiter</category>
      <category>post</category>
    </item>
    <item>
      <title>Clean Architecture Review</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Tue, 01 Dec 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/clean-architecture-review-2pji</link>
      <guid>https://forem.com/horia141/clean-architecture-review-2pji</guid>
      <description>&lt;p&gt;This is my review of &lt;a href="https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt; by Uncle Bob. The book is undoubtedly a classic and I feel bad for not having read it earlier. I think it might have helped with a project or three. Better late than sorry for sure, and unlike other books I read too late (SICP primarily) I did feel I got a lot out of this book, and I came out a better developer on the other side. It certainly gave me a bunch of ideas to try out in &lt;a href="https://jupiter-goals.readthedocs.io/" rel="noopener noreferrer"&gt;Jupiter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I must admit I’ve been skeptical in the past of this whole &lt;em&gt;clean code&lt;/em&gt;, &lt;em&gt;clean architecture&lt;/em&gt;, &lt;em&gt;design patterns&lt;/em&gt;, etc part of the software engineering toolset. Not the things in themselves. But what I perceived as the bias towards “the enterprise” on the one hand, and towards the world of software consultancies and “project”-work on the other hand. It didn’t help that I felt there was a lot of cargoculting in the mix too. As well as a feeling that this stuff is the &lt;em&gt;easy&lt;/em&gt; part of software engineering. As opposed to algorithms, machine learning, functional programming, distributed systems, or other “hard” things. In any case, I got some wisdom in the end and decided to complete this part of my education before I slip too much into management. The fact that my side project Jupiter is hitting some architecture limitations is purely coincidental.&lt;/p&gt;

&lt;p&gt;Anyway, back to regular programming. The topic of the book is software architecture. From the start, we’re faced with the problem of what exactly is &lt;em&gt;software architecture&lt;/em&gt;. Uncle Bob settles on the very wide “every important decision about the technical aspects of the system being built”. Which has the nice property that it applies just as well to the 100 line utility script as it does to the Linux kernel, and just as well in the lowliest embedded system as in the loftiest distributed one. It’s not very concrete, unfortunately. However the book essentially then focuses on the “architecture in the small” (if I may) of components and component dependencies and their proper delineation and orientation.&lt;/p&gt;

&lt;p&gt;The book has a lot of chapters. This is great for snacking and context switching and getting quick wins, but bad for chapter-by-chapter summaries as I’m used to doing. So instead I’ll offer a mish-mash of the actual lessons of the book. More work, but hopefully more useful too. I’ll even throw in a diagram.&lt;/p&gt;

&lt;p&gt;The main problem is that of selecting a good architecture for the system that we are designing. By good here we mean that the system is easy to understand and extend. A good architecture allows for this growth and change to continue. It’s interesting to note that architecture in the sense discussed is not about the functionality of the system, though the performance, security, etc non-functionals do drive it.&lt;/p&gt;

&lt;p&gt;The biggest take away is a set of design principles that should be followed when designing a system. There are two classes of them: the lower-level and more commonly known &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID principles&lt;/a&gt;, and the higher-level component-level principles. By component here Uncle Bob means something like a jar, or dll. But in many ways, it can be extended to larger-grained things like processes, or services. I’ll summarise them here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The release/reuse equivalence principle: the “unit” of release is the unit of “release”. That is, versioned libraries/components can be used and reused, not anything “smaller”.&lt;/li&gt;
&lt;li&gt;The common closure principle: a component should contain classes that change for the same reason.&lt;/li&gt;
&lt;li&gt;The common reuse principle; a component should contain classes that tend to be used and reused together.&lt;/li&gt;
&lt;li&gt;The acyclic dependencies principle: the dependencies graph between components should not have cycles - it should be a DAG.&lt;/li&gt;
&lt;li&gt;The stable dependencies principle: dependencies should flow in the direction of stability.&lt;/li&gt;
&lt;li&gt;The stable abstractions principle: a component should be as stable as it is abstract. Abstract components (consisting of interfaces, ABCs, etc.) should be stable, and concrete ones less stable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The “Clean Architecture” itself is quite simple and follows from the principles. The main idea is to split the code into two layers - the inner “domain” layer and the outer “infrastructure” layer. The inner layer is the pure business logic of the system, while the outer layer handles things like persistence, communication, serialization, etc. Crucially the dependencies are from the outer layer to the inner layer. This is against the flow of control (and thus doing “Inversion Of Control” proper), and also from more concrete to more abstract, and from more variable to more stable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhoria141.com%2Fassets%2Fclean-architecture.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhoria141.com%2Fassets%2Fclean-architecture.png" alt="Components Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The domain layer can be further split into two sub-layers. The first or “core” layer deals with the very abstract and high-level procedures of a business. Things like computing interest rates, or scoring a loan application. These things tend to change very slowly and would exist regardless of the physical instantiation of a system. They would look the same regardless of whether the system is a mainframe program, web service, blockchain contract, , etc. The “application logic” layer deals with the specific use cases of the current system. Things like a clerk verifying the loan documents of a potential client, or a salesman marking an account as inactive. These use cases tend to change with some frequency, and they are bound to the physical instantiation of a system. They would look different depending on whether the system is a mainframe program, an IoT controller code, or low-code automation.&lt;/p&gt;

&lt;p&gt;The infrastructure layer has some canonical splits between presentation and persistence, but in general, here you can put anything which deals with the “world outside” the domain layer. From the database and the realities of turning entities into SQL rows in various tables to capturing user input and transforming it into commands of the various use cases. This layer is concrete and tends to change quite a lot. For that reason, it is called “dirty”. And the dirtiest of components is the main one. This is the component where the system starts - so perhaps it’s a class with the &lt;code&gt;main&lt;/code&gt; function or the initial script file - and where it configures all other classes, linking them together, wiring the abstract with the concrete.&lt;/p&gt;

&lt;p&gt;This means that in the domain layer we should have only &lt;em&gt;simple&lt;/em&gt; classes. There should be no ORM objects, no framework muddling, no concerns about serialization or input validation. Just simple classes doing simple things. Just like one would see in OOP tutorials as “simple” but “unrealistic” examples. I find this thing very attractive intellectually. First because it’s indeed “clean” of external libraries or frameworks - it’s just the application’s own code. But it also allows for the clear separation between the part that codes the business processes and the one which is just accidental complexity. Indeed, this part could just as well be plucked from its most likely webapp form, into a CLI application, or a testing suite.&lt;/p&gt;

&lt;p&gt;As an implementation note (mostly gotten from other sources though), the way the dependencies are manifest is that the domain layer will define some sort of interface - say &lt;code&gt;LoansRepository&lt;/code&gt;, which deals with the persistence of &lt;code&gt;Loan&lt;/code&gt; entities. The infrastructure layer will implement the &lt;code&gt;LoansRepository&lt;/code&gt; via a &lt;code&gt;PostgresLoansRepository&lt;/code&gt; that will handle speaking with a properly configured Postgres instance. It could also define &lt;code&gt;MySqlLoansRepository&lt;/code&gt; or &lt;code&gt;FlatFileLoansRepository&lt;/code&gt;. The main component will then need to configure that the &lt;code&gt;LoansRepository&lt;/code&gt; is resolved to the appropriate implementation for the run. This way, the domain layer doesn’t use anything from the infrastructure layer explicitly - it just says what it expects some other components to provide, and leaves it up to main and polymorphism to do the rest.&lt;/p&gt;

&lt;p&gt;The last section of the book is the &lt;a href="https://en.wikipedia.org/wiki/Catalogue_of_Ships" rel="noopener noreferrer"&gt;catalogue of details&lt;/a&gt;. Essentially all the pieces of technology that we’d commonly understand as central to a system: databases, the web, frameworks, etc are relegated to mere details. Something which we should tightly keep in the application layer, but abstracted away to the needs of the domain layer, rather than running the show. This thing was both the most counterintuitive in the whole book, but also one of the &lt;em&gt;truer&lt;/em&gt; and influential of the bunch. Indeed, building something with the “clean” architecture even imposes the use of libraries more than frameworks. Which is a trend I’ve seen in the industry anyway of shunning &lt;em&gt;big&lt;/em&gt; and &lt;em&gt;all-encompasing&lt;/em&gt; frameworks like Rails or Spring and moving towards simpler frameworks for special use-cases (and perhaps there’s even some causality there to look at).&lt;/p&gt;

&lt;p&gt;There’s a link here to &lt;a href="https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)" rel="noopener noreferrer"&gt;hexagonal architecture&lt;/a&gt;, the &lt;a href="https://medium.com/@shivendraodean/software-architecture-the-onion-architecture-1b235bec1dec" rel="noopener noreferrer"&gt;onion architecture&lt;/a&gt; and even &lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design" rel="noopener noreferrer"&gt;domain driven design&lt;/a&gt; (to an extent). Indeed I’ve come to understand these architectures are a sort of large scale software design pattern for structuring the codebase. Ways in which it is useful to organize the classes/modules of a system, which we’ve observed to work and allow for easy understanding, reasoning, and expansion. On the other hand they’re not set in stone. Like all patterns they are (or should be) guidelines - each system will be different and have goals and constraints such that the form of &lt;code&gt;$named architecture&lt;/code&gt; it uses will look different from another’s or from the standard. That’s why I think the principles are the most important part in the end. You can get something radically different than the “Clean Architecture”, but if it follows the principles, it would still be a good thing.&lt;/p&gt;

&lt;p&gt;Besides reading this book I also watched a bunch of talks, both from Uncle Bob and from others. I’m linking them here because they serve to clarify, contextualizie, and expand the understanding of clean architecture. They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=2dKZ-dWaCiU" rel="noopener noreferrer"&gt;Clean architecture and design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=o_TH-Y78tt4" rel="noopener noreferrer"&gt;The principles of clean architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=IAcxetnsiCQ" rel="noopener noreferrer"&gt;Implementing clean architecture in .NET Core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=SxJPQ5qXisw" rel="noopener noreferrer"&gt;The clean architecture with Ian Cooper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=dK4Yb6-LxAk" rel="noopener noreferrer"&gt;Clean architecture with ASP .NET Core 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=18IqltQ4XE4" rel="noopener noreferrer"&gt;Clean architecture in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=vKbVrsMnhDc" rel="noopener noreferrer"&gt;Achieveing maintainability with the hexagonal architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ujb_O6myknY" rel="noopener noreferrer"&gt;More testable code with the hexagonal architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=u6oTg5oRH24" rel="noopener noreferrer"&gt;Hexagonal architecture in DDD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I couldn’t end before mentioning the final chapter. It’s a rundown of Uncle Bob’s past projects. It was a fun read in itself but two things stood out. One was that Bob’s first gig was in 1970 programming a computer for some union’s accounting needs. This was a mere 25 years after the first computers ever were built to help with the atomic bombs. That’s a massive achievement to go from the smartest minds of a generation working on the cutting edge to a fresh highschool grad of 18 years working on an old (by then) machine in the mundane field of union accounting. The second was just how brutal the developer experience was back then. Punched cards, days long edit-compile-test cycles, assembler everywhere. I’m not 100% I would have found being a programmer so interesting during those times. I’m hooked on our modern tooling.&lt;/p&gt;

&lt;p&gt;Anyway, that’s it from me. There’s a lot more to the book, but hopefully, this has piqued your interest. Stay safe ‘till the next one.&lt;/p&gt;

</description>
      <category>bookreview</category>
      <category>post</category>
    </item>
    <item>
      <title>Friday Blast #95</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Fri, 06 Nov 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/friday-blast-95-4ecc</link>
      <guid>https://forem.com/horia141/friday-blast-95-4ecc</guid>
      <description>&lt;p&gt;&lt;a href="https://blog.clairvoyantsoft.com/productionalizing-spark-streaming-applications-4d1c8711c7b0?gi=5cae7fb77bd1"&gt;Productionizing Spark streaming applications (2019)&lt;/a&gt; - we had to use Spark streaming for a project at &lt;a href="https://bolt.eu"&gt;Bolt&lt;/a&gt;, and this guide proved mighty useful for getting us in the right headspace for tackling the problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://engineering.fb.com/2020/08/17/production-engineering/async/"&gt;Asynchronous computing at Facebook (2020)&lt;/a&gt; - an overview of Facebook’s complex system for handling “notifications” and “notification-like events”. A message queue in a way. As a side-note, I’ve noticed that systems that are essentially message queues (chat systems, notification systems, etc.) don’t ever seem to be implemented as an infrastructure-level message queue (Kafka, SQS, etc.), but rather in a traditional fashion (mixes of databases, queues, caches, servers, etc.).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=-N9i-YXoQBE&amp;amp;feature=youtu.be"&gt;Big data architecture patterns (2014)&lt;/a&gt; - a short overview of how a modern-ish data infrastructure layer looks like - data lakes, ML systems, etc. included.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codeascraft.com/2020/08/17/mutation-testing-a-tale-of-two-suites/"&gt;Mutation testing - a tale of two suites (2020)&lt;/a&gt; - about how Esty used &lt;em&gt;mutation testing&lt;/em&gt; to migrate from one test framework to another. It was the first time I heard of mutation testing (with this definition at least - but the name sounds familiar). It is a test for tests essentially. It applies a batter of mutations to the code base, and runs the test suite on it. Ideally the test suite should fail in the appropriate manner. Quite an interesting and powerful code quality tool - a step above just having tests, and in the realm of code coverage tooling, fuzzing, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=9a1PqwFrMP0&amp;amp;feature=youtu.be"&gt;An introduction to CQRS and Event Sourcing patterns (2017)&lt;/a&gt; - again an intro talk on these two more advanced architecture patterns.&lt;/p&gt;

</description>
      <category>fridayblast</category>
      <category>links</category>
      <category>post</category>
    </item>
    <item>
      <title>Friday Blast #94</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Fri, 30 Oct 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/friday-blast-94-4iof</link>
      <guid>https://forem.com/horia141/friday-blast-94-4iof</guid>
      <description>&lt;p&gt;&lt;a href="https://github.blog/2020-08-13-why-write-adrs/"&gt;Why write ADRs (2020)&lt;/a&gt; - architecture decision records (ADRs) are a form of technical documentation. They cover the big technical decision made on a project, in a sort of syntehsized fashion. Much like a design doc, but without going into the nitty-gritty.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rachelbythebay.com/w/2020/10/26/num/"&gt;Type in the exact number of machines to proceed (2020)&lt;/a&gt; - a nifty double-check for potentially destructive commands of all kinds. Don’t just &lt;em&gt;do it&lt;/em&gt; or require a simple &lt;em&gt;Yes/No&lt;/em&gt; answer. Rather ask the person to work a bit for the answer and also tie it to the magnitude of the mutation - ie number of machines affected by the change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=vKbVrsMnhDc&amp;amp;feature=youtu.be"&gt;Achieving maintainability with hexagonal architecture (2019) #video&lt;/a&gt; - another short intro to hexagonal architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://danco.substack.com/p/homesteading-the-twittersphere"&gt;Homesteading the Twittersphere (2020)&lt;/a&gt; - an interesting take on why there are so many high-quality &lt;em&gt;analyst-type&lt;/em&gt; blogs and newsletters lately (the author included). Humans value &lt;em&gt;status&lt;/em&gt; quite a lot, but in an abundance of information scenario, the old patterns of status via wealth or via power don’t really help in establishing the proper hierarchy. But status via gift does. Much like with open-source software many years earlier. Put out some complex and useful software for free, benefit from the recognition, and get extra IRL rewards from this.&lt;/p&gt;

</description>
      <category>fridayblast</category>
      <category>links</category>
      <category>post</category>
    </item>
    <item>
      <title>Friday Blast #93</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Fri, 23 Oct 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/friday-blast-93-1d8m</link>
      <guid>https://forem.com/horia141/friday-blast-93-1d8m</guid>
      <description>&lt;p&gt;&lt;a href="https://www.johnbcoughlin.com/posts/floating-point-axiom/"&gt;Taming floating point error (2020)&lt;/a&gt; - a brief overview of what error means in &lt;em&gt;floating point&lt;/em&gt; and how it affects work. What I found most interesting was the discussion on error analysis and error propagation through a computation. This was one area I didn’t have a good mental model of how to approach from uni days, and it turns out that (at least conceptually) it is quite straightforward and elegant. Indeed, I have an even higher appreciaton for the design of the floating point standard now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gopiandcode.uk/logs/log-bloomfilters-debunked.html"&gt;Bloom filters debunked (2020)&lt;/a&gt; - apparently there was an error in the analysis of Bloom filters false positive rates lurking for 30 years. Indeed the last step of the analysis seemed a bit hand-wavy the first time I encountered it. The authors used &lt;code&gt;coq&lt;/code&gt; to provide a formal proof of the known correct form and increase our confidence in it.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.daemonology.net/blog/2020-09-20-On-the-use-of-a-life.html"&gt;On the uses of a life (2020)&lt;/a&gt; - the author of&lt;code&gt;tarsnap&lt;/code&gt; (and inventor of key derivation methods in cryptography) got called out that essentially he wasted his life making backup software. This is his response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lethain.com/finding-the-right-company/"&gt;Finding the right company to reach Staff engineer (2020)&lt;/a&gt; - another one from Will Larson. Staff roles are those very-senior engineering roles in a company, and the article is about alignment and expectation setting in order to reach that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Q_bJVokYLRI&amp;amp;feature=youtu.be"&gt;What engineering managers should do and why we don’t (2019) #video&lt;/a&gt; - a short introduction to management for engineers. In video form.&lt;/p&gt;

</description>
      <category>fridayblast</category>
      <category>links</category>
      <category>post</category>
    </item>
    <item>
      <title>Radical Candor Review</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Thu, 22 Oct 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/radical-candor-review-4hd5</link>
      <guid>https://forem.com/horia141/radical-candor-review-4hd5</guid>
      <description>&lt;p&gt;This is my review of &lt;a href="https://www.radicalcandor.com/"&gt;Radical Candor&lt;/a&gt; by Kim Scott. This is a management book as you can surely surmise. The central idea is that one should practice &lt;em&gt;radical candor&lt;/em&gt; in a work environment - a style of interacting with others where one both seeks and offers good and constructive and sometimes hard to hear feedback.&lt;/p&gt;

&lt;p&gt;While I found the idea worthy, the book itself felt quite the slog. The message itself is OK, and there’s ample storytelling, justification, and instruction around it. But that can only fill so much book. Hence the bigger part of the book deals with general “modern” management approaches. The kind of stuff you can read about in &lt;a href="https://dev.to/horia141/the-managers-path-review-3fc"&gt;The Manager’s Path&lt;/a&gt; or &lt;a href="https://dev.to/horia141/an-elegant-puzzle-review-475i"&gt;An Elegant Puzzle&lt;/a&gt;. It’s also stuff that I am more or less doing as a manager. Hence my earlier characterization as a slog.&lt;/p&gt;

&lt;p&gt;The most worthwhile part was the first one consisting of four chapters. These only dealt with radical candor in itself and why one should care, with copious examples and an analysis of the various facets of it - from relationship building to delegation.&lt;/p&gt;

&lt;p&gt;The second part focused on implementation. From this only the last chapter I found useful, but mostly because it had a bunch of easy to apply tips and tricks for time management, meeting structuring, etc. Stuff I could steal right away.&lt;/p&gt;

&lt;p&gt;Even given all of the above I am not 100% would want to commit to such a thing, and follow the protocols. I do think a large part of this is achieved via simpler things like building a human relationship with your colleagues and reports, and having structured career conversations. The rest can surely help, but the delta might not be sufficient.&lt;/p&gt;

&lt;p&gt;Anywho, at least the highlighted chapters are interesting and worth to dig deeper into. And if you’ve never read any other management book this one isn’t a bad start at all.&lt;/p&gt;

</description>
      <category>bookreview</category>
      <category>post</category>
    </item>
    <item>
      <title>Announcing Jupiter Release 0.5.1</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Sun, 18 Oct 2020 00:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/announcing-jupiter-release-0-5-1-54lb</link>
      <guid>https://forem.com/horia141/announcing-jupiter-release-0-5-1-54lb</guid>
      <description>&lt;p&gt;I’ve prepared a minor release - &lt;code&gt;0.5.1&lt;/code&gt; - which contains a lot of goodies for recurring tasks. This version introduces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recurring tasks can have &lt;em&gt;active intervals&lt;/em&gt;. Only during this interval will inbox tasks be generated. This can be open ended of course.&lt;/li&gt;
&lt;li&gt;Inbox tasks from recurring tasks now have the year included in the name.&lt;/li&gt;
&lt;li&gt;Reporting on habits also shows a “completion ratio” broken down by sub-periods.&lt;/li&gt;
&lt;li&gt;Inbox tasks now have an &lt;em&gt;actionable date&lt;/em&gt;. They’ll be visible to work on one week before this. Recurring tasks have been updated to allow generation of such fields too.&lt;/li&gt;
&lt;li&gt;Fix a timezone issue with recurring tasks generation.&lt;/li&gt;
&lt;li&gt;Fix an issue with smart list syncing which caused every smart list to contain every smart list item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always checkout the &lt;a href="https://jupiter-goals.readthedocs.io/en/stable/install/"&gt;installation instructions&lt;/a&gt; to find out how to get hold of the latest version.&lt;/p&gt;

</description>
      <category>jupiter</category>
      <category>post</category>
    </item>
    <item>
      <title>Friday Blast #92</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Fri, 16 Oct 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/friday-blast-92-177n</link>
      <guid>https://forem.com/horia141/friday-blast-92-177n</guid>
      <description>&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/50966676/why-do-arm-chips-have-an-instruction-with-javascript-in-the-name-fjcvtzs"&gt;Why do ARM chips have instructions with JavaScript in the name (2018)&lt;/a&gt; - remember kids, if your programming language becomes popular enough, its primitive operations will become CPU instructions. I wonder if there’s been any analysis done on this? Like look at where a sufficient sample of programs spend their time and make that into instructions. You’d need a size/complexity heuristic to not just leave it at&lt;code&gt;main&lt;/code&gt; but I’m sure companies such as Google or AWS which run big sever workloads would have the data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=QyJZzq0v7Z4&amp;amp;feature=youtu.be"&gt;Why isn’t functional programming the norm? (2019) #video&lt;/a&gt; - the short answer is “it’s complicated”. The longer answer is that FP languages lack either a “killer app” or some serious corporate backing. Add do that a bit of a definitional problem - like what is an FP language? Is Common Lips where you can have imperative constructs more FP than Rust where everything is immutable by default? OTOH many modern languages have functional programming capabilities, so in that sense FP is the &lt;em&gt;present&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.theobservereffect.org/daniel.html"&gt;The observer effect with Daniel Ek (2020)&lt;/a&gt; - an interview with Spotify’s CEO. There’s a lot to take in, but perhaps for me the most interesting part was about the coaching he provides to his reports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.profgalloway.com/airbnballer/"&gt;AirBnBaller (2020)&lt;/a&gt; - an analysis of why in the long run AirBnB might be the “breakout” startup of the 2010s, eclipsing the likes of Uber, or Palantir. Right now, things are dire with the global pandemic, but it won’t last forever. If anything, as a supply gateway AirBnB will have a very strong hand to play vs traditional hotel chains.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://rachelbythebay.com/w/2020/10/14/lag/"&gt;40ms of latency that just won’t go away (2020)&lt;/a&gt; - another case of being tripped up by Neagle’s algorithm for TCP - which batches short message bursts into bigger chunks to more efficiently utilize bandwidth. At the expense of latency. Disabling it is set via some flag on the socket. What I always find peculiar about these low level APIs is how much they had that you’re doing a “big thing(tm)” with these things.Sometimes it’s not even clear it works or is enough to work. I definitely like the higher level API where you’d instantiate a &lt;code&gt;NoBufferingConnection&lt;/code&gt; or something of the sort and make it really clear and semantic what you’re trying to achive.&lt;/p&gt;

</description>
      <category>fridayblast</category>
      <category>links</category>
      <category>post</category>
    </item>
    <item>
      <title>Friday Blast #91</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Fri, 09 Oct 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/friday-blast-91-ha2</link>
      <guid>https://forem.com/horia141/friday-blast-91-ha2</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=996OiexHze0&amp;amp;feature=youtu.be"&gt;OAuth 2.0 and OpenId Connect in plain english (2018) #video&lt;/a&gt; - A gentle guide to these protocols for managing authorization / identity and its delegation. It’s one of those things every developer building web applications should know about, but there’s a dearth of good material out there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=t7iVCIYQbgk&amp;amp;feature=youtu.be"&gt;Modern banking in 1500 microservices (2020) #video&lt;/a&gt; - An overview of Monzo’s architecture and a little bit of their tech stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Bz2EXg0Fy98&amp;amp;feature=youtu.be"&gt;Did you accidentally build a database? (2016) #video&lt;/a&gt; - one of the founders of CochroachDB talks about various large-scale systems and how they’re essentially poorly implemented databases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.johndcook.com/blog/2020/10/05/understanding-statistical-error/"&gt;Understanding statistical error (2020)&lt;/a&gt; - many models can be written as &lt;code&gt;R(X) + \epsilon&lt;/code&gt;, where &lt;code&gt;\epsilon&lt;/code&gt; is some noise factor with following some distribution and &lt;code&gt;R(X)&lt;/code&gt; is some deterministic relation. This &lt;code&gt;\epsilon&lt;/code&gt; is not an error of reality, but of our own modelling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rootsofprogress.org/industrial-literacy"&gt;Industrial literacy (2020)&lt;/a&gt; - a bunch of things to understand about our modern industrial society, before attempting to change anything.&lt;/p&gt;

</description>
      <category>fridayblast</category>
      <category>links</category>
      <category>post</category>
    </item>
    <item>
      <title>Friday Blast #90</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Fri, 02 Oct 2020 07:00:00 +0000</pubDate>
      <link>https://forem.com/horia141/friday-blast-90-47fa</link>
      <guid>https://forem.com/horia141/friday-blast-90-47fa</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=ujb_O6myknY&amp;amp;feature=youtu.be"&gt;More testable code with the hexagonal architecture #video (2019)&lt;/a&gt; - the &lt;em&gt;hexagonal architecture&lt;/em&gt; is the name given to an clean and interesting approach to building large “business” applications. There is essentially a core of logic, surrounded by “ports” for persistency, communication, etc. and “adapters” that allow the logic to make use of the ports.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=u6oTg5oRH24&amp;amp;feature=youtu.be"&gt;Hexagonal architecture in DDD #video (2015)&lt;/a&gt; - another take on this, with some domain driven design bits thrown in. A lot of folks are doing both of these at the same time, and the match seems good.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dropbox.tech/infrastructure/how-we-migrated-dropbox-from-nginx-to-envoy"&gt;How we migrated Dropbox from Nginx to Envoy (2020)&lt;/a&gt; - in three words - the hard way! This is a surprisingly detailed look at what I can imagine is the equivalent of switching the engine in flight on an airplane.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://engineering.linkedin.com/architecture/brief-history-scaling-linkedin"&gt;Brief history of scaling LinkedIn (2015)&lt;/a&gt; - The article was kind of light on the details, and is quite out of date. On the other hand, LinkedIn is an often overlooked tech powerhouse, with a lot of custom technology they had to build in order to handle their scale. So it’s well worth a read to see when and how these things got their start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lethain.com/work-on-what-matters/"&gt;Work on what matters (2020)&lt;/a&gt; - can’t have a friday blast without a Will Larson post. The main idea is that as one advances through a career (not in time, but in impact and scope), one needs to deliver more in less time. Hence, you need to focus on what matters, and aggresively cut non essential work (drop it, or delegate it, basically).&lt;/p&gt;

</description>
      <category>fridayblast</category>
      <category>links</category>
      <category>post</category>
    </item>
    <item>
      <title>Announcing Jupiter Release 0.5.0</title>
      <dc:creator>Horia Coman</dc:creator>
      <pubDate>Tue, 22 Sep 2020 07:20:05 +0000</pubDate>
      <link>https://forem.com/horia141/announcing-jupiter-release-0-5-0-2ec3</link>
      <guid>https://forem.com/horia141/announcing-jupiter-release-0-5-0-2ec3</guid>
      <description>&lt;p&gt;As promised, the &lt;code&gt;0.5.0&lt;/code&gt; release comes much faster than the &lt;code&gt;0.4.2&lt;/code&gt; one. It includes a single change, namely &lt;a href="https://jupiter-goals.readthedocs.io/en/stable/concepts/smart-lists/"&gt;smart list&lt;/a&gt;. It’s a significant addition however, and the first foray outside task-planning for Jupiter.&lt;/p&gt;

&lt;p&gt;Smart lists essentially are lists. You can use them to build lists of books to read, movies you’ve watched, etc. Long term, there’s gonna be some actual smartness added to them - syncing with YouTube, or Amazon, or Spotify, but right now they’re pretty basic.&lt;/p&gt;

</description>
      <category>jupiter</category>
      <category>post</category>
    </item>
  </channel>
</rss>
