How Software is Designed and Built

December 9, 2024

William Hooper looks at how software design can influence the success of a project.

William Heath Robinson had a delightful eye for the absurd. His designs were elaborate and amusingly flawed. How is software designed and built, and what is the effect of this on value to a customer? Does it matter if the design pattern for your system is borrowed from one of his cartoons?

For non-contentious lawyers, it can be a challenge to define what is “good design” with sufficient precision to achieve contractual certainty. As the contract rarely defines design quality, it is difficult to rely on in a claim for breach. As a good contract captures what is important in an agreement, and customers should rely on receiving a good design service from their suppliers, omission seems unwise.

Objectives of Design

A design represents the team’s approach to delivering the application. It should achieve the objectives set for it in the business case, delivering a solution to the requirements. When done well, distinctive software can deliver a valuable strategic lead to its developers.

Each customer should consider its own objectives of software design. The following are likely to feature:

  1. The system should efficiently and effectively satisfy the design goals.
  2. The software works for the business and is sympathetic to the user. It fits into the environment in which it is used. It reflects a deep understanding of the business and makes sense of it in operation.
  3. The design supports the development and implementation team in their delivery and maintenance of the system. They know what they have to do and how to do it.
  4. It is adaptable, maintainable, extensible, scalable to meet adapting business needs; it keeps working well over the intended lifetime.

The Value of Design

A good system design deploys coherent concepts in a way that makes sense to users. They adopt and engage with greater enthusiasm as it makes sense to them in performing their tasks. This gives the supplier longevity and greater value. For the support community, good design makes it obvious what is to change and how, so simplifying, accelerating and reducing the costs of maintenance. Supple design simplifies adaptation to emerging need, facilitating the delivery of greater value. A higher integrity of solution is supported by the clarity of its working and the continuous test.

Design involves the balanced consideration of ways in which the system’s objectives could be met, from which the best available option is selected. This normally involves multiple moving parts that have to be brought together into an end-to-end system, so the options change in the course of design.

Bad design is seen in a tangled mess of logic. It may perform aspects of what is required, but is so contorted that anyone charged with fixing it has the greatest difficulty in working out what is done where and how. Such an edifice is fragile and painful to adapt.

Approach 1: Hack

A “hack” is a solution to some problem that may not be the best solution to a programming problem, but it works. Hacked software is built without design.

Rapid development in isolation at a small scale for short-term use may not cause harm. This article does not argue for excessive design overhead. There is always an element of design that involves experimentation to see what works.

A contract for services is unlikely intentionally to specify a hack approach. It can however arise and troubled delivery frequently follows. Hacking lacks coordination between developers working along-side each other. When developers do not carefully manage dependencies and interactions, they cause confusion and delay. If in coding a change, a remote component is broken by it, the developer has to undertake additional work to repair the damage. A good design and model confine the effects of change.

Approach 2: Waterfall

This is an organised, and traditionally widely-deployed approach to software development and planning. Waterfall’s top-down thinking gives impressions of certainty. The contract contains requirements. A small, central group of elite architects designs first a high-level architecture, feeding estimates derived from this to the project manager for planning and costing. After contract approval, the team goes on to elaborate the requirements[1] and refine the design. They progressively develop the lower-level detail of the design before going on to code and test. Developers first unit test elements of the solution in isolation, before bringing them together in progressively larger modules, culminating in a full User Acceptance Test (UAT).[2] The business decides when the application is ready to go live and deploy to business users.

Architects define the software design in documents before the build starts. Often in practice the as-built deviates from the design. Sometimes documents are updated. Often not.

This ordered, linear progression is a model of delivery that greatly simplifies reality.

“All models are wrong, but some are useful.”

George Box

As Good as it Seems?

Non-technical managers often like the Waterfall approach as they find it easy to understand. This makes it suitable for non-specialists and simple projects. However, it also has serious shortcomings. The business experts talk to the analysts, and analysts digest and abstract. They then pass the result along to the programmers, who code the software. This approach fails because it lacks feedback. The analysts have full responsibility for creating the solution model, based only on input from the business experts. They have no opportunity to learn from the programmers or gain experience with early versions of software. Knowledge trickles in one direction but does not accumulate. Misunderstandings are rife and frequently emerge only just before launch, when it is too late to fix them.

This one-way communication lacks certainty. Words are a means of communicating concepts. Communicated statements make many assumptions of context, constraint and relationship. This gives rise to the risk that whilst what is delivered may be a compliant solution, it is not what the customer wanted and that it is impracticable in use.[3] Software developers often lack graphical and user-experience design skills. The results may be ugly and difficult for business users. Disagreements may arise as to whether revision constitutes a chargeable change. Contractual certainty is not always what it appears to be.

