4 Guiding Principles for Software Engineers

Why these principles?

There’s been a few things going on at work and within the wider software industry:

  • AI is on everyones lips, and given its ability to generate large amounts of code, fear has grown as to what future exists for software engineers.
  • I’ve been talking to an engineer who is frustrated that they can’t land a “senior software engineer” title. They don’t understand what’s holding them back. They have 10 years of experience after all.

Different circumstances, but in both, I have seen a lack of understanding and application of foundational behaviours I expect to see in experienced software engineers.

In the AI case, the profession is not just about churning out code (that’s a topic for another time for the sake of brevity.) In the case of the frustrated engineer, they think they just need to learn more languages, do more courses, watch more tutorials. I don’t care if you know 1 language or 5. A good experienced engineer will pickup whatever technology is necessary and be productive in a timely manner. The main problem they have, is that they don’t follow any of the principles below.

I’ve hired software engineers. I’ve promoted software engineers. These foundational behaviours are what I have seen distinguish top level engineers from their peers. These foundational behaviours will set you up for a succesful career, ahead of the majority.

1. Persevere and grow from the unfamiliar

I can’t even count the number of times I’ve been stuck on a difficult problem throughout my 15 years of programming. I don’t think that problem will ever truly go away, not if you are pursuing new challenges or looking to dig deeper and further your understanding.

One problem I constantly observe, is a lack of grit. A lack of perseverance in overcoming the obstacle at hand.

With any new challenge, I tell myself “I will solve this”. Yes, that sounds a bit cheesy and lame, but having a strong mental fortitude and avoiding the pit of despair will help you to solve the problem at hand.

Generally when I’m stuck, it’s due to a lack of context or domain knowledge. So what do I do?

I start building context.

  • Do a google search, grab a book, watch a video. Do something to give you a fresh perspective
  • Try take something you’ve learnt (that’s now a part of your context), and build a small piece
  • While building, try to understand the scope of your problem. If it’s starting to feel “big”, break it down. Just get one small thing done.
  • Build on top of that small thing. Build momentum.
  • Repeat

Congratulations, you’ve learnt something and applied it. 🎉

Now the above is very abstract, I admit it. But that’s the point of these principles. I’m not here to give you the exact answer for your use case (it’s problematic if you expect that and want to grow as a software engineer - sorry).

2. Understand that “best practices” are a guide. Create practices for your given problem and context.

Whenever I hear or read the phrase “best practice” I cringe. That’s because it’s often used in statements such as:

  • “Let’s make this change because it’s best practice”
  • “We have to do standup, planning and retro as it’s best practice”
  • “That’s bad because it goes against best practice”

Please. Don’t. Do. This.
Please. Use. Your. Brain. 🧠

You can advocate for changes, compare solutions and adopt particular software delivery processes but make a conscious decision. Think about your problem, situation and constraints. Think about what the “best practice” gives you and if it makes sense against those dimensions.

Articulate your reasoning without the words “best practice” and I promise you will be a better software engineer for it. You will actually succeed in your goals, whether that’s solving a technical problem or influencing change (because you actually thought about it).

3. Manage complexity

Complexity is a honey pot for software engineers. For whatever reason, we are drawn to it like bees, and greedily consume as much of it as we can. Bzzz! 🐝

Complexity comes in many forms. One factor that contributes to complexity, is solving for edge cases and problems that we don’t have yet (just in case of course). You need to get comfortable balancing the “what we need now” vs “what we will need later” when building software. I’ve seen so many over engineered MVPs that were later dismantled as they failed to deliver the estimated customer value. And that’s ok! That’s part of building and experimentation! The point is, make sure you have something worth hardening first.

Complexity also exists in problem domains, some being more complex than others. We can’t get rid of all complexity in these situations, but we can manage it. An analogy that might help, is to think of a “complexity budget” (similar to the idea of an “innovation budget”).
Don’t use your complexity budget to:

  • Intentionally have three different actions that can happen depending on how fast the user clicks their mouse in your React UI.
  • Show five different error states with custom illustrations and recovery actions for errors that happen <1% of the time in practice (use a default error and move on).

Use your complexity budget on the core product.

Please remember:

  • Creating a complex solution does not imply you are a technically strong developer. Rather, it implies you lack the experience of witnessing a complex solution deterioate over time and fail to adapt to change.
  • Understand the complexity you are working with, and find ways to simplify and manage it.
  • KISS, YAGNI and WET are the only acronyms worth knowing. Forget DRY and SOLID, it does more harm than good. I’ve seen more problems caused from terrible abstractions than a few pieces of duplicated code (had to get a jab in at DRY somewhere).
  • Again, use your complexity budget on the core product, not side quests.

4. Read the code

This may seem like an obvious one, but I observe a lack of this in practice. A large number of software engineers simply don’t read enough code.

At the first sign of a roadblock, or confusion around interfacing with an API built by another team or external maintainer, they will request assistance (especially painful if working across timezones, and it takes at least a day to get a reply). Now I’m not against asking for help, but don’t let artificial barriers stop you from answering your own question and unblocking yourself.

Pull the repo for that package, look through the code, and try understand why it doesn’t work the way you expect.
If you see some syntax you don’t understand do some research and build that context, that’s how you learn.
If you see anything you don’t understand, start to unravel it piece by piece. Start to understand it enough to remove that initial roadblock. Yes, you will be slow at first, but over time, you will build speed to the point of reading it like English (or your native language)
Make this a habit.

Being able to read code fluently is a superpower. If embraced, you will be able to solve any software problem that you are presented with (yes, really). Your growth will accelerate, you will have more career opportunities and you will be a better software engineer.

But for this to be true, you truly need to understand, reason and critically think about the code you are reading.