Programmer as wizard, programmer as engineer
We have different design goals and constraints when we’re doing one [wizarding] or the other [engineering]. With engineering, we’re tasked with the long term maintenance of a piece of software, and we also become concerned with many lower-priority properties, such as its performance. With wizarding, we’re often best served by designing for ease of throwing code away rather than maintaining it. Well-engineered code is irreplaceable, but well-cast spells should be transient.
In this post, Ted Kaminski talks about two different styles of programming: wizarding and engineering. At first, all startup prototypes/Minimum Viable Products are created as fast as possible: we need to see if our startup idea is viable first. If the business grows, the developers need to transform this prototype to a stable product, able to grow and include new features. Developers need to shift from the wizarding attitude (everything is temporary) to an engineering mindset (long term maintenance, the software needs to work for a long time and is used by many users).
These two "styles" -and the transition between them- reminds me of the Makers vs Menders difference. A Maker is a developer who love to create stuff quickly and are excited by deadlines and time pressures. On the other hand, a Mender likes older codebases, is satisfied by fixing longstanding bugs and making the whole system more stable and more secure.
How do we do switch from one style to the other, though? The author suggests we should write enough tests to be sure everything is working, separate big applications into microservices when it makes sense, and rewrite critical parts of your system in languages that can offer static (or gradual) typing and good tooling.
Separating concerns into their own services -when it makes sense and does not lead to a distributed monolith- can help reason about the system as a whole, and making each service faster and more stable, especially when paired with the right dose of testing.
I'm also a fan of static languages such as Rust (even in the browser!), that can feature good tools such as cargo, and an expressive language that helps developers implement critical systems with fewer errors.
I'd also like to suggest to recognize when the project should move from wizarding to engineering. Failure to understand when the project needs to transition to the engineering state, and plan for it, is probably the most unappreciated problem I encountered in my career so far. If the team can't slow down and fix growing pains, they will only get stronger and mutate into outages, and the team won't stop firefighting production issues. My suggestion is to keep note of small issues, or tasks that are taking longer than expected for technical reasons, and expose them during a retrospective. Having senior engineers in the team also helps, especially if they are experienced with the project's technology stack.
So, I hope you liked the first post of Interesting Links, a new column where I highlight interesting articles, with my own comments and thoughts. If you liked this post, you should totally share it on Twitter, or support me on Ko-fi.