The Software Engineer Oath
Striving for the unattainable is worthwhile
Have you read the previous blog yet?: The Development Process, part 2?
In this series, I have discussed many aspects of the software engineering profession that I feel a true professional needs to consider. Of course, my perspective is coloured by my own abilities, experiences, and desires. Still, I hope it has provided insights into the world of software development, particularly the roles and responsibilities of the software engineer within it.
We’ve discussed many topics, and I feel it is good to revisit them here to refresh our memories.
What I haven’t touched
But first, a note on completeness. Despite my best intentions, and despite this series being ten entries long, I could not discuss everything I wanted. Some aspects of software development I could not find a place for; others, I only remembered a few entries too late. And some I did discuss, but in hindsight, I did so far too briefly. So, for the sake of completeness, I would have loved to talk more about the importance of cloud development, various infrastructure concerns, data storage challenges, orchestration, abstraction, decoupling, the potential of Artificial Intelligence (especially the impact of coding Copilots), the importance of learning, how to refactor code, when to fix legacy and when to rebuild it, and even a small pointer on how to say “no”. But alas, I did not. But now I’ve at least mentioned all these topics, and you can just pretend that I said some very insightful things with regard to each of them.
What we have discussed
In the first part, we started with why I felt a blog series on software engineering craftsmanship was necessary in the first place. The degree to which our field lacks professional, ethical, and moral guidelines is staggering, and the youth of the field is not an excuse, especially since the field is growing exponentially. I also tried to illustrate the difference between coders, programmers, and engineers, at least in how I use those terms. Paraphrasing myself, coders focus on code by manner of functions, programmers are responsible for features, and engineers are accountable for software, with all its abstractions, dependencies, and real-world concerns.
In parts 2 and 3, we discussed the code-level responsibilities of a software engineer. I mentioned that seeing code styles and patterns as the be-all-end-all for writing quality code misses the mark and causes developers to focus on the equivalent of neat handwriting instead of the message to write down. Instead, I advocated for three things. One, follow a clear coding process (e.g., pair programming, code review, test, merge to the main branch). Two, automate agreed-upon styles and standards using tooling. And three, whatever you do, write testable and automatically tested code. Further, I posited that good code does not document itself, and advocated for learning to write quality documentation (or having it generated), especially concerning the why’s and when’s of the choices made. The what of the code does not need to be documented (unless we’re talking, for example, about public APIs), as long as you make sure that the code can be easily debugged and has tests describing the various code flows.
In parts 4 and 5, we zoomed in on the software-level responsibilities. I argued that quality code is only important insofar as it serves to heighten the quality of software holistically. I then mentioned a few ways to measure the quality of your software, and why it is important to do so. Defect density measures the correctness of your software. Reliability is measured with Mean Time Between Failures and Mean Time To Repair. The profitability of your software can be established by calculating the Return On Investment. I discussed load testing, response time, throughput and resource utilization as ways to determine performance. Usability can be quantified using analytics and questionnaires, or sometimes something simple like the number of clicks per common task. And finally, we discussed integrability, which is expressed in integration lead time and the number of integration points.
In these two parts, I also mentioned the importance of understanding why and when we take on technical debt and what measurements to use to determine when we should start repaying it. Cycle Time, Bug Ratio, and especially Technical Debt Ratio will help to gain insights into software quality and the costs of technical debt. And finally, I mentioned DevOps, its crucial feedback loop, and the importance of taking responsibility for the entire process: planning, building, continuous integration, deployment, and operations, which feeds back into planning. I stated that a software development project should employ DevOps unless it was unable to because of external factors.
In the next two parts, 6 and 7, I could finally start talking about what is starting to become a career-defining phrase for me: ethical software development. Writing capital G Good software requires making sure you create secure software, the importance of keeping up to date regarding security, and why security by design is paramount. A software engineer should also be well-informed regarding privacy and governance, and we discussed how to do that as well. We investigated the meaning of addictive design and why being transparent to your users is important. Also, we looked at how avoiding bias and aiming for inclusivity are concerns for a software engineer as well. We evaluated the pros and cons of open-source software. I discussed the importance of writing transparent and transferable code so those taking over your software can take ownership when you leave and be accountable. And in the most idealistic paragraphs in this entire series, I urged you to take both the cultural and environmental impact of your software into consideration.
In parts 8 and 9, we took another look at the software development process and the people we work with. We looked at the problems with Waterfall (and what could still be salvaged from it) and the challenges with Agile working. I advised you to increase efficiency by using meetings as structure, but also discussed how to keep those meetings efficient. We dove into the iron triangle and how Cost, Time, and Scope should all be considered when talking about deadlines. We ended by discussing how working with people is essential to being a software engineer. We tried to determine how Product Leadership related to Product Management and Product Ownership, and I argued that a Product Leader in some form is an essential member of any software development team. We also looked at Tuckman’s Stages of Group Development, and how being aware of its stages (Forming, Storming, Norming, Performing, and Adjourning) can help a software engineer make the team more efficient, as each stage implies different needs.
My final argument was that for quality software to exist, a software engineer needs to be able to guarantee a few key team factors, namely equality, emotional safety, and enjoyment. Those are all necessary to foster a team culture where people can contribute together to create quality software.
One last metaphor
In the very first entry in this series, I used the metaphor of a doctor to illustrate the importance of being accountable and professional in our work. Lucky me, it is that same metaphor that will close out this series. As you probably know, when doctors graduate, they swear an oath. (Note: this is no longer the Hippocratic oath. In fact, there are many different oaths currently in circulation. They should standardize that!) In their oaths, doctors usually state how they will try to behave as a professional and to what standards they will hold themselves. I feel software engineers need a similar approach.
Once you have made the choice to be an engineer instead of a coder or programmer, I believe you should swear an oath on what that choice means, and why it matters. So, in this last part, I present to you The Software Engineer Oath, which I’ve named Dijkstra’s Oath, after Edsger W. Dijkstra (of Dijkstra’s algorithm). It neatly summarizes, in my opinion, the absolute minimum level of responsibility each software engineer should uphold to ensure that the field of software engineering continues to grow in a healthy, moral, and profitable way.
I solemnly swear to uphold the following principles of craftsmanship and excellence in my work as a software engineer. I commit to the following:
I will strive to write maintainable, testable, and efficient code.
I will make sure the quality of my code is determined automatically, with tests covering the unit, feature, integration, and application levels.
I will embrace automation to enhance productivity, using tools for assessing the styling and quality of my code and software.
I will make sure my code and my software are documented comprehensively, detailing the when, how, and why of my choices.
I will take security, privacy, and governance into account from the earliest possible stage.
I will use metrics to quantify the quality of my software and use those metrics to create a feedback loop that drives future development.
I will work cooperatively with others, valuing diverse perspectives, and contribute to a culture of equality, emotional safety, and enjoyment.
I will do my best to help set realistic deadlines, based on available data.
I will take responsibility for my software, from the planning phase, through the development phase, all the way to the deployment and operation of my software.
I will commit to lifelong learning, staying up to date with the latest technologies, trends, and concerns in the ever-evolving field of software development.
In the pursuit of these principles, I recognize that software engineering is not just about writing code, it is about creating solutions that positively impact society.
Where to go from here
I want to thank you, the reader, for reading all ten entries in this series (or at the very least, this final one). Please, don’t let the end of this series stop you from sending me your thoughts and comments, as they have been very insightful. (Okay, let’s be fair, most of them have been insightful.) Specifically, I’d love to see your take on a software engineering oath.
Especially once the series’ end drew near, quite a few of your comments asked me whether, after the series ended, I intended to start another series. It is now time to answer that question.
My plans are to first focus on a few stand-alone blogs discussing the various new developments in AI. I started this series in early 2023, with monthly installments, and this year has seen an unprecedented amount of attention for AI, especially generative AI. That field has always had my interest, and I feel I have some worthwhile things to say about the current possibilities and pitfalls, so I feel that writing about that is a good starting point. But after that, who knows? I might do another series. So please, feel free to send me suggestions. Maybe I will even revisit this series in the future, detailing what has changed since then. Because I am sure that – even if I have somehow been completely correct for the entire series, time will inevitably turn some of my truths into untruths.
In short, I won’t disappear, and I am open to input. It’s not like software engineering is going anywhere anytime soon.
Happy coding, everyone.
A full overview of all the blogs from this serie from Jelle:
As always, I ask you to contact me. Send me your corrections, provide suggestions, ask your questions, deliver some hot takes of your own, or share a personal story. I promise to read it, and if possible, will include it in the series.
Writing Quality Code, Part 1