Pragmatic Principles for Software Engineers
Core software engineering principles for writing scalable, maintainable, and production-ready code inspired by the Pragmatic Programmer mindset.
The Essential Pragmatic Engineering Rules Every Developer Should Live By
I have listed some of the most essential rules every software engineer should know. These principles are taken from The Pragmatic Programmer by Andy Hunt and Dave Thomas.
Algorithm speed 🚀
Although this is nothing new for any experienced engineer, you should always be careful when dealing with multiple loops.
The complexity of a simple loop is O(n). Now, if we introduce a function or method inside it that also loops over something, the complexity will immediately become O(m × n). Always consider the side effects of any change in your code to ensure there is no impact on the scalability of your application in the long term.
Best isn’t always best 💡
Be aware that premature optimisation is not always the appropriate decision at the start of any project or proof of concept (POC). At that stage, it is impossible to know the traffic or the eventual iterations and direction of your application. Instead, it is usually wiser to keep things simple and small.
Be pragmatic. Not a coincidental “Code Monkey” 💥
Coding is not a mechanical job. As a pragmatic programmer, you need to make the right decisions. You need to think critically about all code and the impact it could have, as well as how your code and software architecture will scale in the future.
On the other hand, a coincidence programmer will write code without planning or looking at the big picture. They tend to add mechanical code in an inefficient manner.
Automation 🤖
Automating things is an important concept in the lifecycle of an application. However, like optimisation, if you automate too early things that might not be repetitive, it will only add unnecessary extra hours of work.
Learn what you need 📝
Learning the right tools well (such as Jenkins, Docker, a framework, shortcuts, your favourite IDE, or a benchmarking tool) will be one of your greatest strengths in your career.
Don’t write Dodo-Code 🦤
Writing dodo code implies that your code will not adapt well over time. The dodo did not adapt to the presence of humans. They were once abundant on the island of Mauritius before going extinct. Do not give the same future to your code. Keep your codebase agile and well maintained, using good design patterns that make new changes and feature implementations easy.
Testing before production 🍳
Although this can seem obvious, too often I see last-minute “important” changes that need to be shipped to production as soon as possible. And since the software engineers do not have the time or necessary resources, they proceed with shipping the changes right away to please their manager or C-level stakeholders.
This can end up quite badly. It is always easy to underestimate what can go wrong until you wake up one morning and the entire online service is down because of a missing assignment operator or a missing semicolon or comma causing incorrect behaviour. No matter how much you trust the release, you are never 100% sure of the consequences of each change in your code. Integration and acceptance tests can be very useful here.
A good practice is also the use of the “chaos monkey” technique in your application to make sure there are no obvious issues with it.
The boy-scout rule 🧹
The Boy Scout rule says: “Always leave the campground cleaner than you found it.”
It means you should clean up even when others leave things messy, no matter the excuses. It does not matter whether you created the mess or not. The rule aims to make the codebase incrementally better, step by step, every time you touch a legacy or outdated part of the code.
So, every time you need to add or change something in an existing function or class, identify a small improvement you can also make. A tiny improvement will not introduce new problems or make the code review harder, but those small improvements, applied consistently, will make the entire codebase much cleaner over time.
Debugging mindset 🧠
Before debugging, it is important to adopt the right mindset. Debugging can be tricky and time-consuming.
Here are some rules of thumb that make this “mental digging” more pleasant 🤠:
Immediately think about which tier or layer of your code the problem could come from.
Failing early will tell you more directly where something is not working. Always fail early instead of quietly moving to the next function when something is not supposed to happen.
Use breakpoints and exception tracing.
Speaking to your rubber duck, an AI chat, or a colleague will help you see the bigger picture of what you are working on. Very often, you will have an “aha” moment when you explain what is not working, what has changed, and where you looked in the code.
Step back and consider the overall architecture and infrastructure to locate the problem more easily.
Rubber Duck debugging technique 🐥
Happy Debugging Day! 🤠 Enjoy solving and tackling your technical challenges! 🎯
I’ve built plenty of projects on my GitHub over the years. Feel free to browse through for inspiration or contribution.
I’ve got more exciting content coming your way on my LinkedIn. So, make sure to hit that follow button so you don’t miss out!

