So far, my discussions of what makes good code and good design have revolved around two ideas: simplicity and layering. However, there is more to building quality systems than just simplicity and layering.
The ISO/IEC 25010:2011 standard defines a useful model for thinking about and discussing characteristics of quality (or ‘good’) systems.
The standard defines the following eight characteristics, and thirty-one sub-characteristics, of software product quality:
- Functional suitability
-
Does the system do what it is supposed to do?
-
Completeness: Does it do everything it needs to do?
-
Correctness: Does it do things right?
-
Appropriateness: Does it solve a real problem?
-
- Performance efficiency
-
Does the system run efficiently? (e.g., does not waste CPU, bandwidth, disk space)
-
Time: Is it fast?
-
Resources: Does it avoid wasting resources?
-
Capacity: Can it handle the expected number of users?
-
- Compatibility
-
Does the system integrate with or work well with other systems?
-
Co-existence: Can it be deployed alongside other systems/modules?
-
Interoperability: Can it communicate with other systems?
-
- Usability
-
Can end-users operate the system correctly?
-
Appropriateness recognizability: Is it obvious that it is useful?
-
Learnability: Is it easy to learn?
-
Operability: Is it easy for experienced users to achieve their goals?
-
User error protection: Does it help users avoid making harmful mistakes?
-
User interface aesthetics: Is it beautiful?
-
Accessibility: Can people with disabilities use it?
-
- Reliability
-
Does the system work when it is needed to work?
-
Maturity: Does it work in typical situations?
-
Availability: Does it work when required?
-
Fault tolerance: Does it keep working during failures?
-
Recoverability: Can it be restored quickly after failure?
-
- Security
-
Does the system only allow access according to the levels of authorization of users?
-
Confidentiality: Does it keep data secret?
-
Integrity: Does it protect data from unauthorized changes?
-
Non-repudiation: Can it be trusted as a reliable source of truth?
-
Accountability: Can it track changes to the users who made the changes?
-
Authenticity: Can it prove the users and systems are who they say they are?
-
- Maintainability
-
Will it be easy to fix and make changes to the system in the future?
-
Modularity: Does a change in one component require changes to other components?
-
Reusability: Can its code be reused?
-
Analysability: Can it be understood and studied?
-
Modifiability: Can it be changed easily?
-
Testability: Can it be tested?
-
- Portability
-
Will it be easy to move the system to other servers and technologies?
-
Adaptability: Can it be moved to different environments or usage scenarios?
-
Installability: Can it be easily installed and deployed?
-
Replaceability: Will it be easy to replace when better alternatives eventually come along?
-
There are many characteristics to consider! In formal projects, these characteristics can be specifically addressed one-by-one in the project documentation. In informal projects, the list can be helpful to consider your real objectives.
I believe there is a bias among many developers to focus on the technical aspects that are easy to measure (e.g., performance efficiency and reliability) or that are the most exciting (e.g., security). However, all of the dimensions of quality are important to consider. For example, a system that is unusable or doesn’t function is not going to be used by anybody, even if it has incredible performance and reliability.
Building quality systems
Of all the monsters that fill the nightmares of our folklore, none terrify more than werewolves, because they transform unexpectedly from the familiar into horrors. For these, one seeks bullets of silver that can magically lay them to rest.
The familiar software project, at least as seen by the nontechnical manager, has something of this character; it is usually innocent and straightforward, but is capable of becoming a monster of missed schedules, blown budgets, and flawed products. So we hear desperate cries for a silver bullet — something to make software costs drop as rapidly as computer hardware costs do.
But, as we look to the horizon of a decade hence, we see no silver bullet. There is no single development, in either technology or in management technique, that by itself promises even one order-of-magnitude improvement in productivity, in reliability, in simplicity.
‘No Silver Bullet--Essence and Accident in Software Engineering’, Computer, vol. 20, no. 4.
There is no silver bullet that will slay the barriers to producing high-quality software. Instead, quality depends on ongoing effort to improve technology, processes and people.
Frederick Brooks (1987) speculated that higher-quality software might come from the following strategies:
-
Buying (or reusing) existing code, whenever possible
-
Gradually refining requirements and building prototypes
-
Incremental development: growing, not building, software
-
Teaching programmers to become great designers
These ideas have been echoed in different ways through the years, perhaps most famously in 2001, in the Manifesto for Agile Software Development (the ‘agile manifesto’). This manifesto has four tenets:
-
Individuals and interactions over processes and tools
-
Working software over comprehensive documentation
-
Customer collaboration over contract negotiation
-
Responding to change over following a plan
The common theme in both the agile manifesto and Brooks’ writing is that quality systems evolve and grow through constant experimentation, by putting working software in the customer’s hands.
Everyone has their own biases about how to begin organizing a project. I believe that the most challenging part of software development comes from teamwork. In any project with more than one developer, success depends more on having a team with a common vision, than whether the developers are talented or are making good technical decisions. Even technical decisions should have people in mind: a complex software framework or a cutting-edge tool might appear to be technically superior, but if team members hate it or are confused by it, they will not use it.
The role of architecture
…It is reasonable to assume that for any system requirement there is a family of system designs which will meet that requirement, we must also inquire whether the choice of design organization influences the process of selection of a system design from that family… To the extent that an organization is not completely flexible in its communication structure, that organization will stamp out an image of itself in every design it produces. The larger an organization is, the less flexibility it has and the more pronounced is the phenomenon…
…Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.
‘How Do Committees Invent?’, Datamation, vol. 14, iss. 4.
I find it remarkable that I am so often able to diagnose team problems by looking at their code. However, this is not a talent unique to me. A dysfunctional team often produces code that is so dysfunctional that any observer can diagnose their problems.
A team with developers that do not talk to each other will inevitably implement a collection of disconnected features that do not integrate. A team with front-end developers who do not collaborate with back-end developers will produce a system with an inconsistent interface between the front-end and back-end code.
Software architecture is the understanding of the design of a project shared by the expert developers on that project. [1] Architecture plays an important part in the organization. Conway’s law shapes architecture but architecture also has the potential to influence the team itself:
-
The architecture should support the ways that team members work and collaborate
-
The architecture serves as a common understanding and language of the application to help developers understand each other
-
The architecture sets the fundamental principles by which team members will collaborate
In addition to these team factors, architecture creates a framework for building systems that can grow and evolve. The mindless addition of new features can result in an ad-hoc and complex system. Instead, software architecture provides an overall design that gives a simple and consistent structure to new features.
Architecture relates to all of the non-functional characteristics of quality:
-
Architecture can improve or hinder performance (performance efficiency)
-
Architecture can provide standards and interfaces for compatibility with other systems (compatibility)
-
Architecture can inform the design of clear mental models of the system operation (usability)
-
Architecture can include redundancies and protections against failure (reliability)
-
Architecture can make it easier to identify and fix critical security issues (reliability)
-
Architecture can ‘future-proof’ a code-base, making it easier to extend, evolve and grow in future (maintainability)
-
Architecture can make it easier for components to be replaced and upgraded (portability)