May 9, 2024

How I use principles to develop engineering strategies.

Principles. We all have them, but how often do we spend thinking about them? Or even better, writing them down?

As I found myself evolving as a tech leader, I realized I needed to make some adjustments to the way I approached my work. I had to shift away from technical details and more towards strategic thinking. I’m sure this is a common situation leaders find themselves in, but letting go of the “work” wasn’t completely obvious to me right away. I was eventually able to reason that engineering teams are good at what they do. They’ll be able to figure out how to build whatever awesome thing we were building even without my amazingly witty and insightful code reviews. What they really needed from me as a leader was to have a plan ready for whatever was about to happen next. Holy shit! How do you anticipate the infinite possibilities of anything and everything that could happen next!?

People talk about natural leadership abilities, and there is truth to that, but you can hack your aura of leadership ability by having a standard playbook in your back pocket.

A great read on the subject of principles and system thinking is Ray Dalio’s 2017 book Principles. After reading Ray’s book I realized I had been leaning on my personal principles for success and there was even more I could be doing. I used to dismiss this approach as a matter of style. As if it were an aesthetic choice instead of the principled baselining that it actually was. Ray’s book gave a name to something I was already doing and opened my eyes on how to systemize it.

Functionally understanding your own principles can help you build a solid foundation for strategic thinking. These are my personal engineering principles. There are many like them, but these ones are mine…

1. Prefer free software.

I owe everything to being interested in gnu and linux during the time it was emerging. It was easy to pay attention to developments in open source projects because I could just read the source code. Keeping my ear to the ground I gained a reputation of being able to deliver prototypes and production systems rapidly at little cost to the organization.

Beyond the functional benefits of free software more importantly is the liberty it awards you. This is something I think Richard Stallman is really right about; free as in free speech, not beer. If you stick with free software you will never have to pivot at the whim of the license holder.

I have never once regretted building systems based on free software components. As the adage goes; Nobody ever got fired for choosing redis or postgres.

2. Sprint zero isn’t negotiable.

I have always felt that the delivery pipeline has to evolve with your product just like any other money making feature. Being able to get your product to your customer is a feature that should ship in sprint zero. Ignore at your peril. You know you will have to do it later anyway and by then it will be more complicated.

It’s better to start with a simple delivery mechanism that can reliably ship nothing. When sprint one comes around your team will already be comfortable enough to reliably ship your first features. As complexity in your project emerges so will your pipeline.

Do it before you start engaging in feature work. You don’t have to come up with the perfect pipeline, you just need to be devoted to getting what is currently available to your customers. Put an end to early stop energy by designing the “perfect pipeline” upfront. Instead establish a solid foundation your team enjoys using to ensure continuous delivery to your customers and iterate on it over time.

3. Refactor as you go.

I have experienced a lot of engineering teams who are confused about the role of refactoring in their job.

I’ve been in countless meetings standing between the engineering team and the product team. The engineering team wants to slow down and fix any fallout from their previous sprint. The product team can’t understand why we can’t keep forward momentum. The engineering team thinks it’s reckless to jump ahead. The product team questions how we have tech debt on something we just did. And so on, and so on… Refactor as you go and eliminate this common divide between product and engineering.

Sure, teams working on legacy systems can sometimes afford to take a break from feature work to plan a refactoring sprint, but in my experience that approach seems endless and I’ve rarely seen it make a dent.

Nope, you should just refactor the bits of the codebase the code you are introducing is touching. Otherwise known as the boyscout rule. Likely the up next task is adjacent to the feature you just shipped anyway. This approach is great because it absolves you of existing tech debt while you make a difference with the awesome new widget you are shipping. You can make your engineering manager and your product team happy in one foul swoop. Include a bit of uncertainty time in your velocity predictions. No one will notice a few extra hours and you will never end up in a two week refactoring sprint again.

For Sr Engineers the code review cycle is a great time point out refactoring opportunities. Use consistent language from a common reference such as Refactoring Guru. Over time your team will develop a refactoring shorthand and their submissions will show improved pattern foo.