In building construction, it is normal to have one or more rounds of contracts for design (e.g. architecture, structural engineering, ground-works), the product of which is let in one or more lots for building work. In software development, the writing of code is indistinguishable from design. Design issues arise throughout the software lifecycle until the application is retired from use. Waterfall is software’s equivalent of a construction approach.

Approach 3: Iterative Design and Delivery

Real engineering programmes have long used iterations. A series of phases with progressively more complete and production-ready prototypes results. Modern software engineering practice, supported by agile methods, extreme programming (XP), continuous integration and automated testing, takes this to extremes. Each iteration takes the programme closer to a solution. The aim is that from early on, the software “works”, although major parts of the desired functionality may not then have been developed. [4]

This works best where business domain experts work closely along-side application developers. Together they construct a model of the solution and continuously validate that it and the developing solution do what is required in the most effective way. Early exposure first to the model, then to working prototypes, allows refinement of model, application code and expressed requirements to validate the approach. This helps to identify implied requirements and dependencies. Additional work arises in the course of delivery to fulfil these. Some see this as a lack of contractual certainty. The delivery team should prioritise such amendments based on what is most important to get right before launch. Amendments to peripheral aspects are scheduled for modification after launch (if at all).

The Benefits of Iteration

This approach delivers a better-quality and insightful fit to what the business needs, earlier than is commonly available under Waterfall. There is just as much design work (if not more) as under Waterfall and its top-down architecture, but it focuses on the integrity of the shared model and alignment to that under the programme design principles. But rather than design THEN build; it is design WHILST building. The building therefore starts earlier. There is a price: the assumption that the solution will be built once, and built right-first-time goes. Each change to the design, of which there are many, results in the need to re-adjust the existing application to the new design and model. This is called “re-factoring”.[5] If developers change each element of the solution many times, this emphasises the value of integrity of documentation, consistency of use of language and pervasive automated tests. The result should be a more adaptable and maintainable code-set. It must be clear to all what each element of the solution does, its dependencies and relationships to others.

Iterative delivery is often associated with the use of advanced software engineering practices to coordinate the work of multiple workstreams, and continuously integrate the components. They do this to ensure that a change in one area has not broken another.  This requires a level of business input, developer skill, managerial sophistication, automated tooling and engineering practice that is beyond the capability of many. As many Agile contracts have proven, chaos at speed can be much more expensive than slow incompetence. Designing for such an approach is far from easy, but the methods to do so are now mature. Not all practitioners are yet proficient in their use. Some should not try to apply iterative delivery.[6]

Conclusions

Under agile and extreme programming methods, one should define the tests of completion before starting development. This is known as the “definition of done”. This is to guard against ambiguity.

Practice in software engineering and delivery is changing rapidly. To write good contracts and to enforce them well requires a degree of understanding of what should be happening on a project and the variety of approaches that may be taken. Good Industry Practice is changing.

It would not be wise for the author of a contract schedule to tell a supplier how they should be delivering. It is necessary for a customer to satisfy themselves that the favoured supplier has a good and coherent approach, that it has the skills and resources to deliver it and that they will commit to perform to it. The quality of design, and the later manner of delivery have such a strong effect on the value delivered to a customer that it is worth considering at the time of agreement how performance is to be assured. Change is inevitable. Manage it well and if you are fortunate and your supplier is talented, you may be delighted by the insights gained along the way.


[1] Barcelos, L.V., Penteado, R.D. Elaboration of software requirements documents by means of patterns instantiation. J Softw Eng Res Dev 5, 3 (2017). https://doi.org/10.1186/s40411-017-0038-9

[2] https://www.javatpoint.com/software-engineering-v-model

[3] https://oareborough.com/Insights/assessing-design-quality/

[4] https://oareborough.com/Insights/contracting-for-multi-supplier-devops/

[5] https://www.techtarget.com/searchapparchitecture/definition/refactoring

[6] Evans, Eric, Domain-driven design: Tacking complexity in the heart of software (2004) Addison-Wesley

Winters T, Manshreck T, Wright H (2020) Software Engineering at Google, O’Reilly

William Hooper acts as an expert witness in IT and Outsourcing disputes and a consultant in service delivery. He is a member of the Society of Computers and Law and a director of Oareborough Consulting. He may be reached on +44 7909 958274 or William@Oareborough.com