Curated by: Sergio A. Martínez
“Never trust a system that seems to be working” – Foone Turing
Anyone who has ever tried to develop software knows that it can be a very complex task. There are many different types of programs you can create, ranging from simple applications to large and complex operating systems, and each has its own unique set of challenges. However, there are common trends no matter what you are developing: for one thing, software is built upon layers of code, meaning that any change to the codebase can potentially affect the entire program. Software typically works in tandem with other programs and systems, so a change to one piece of software can often ripple outwards and cause problems with other programs. Furthermore, many software applications are used by millions of people all over the world, so even a small bug can have major consequences.
In other words, developing software requires a great deal of care and attention to detail to ensure that the final product is stable and usable, ready to do what you want it to do. Nothing beats the moment when you run a program for the first time, and it seems to work very well. But for a certain kind of developer, this is the point when the actual challenge starts: getting something to work is the first step to creating a truly wonderful piece of software but may not be the end of it.
So, this time, we want to discuss the subtle and crucial difference between “working as expected” and “working as intended”, how this can make or break an entire project, and how a smart developer can begin to understand why a system might fail even after it successfully seemed to work perfectly. Onwards!
Knowing and not knowing
Software is everywhere. It’s running our phones, our computers, and our cars. It’s become so integral to our lives that we often take it for granted, when in fact, achieving software that works at all is almost miraculous. We’re talking about lines of code, written by fallible human beings, that work together to design very complex systems with tons of moving parts that must work in very specific contexts. And yet, more often than not, they actually do what we want them to do. Sure, there are the occasional glitches and bugs, but overall, it’s amazing that software works as well as it does. However, how do developers achieve that?
We can sum it up with this famous quote by Former Secretary of Defense Donald Rumsfeld: “There are known knowns, things we know that we know; and there are known unknowns, things that we know we don’t know. But there are also unknown unknowns, things we do not know we don’t know.” It might look like a mouthful, but it’s a great starting point for risk assessment and post-mortems of software issues. How many known and unknowns do you have about the system you build? How many things you don’t know you don’t know? Because the idea of working software is not as clear as you might think, and your approach to this is defined by your experience as a developer. In short…
- When something works, a junior developer feels excited. They tend to focus on the known knowns; they know the system is working, they know how it’s working, and further considerations are secondary until an issue becomes apparent. These developers are still experimenting and learning new things as they go.
- When something works, a mid-level developer feels relieved. They tend to focus on the known unknowns; they know the system is working, and move on to the unknowns (bugs, compatibility problems, glitches, etc.) that cause immediate issues, but mostly as a means of ensuring stability and shipping the product.
- When something works, a senior developer feels concerned. They focus on the unknown unknowns, without assuming that the system working is enough to move on; having a complete understanding is a must to guarantee the quality and intended functionality of the program. Thus, when achieving a working system, their first question is always “why?” to make sure the stability of the program is unassailable.
So, it all comes down to experience, giving you a nagging feeling at the back of your mind when the code runs: is it doing it as it should? This is the heart of the problem between systems working as intended and systems working as expected, which are not always the same thing. Understanding the difference between both is what separates a good program from a bad one, ensuring that the design of a system is the one responsible for it working, and not a series of coincidences that give the impression that it is. Otherwise, you are sitting on a time bomb, ready to go off when the correct circumstances align. In short, the development process, once you complete a version of the product, should look more or less like this:
Okay, we might be exaggerating a little, but in broad strokes, this is how you avoid being blindsided when something unexpectedly breaks in the long run. Taking the time to view the program holistically, where you can properly see how every individual element is interacting with everything else, is the ideal way to develop a good, stable application, and although it is possible to reach the point where you actually know exactly how a system works, it’s never going to be on the first try.
This Twitter thread linked above gives a great example of this, in which assuming that a working system is a good system can have deep consequences (long story short, an undetected error in the certification software of a company that built servers was loading the wrong kinds of tests, giving false positives on the architecture of machines intended to handle a lot of data, which could be quite a problem if left unchecked), and being aware of the existence of unknown unknowns can save you from a bad headache in the future.
Knowing is half the battle
So, to recap, the success of any software development project depends on two things: a complete understanding of how the application works, and a detailed risk assessment. Here at Scio, where we always try to bring the best software development in Mexico, we came to understand that, without these two elements, it is impossible to produce a good outcome:
First, always assess the risks. This means identifying all of the potential problems that could occur during development and assessing the likelihood of each one occurring. Once the risks have been identified, they can be mitigated through planning and implementation. For example, if there is a risk that the application will not work as intended, then extra testing can be built into the development process to ensure that it does. And second, gain a complete understanding of how the application works. This includes understanding the code base, the architecture, and the dependencies. Without this knowledge, it is impossible to make informed decisions about the best way to develop the software. It also makes it more likely that errors will be made, which could lead to problems during development or after the application has been released. A complete understanding of how an application works will always be critical to achieve the best result.
The Key Takeaways
- Software is a very complex field where the number of moving parts, requirements, and situations where it must work make it difficult to create flawless products.
- One of the bigger challenges is understanding a system thoroughly, otherwise a software application can fail in unexpected and disastrous ways.
- A key strategy is being aware of your known knowns, known unknowns, and unknown unknowns.
- In other words, what separates novice developers from veteran ones is the understanding that a system working as intended is not the same as a system working as expected, and solving this difference can guarantee the best outcome.
Scio is an established Nearshore software development company based in Mexico that specializes in providing high-quality, cost-effective technologies for pioneering tech companies. We have been building and mentoring teams of engineers since 2003 and our experience gives us access not only to the knowledge but also the expertise needed when tackling any project. Get started today by contacting us about your project needs – We have teams available to help you achieve your business goals. Get in contact today!