The Iceberg Principle
In 212 BC, Archimedes of Syracuse discovered the laws of buoyancy that explain why over 90% of an iceberg’s mass is beneath the waterline. Most of what is there is invisible at a distance. This is why ships give icebergs a really wide berth — so they don’t end up at the bottom of the Atlantic Ocean like the Titanic.
Software has a similar problem. Much of what it takes to build a world class software product lies well beneath the surface, invisible to the stakeholders that are most often paying the bills. There is no arguing that you have to build the right product to achieve any modicum of success. But once you are sure that you have the right product, you need to build that product right. That’s where engineering discipline steps in.
What we call “software architecture” is the discipline of advocating for the balance of the functional vs. non-functional requirements for a software product. In simple terms, software architecture’s role is to ensure that all the stuff below the surface of the product that you are developing has a voice so that the software has an amazing future. How you invest in software architecture is a proxy for how much you care about long-term software quality. The dilemma is that with most software projects, you are developing something that has never been built before. Pieces and parts may have been built previously, but the specific combination that you are building, and the user experience that you are putting on it, are unique. It is impossible to perfectly predict how the system will be used. If we spend our energy trying to make our predictions perfect, we forgo getting products and features to market and worse, we miss what is possible.
We need to find ways to maximize predictability without restricting possibility.
In other words, what gets built needs to be flexible because we know that it will need to change frequently and in big ways. Because of this need for almost infinite flexibility, it is also impossible to eliminate all possible technical debt. Because developers need the ability to experiment with different routines and procedures to optimize their solutions without perfect knowledge of what the future holds, tradeoffs have to be made. When we optimize software, we have to strike an imperfect but purposeful balance between the non-functional requirements and the functional requirements.
The software architect’s primary job in the context of a software product development is to be a voice for those non-functional requirements. Their charter needs to be continuously raising the bar on baseline quality through inspection, tools, automation, team culture and best practices. The dimensions of non-functional software quality are complicated and it is cost prohibitive to maximize every possible dimension. The imperative is to find the right balance for these longer-term investments.
The Software Architect needs to steward the tools, investments, policies and practices for the software products that are built so that they are:
- Future Ready. Your team needs to work to make sure that the product is not being coded into a corner and that it has a future. This means that they are constantly looking for best practices around reusability, extensibility, testability and modularity. These are the things that will help the business maximize the flexibility that they get from their technology investments.
- Supportable. Your team needs to build best practices, processes and create policies that make sure the product is appropriately fault tolerant, serviceable, testable, upgradable and sufficiently documented.
- Efficiently Built. Your team should be aggressively experimenting with new technologies and ideas, but careful to steward your resources in the process. They should be looking for economies of scale in your tools, components and engineering practices. They must always strike a balance in how you invest in innovation and improving your execution. This includes things like managing source code control, automating software builds and implementing continuous deployment.
- Risk Managed. Your team must be aware of and appropriately managing the business risks, liabilities and compliance issues associated with your software products. This means that they are employing appropriate security testing and monitoring tools, they are addressing the source code licensing issues that can get you into trouble and are competent in and complying with any regulatory statutes and standards that your business demands.
- Performant. You know how your products will scale and respond under expected load scenarios, both now and in the future, and are able to support the growth of the business. Your team understands how responsive it is to our end users’ actions. By measuring and managing concurrency and reliability, they make sure that your software products can be monitored for all of the critical business functions that they support.
Building for any one of these “Iceberg Principles” almost always results in a trade-off for one or more of the others. The architect’s role is to educate the business on the consequences of the choices made around the non-functional requirements and being an advocate for informed choices. The key to managing technical debt for any software product is to be aware of these trade-offs and to put a system in place to test for whichever factors are important. Even better, working these testing tools into your continuous integration and continuous deployment environments is ideal.
If you don’t want your software products to end up like the Titanic, make sure you are finding the right balance between the functionality that the business demands and the aspects of non-functional quality that your product needs to ensure it has a viable future.
- Originally published here: https://www.itx.com/ITX-Blog/Article/394/The-Iceberg-Principle