Complacency toward everyday refactoring could be the reason why new systems often drift into legacy territory faster than they ought to. If you do a little bit everyday it will feel less daunting. You will be more in tune with your codebase and you may even discover connections that may have otherwise been elusive.

4. Be Lazy!

This one has gotten me in trouble with manager types and perhaps there is a more nuanced way to say it but I truly mean it in the best possible way. I tried to make this point on the maintainable podcast and I’ll qualify further here.

Back when mullets were cool the first time and I first got into programming I quickly learned that computers are amazing things. They do exactly what you tell them to do over and over again really fast! I marveled at how I could spend a bunch of time typing things into the computer once and then watch it happen a million more times with the click of a button. I could go downstairs to get a Coke while my computer was setting itself up to play Wolfenstien from that perfect batch script I just wrote. I’ve never lost that sentiment.

   

I’ll gladly trade 6 hours now writing a script to automate an hour of manual work to never have to do it again. This is what I mean by being lazy. Be lazy enough to code it instead of accepting it. Construct your masterpiece in the laziest possible way. The less code you write; the less bugs you have to fix; the less mess you have to maintain; and the less future problems you will encounter. Be lazy enough to fuel your excellence. Every once in a while you may even stumble upon something other people actually want. Billion dollar companies have been founded this way.

Don’t forget that Larry Wall sites laziness as the top virtue of a great programmer. And we should all listen to Larry Wall. Anyone who can pull off wearing a moustache and a hawaiian shirt knows what’s up.

5. Prefer reversible decisions.

The responsibility of making solid decisions for your team can be heavy. Your team is trusting you to not put them in and awkward situation while senior management and your peers are watching and keeping score. I’ve found that a good way to lessen the burden is to consider reversible decisions. Imagine how much freedom and decisiveness you would gain if your decisions didn’t actually matter? I’ve been able to prevent myself from getting stuck overthinking by lowering the stakes and making decisions that can change later with little cost.

   

You aren’t special. Unless you are working at the jet propulsion laboratory someone has likely created some prior work for you. Build your solutions on top of those building blocks. Let go of the outcome by shifting your mindset from absolutes to tradeoffs. Move forward and learn quickly. Adjust in smaller increments and reduce the risk of any major overhauls (or god forbid the dreaded rewrite).

Ensure reversibility with behavioral design patterns. Code simple abstractions and rest assured that it won’t matter if you made a good decision or not. Change your mind later. Couple with a feature flag setup and experiment without your customer even knowing.

6. It’s going to suck anyway.

In a not so distant point in spacetime I was leading a small frontend team. As often the case, half the team was sequestered to another project so it was just me and Betty holding down the fort. No problem, Betty and I were a great pair who counterbalanced each others strength’s and weaknesses perfectly. We were wrapping up a new feature and pairing on some late change requests. The changes were that dreaded combination of not important and urgent. I pointed out that the request was taking something away from the clean workflow Betty and I had already implemented. My generation X’ness must have rubbed off because Betty responded by proclaiming “ya, don’t they know it’s going to suck anyway?!”

This response delighted me. I thought wow, that’s so perfect. What a great take on perfection is the enemy of good. Perfectly articulated in the spirit of the Agile Manifesto: It’s going to suck anyway… and then it won’t. You can’t begin to improve on something until you start it. Coding should be creative and fun. It’s like learning an instrument. You wont be a good saxophone player after watching some instructional youtube videos. You have to live it and practice.

This was a great lesson that has evolved into a core principle for me and a reminder not to doubt my ship first instincts. Keep it simple, get it out there and see what happens.

Onward and upward.

When introduced to a new project I like to begin with my own personal principles. Every organization is unique and every problem is different. It helps me to have a solid foundation that I know I can rely on.

I really like working with teams to evolve principles to the organization or situation. Every retro is a great opportunity to make adjustments. Over time the organizations unique culture (or subculture) starts shining through this practice.

As a leader I then have a principled foundation that my team already believes in to help guide strategic planning.

If you’ve never put your own principles down in writing, you should try it. It can give you some amazing introspection to your engineering approach.