When designing software architecture for a new product, it is often difficult to evaluate available design options and choose the optimal ones. That happens often because it is unclear for developers what criteria they should use to make design decisions and why.
Some developers rely on their previous engineering experience and personal preferences in practices, technologies, tools and patterns. The issue is that each dev team member has different preferences, opinions and assumptions. As a result, it may be difficult to reach consensus within a team and agree on some decisions. Arguing over subjective opinions and preferences may not only damage relationships between co-workers, but also won't necessarily lead to the software architecture optimised for achieving the business goals.
What can developers do to make architecture design decisions more objective and less difficult? One option would be to:
- start with investigating the non-functional requirements for the product;
- understand which software quality attributes it should be optimised for;
- then use that knowledge to choose the architecture options that allow their product to meet all the business requirements.
Before we move on, let me explain what non-functional requirements and quality attributes are.
Non-functional requirements specify criteria for evaluating how a software system should perform rather than what it should do. An example would be a requirement for a web API endpoint response time to be under 200ms.
When we say that a software product should be "secure", "highly-available", "portable", "scalable" and so on, we are talking about its quality attributes.
In other words, a software product must have certain quality attributes to meet certain non-functional requirements.
A couple of examples.
Example 1: a product must be able to stream video content to 0.5–1M concurrent users 24/7 all over the world. These non-functional requirements encourage developers to consider design options that lead to a highly-scalable, highly-available, fault-tolerant architecture. In addition, the requirement to be available globally means that the product must support internationalisation, to be localised for various countries.
Example 2: a product must be available during business hours to a few hundred users in a single country. These requirements suggests that the product doesn't have to be particularly scalable. It probably doesn't even have to be constantly available outside "extended" business hours.
Non-functional requirements should be quantifiable and include targets like "0.5–1M", "24/7", "a few hundred", "business hours" in the examples. There must be a way to check if a requirement has been met. Developers can use these targets as benchmarks to tell whether their product meets requirements.
It is crucial for developers to be aware of all non-functional requirements including all the assumptions and implicit stakeholders' expectations if they want to build a successful product. If such assumptions are discovered later, changing architecture may be expensive.
Once developers have non-functional requirements they can understand what quality attributes they should optimise the architecture for. For instance, in Example 1 it is logical to optimise the product architecture for scalability (so it could reach desired capacity) and availability (so it could be available 24/7).
Developers may also want to know what quality attributes their product architecture doesn't have to be optimised for. Then, if required, they would know which qualities to sacrifice to meet the important requirements. Good candidates for such attributes have either no related non-functional requirements or easy-to-meet ones.
It would be convenient for developers to have a comprehensive list of quality attributes to go through and check if each attribute has related non-functional requirements.
I often use a list of 32 quality attributes (grouped into 8 characteristics) defined in the international standard "ISO/IEC 25010" in the section that introduces a software product quality model:
- functional suitability: functional completeness, functional correctness, functional appropriateness;
- performance efficiency: time behaviour, resource utilisation, capacity;
- reliability: maturity, availability, fault tolerance, recoverability;
- usability: appropriateness, recognisability, learnability, operability, user error protection, user interface aesthetics, accessibility;
- security: confidentiality, integrity, non-repudiation, accountability, authenticity;
- compatibility: co-existence, interoperability;
- maintainability: modularity, reusability, analysability, modifiability, testability;
- portability: adaptability, installability, replaceability.
I'm not including the definitions here. You can find them either in the free fragment of the official standard, or on this page.
I know, most of these characteristics sound very abstract and unhelpful to a developer trying just to build a piece of software. But let's take a look at an example to better understand how to use that list and what knowledge about our product we can get out of it.
Example 3. Imagine a team of Ruby on Rails and React developers building a global online marketplace for freelancers to sell services like web development, digital marketing, SEO, copywriting, etc. Let's go through some characteristics (quality attributes) from the model to define non-functional requirements and choose the ones the product architecture should be optimised for.
For brevity, let's look only at the sub-characteristics of "maintainability".
"Modularity", being a great quality, doesn't seem to have related non-functional requirements for an online marketplace.
"Reusability" is another great quality that seem to have no related non-functional requirements in this case.
"Analysability" is important. Developers would want to diagnose the product in case of failures, collect and analyse system metrics (i.e. response time, page load time, CPU and memory usage, etc.), search and analyse logs, etc. Product people would be interested in having capabilities to collect metrics like average visit duration, conversion rate, percentage of users that use particular features. Examples of non-functional requirements could be:
- all exceptions must be logged into a third-party system, stored for 12 months and be searchable,
- logs must be collected in a third party system, stored for five years, and be searchable;
- homepage load time must be less than 500ms;
- every user click in the web app must be tracked in a third party tool; etc.
Clearly, online marketplace architecture has to be optimised for "analysability."
"Modifiability" is important too. Especially in the long term when it determines the cost of evolving and maintaining the product. Related non-functional requirements may look like:
- upgrade all third-party libraries and frameworks to the most recent major version no later than in 30 days since their release date;
- have all infrastructure in code to simplify changes to provisioning and deployment processes.
"Testability"-related non-functional requirements may look like:
- have 98% unit test coverage for backend and frontend code;
- have acceptance tests for all scenarios linked to conversion funnel;
- have security checks and vulnerability scans that prevent code with known security flaws to be shipped to production.
If I had to design software architecture for this online marketplace, then among its five maintainability characteristics I would optimise for (in this order):
- testability: to ensure developers can move fast and detect defects early;
- analysability: to ensure developers have visibility into how the software components of product operate
- modifiability: to ensure we don't code ourselves into a corner and can maintain and evolve what we have built.
I hope the example has demonstrated how after going through the list, developers can find out which quality attributes they should optimise architecture for. As a result, it will be easier for them to compare design options and choose the optimal one faster. In addition, developers will make decisions based on rigorous requirements analysis rather than on their personal preferences and opinions.
Please note, there is no need to limit the list to only the 32 attributes from the quality model. Other quality attributes like the one in this Wikipedia article can be useful too.
Also published in my Medium account.