How engineering principles help me build high-quality software
In recent years software engineers have become sloppy, especially when compared to the rigor and precision of traditional engineering disciplines. And, I think, at least part of the reason is that software engineering has increasingly decoupled from physical constraints.
Back then when computational resources were scarce, software engineers were often required to think hard about certain problems. However, the vast increase in computational power and data allowed software engineers to become sloppy to the extent as of which the design of an algorithm doesn't seem to be important anymore.
Meanwhile, the low standards among software engineers have even become something of a meme with programmers frequently admitting that they rely on Google, Stack Overflow and ChatGPT to solve problems, often resorting to copying and pasting code without thoroughly assessing its quality or fit.
I personally admire the rigor and precision of traditional engineers and in recent years I came to the conclusion that I could borrow principles from traditional engineering and apply them to software engineering in order to improve the quality of my software products to a considerable extent.
Systems thinking
One such principle is the systems thinking approach. What is known as 'systems engineering' involves integrating various imperfect subsystems into one system that exhibits emergent behavior. Take aviation engineering as an example. An aviation engineer is required to integrate different imperfect subsystems, none of which alone has the ability to fly, into a holistic system capable of flying, such as mechanical systems, electronics, software systems, materials etc.
As a software engineer I don't design airplanes, but I often integrate different imperfect subsystems into a holistic system, such as hardware and software, frontend and backend, each of which consists of many subcomponents and layers. Similar to aviation engineering, I have to think not only about the characteristics of each of the subsystems, but also how these different subsystems interact with each other.
Thinking from first principles
Another critical engineering approach is to think from first principles, which basically describes a method that breaks down a complex problem into basic assumptions, from where an engineer deductively derives conclusions - a technique that is particularly popular when dealing with new problems no one else had encountered before.
In most of my major projects I am encountering very hard problems, which I could only solve by thinking from first principles. If I found myself in a deadlock for many days with no solution in sight, I usually take a step back, start thinking about the problem from scratch and try to find a different approach. Often, this approach leads to solutions that differ significantly from my initial approach but ultimately proves to be the better way.
Thinking in terms of trade-offs
Engineers are often faced with trade-offs, in which a certain advantage comes with a cost or implies a disadvantage. Or as the economist Thomas Sowell once said, 'There are no solutions, only trade-offs' - most engineers are fully aware of trade-offs. A higher quality usually implies higher costs, a better performance usually requires more resources or higher speed implies lower accuracy. In other words, the physical world puts constraints on engineers and their designs.
Similarly, software engineers also deal with trade-offs, including trade-offs between efficiency and resilience, usability and security, scalability and simplicity, standardization and customization or between flexibility and complexity. Being aware of the concept of trade-offs helps me balance advantages and disadvantages in a more systematic and structured way.
Tendency towards complexity reduction
Another important engineering principle that I frequently encounter in software engineering is the tendency to avoid complexity. Complexity can often lead to major problems, including instability, unknown unknowns or challenges in maintaining a system. Again, let's take a look at the aviation industry. Some aviation engineers are proposing so-called morphing wings - wings of airplanes that consist of moving parts and can potentially improve the maneuverability and aerodynamic efficiency of airplanes. The problem though is that morphing wings means adding a significant amount of complexity to the airplane, which could be a risk to the overall stability of the system.
Software engineers often find themselves in similar situations. Adding complexities to software can be attractive, because they allow for more or better functionalities, the problem though is that complexities can result in instability or they can be difficult to maintain or to debug. While in some cases complexities might be worth considering, in many other cases, however, complexities can lead to considerable problems.
Conclusion
These are just the most important engineering principles software developers should take into account, but there are many more fascinating concepts software engineers could utilize to improve the quality of their software such as the concept of redundancy, modular designs, the iterative process of optimizing a system, safety margins or human-centered designs.