What are Non Functional Requirements in software architecture
Previous to know about non functional requirements it is important to know what is a requirement in software engineering.
Requirements are the description of a services provided by a system and their operative restrictions.
Discover, analyse, document and verify requirements is the process known as Requirement Engineering. Requirements can be the base of a contract offer or the base contract itself in software projects.
There are several types:
Non functional requirements
Domain or Business requirements
Non functional requirements are directly related with emergent properties of a software system and specify or restrict them. Examples of these properties are:
They can be much more critic than any other requirement. As a result, a flight control system that does not meet reliability requirements will be insecure and therefore unusable.
Non functional requirements arise, also known as Quality Attributes, from the needs of users, budget restrictions, company politics, interoperability with other software or hardware, external factors like security regulations or privacy legislation.
Why you should know about Non Functional Requirements
Even if you are not a software architect, and you are a developer, taking care about non functional requirements it's crucial. It allows to deliver great features without compromising the whole system and add complexity and technical debt.
In order to evaluate which software architecture is the best for a digital project, it is necessary to know first which are the non functional requirements for the same.
Each software architecture style has different impact on each Non functional requirement. E.g. Batch Sequential architecture can have a negative impact in usability while a MVC architecture has a great perform in this area.
Main Non Functional Requirements types
In this section are described different types of Non Functional Requirements in the same order shown in Arquitecto Software.
Also known as a serviceability, it refers to the ability of a software system to ease technical support in some areas:
Installation and configuration of the system.
Provide information that is useful for identify exceptions, debug and isolate the root of problems. Also known as logging or tracing.
Monitor health metrics of the system.
Good supportability results in more efficient maintenance and reduces operational costs.
The usability is about how easy it's for a user to use the platform and achieve the expected results with effectiveness, efficiency and satisfaction. These properties are addressed in ISO/IEC 9126-4
Usability includes the ability of being accessible to all people, even those with disabilities. This can be accomplished implementing assistive technology in the UI, and providing text for all images and multimedia resources.
Good usability results in better customer satisfaction, more recommendations, and definitely can boost the organic growth of a company.
This requirement is related to System Development Life Cycle (SDLC) in which a software system go through a series of Life-Cycle phases:
Integration and testing
Deployment and maintenance
In order to discontinue a software system, there is a process of transition to a new system. Design architectures that take this into account will facilitate migrations in the future.
Cost can be the achilles heel of a software project. There are a lot of elements to consider in the overall cost of a software architecture. The most outstanding examples are:
Implementation cost: a more complexity architecture requires more qualified engineers.
Costs associated to failure management and recovery.
Data Backup strategy costs.
Resources needed to run the system: hardware, electricity, etc.
Costs associated to system maintenance and support.
A clear costs example is the one that can be seen in monolithic vs. microservice costs at the beginning of a project. A monoholitic app will be less expensive in resources and complexity management than a microservice architecture with orchestration.
To highlight the importance of costs in software architectures there is a book with the title: "RCDA: Architecting as a risk and cost management discipline"
Scalability refers to the capacity of maintain effective performance during a steep increase in workload without the need to be redesigned. An example of this can be a peak of users using the software simultaneously.
There are many different methods to scale an application and is largely subject to the architecture and behavior of the application. For microservices, Scale Cube defines primarily three approaches for scalability:
Scale the x axis by horizontally cloning the application
Scaling the y axis by splitting different functionality
Scaling the z axis by partitioning or sharding the data
A more general approach for software architectures can be:
Horizontal scalability (scale out): add or remove nodes to a system.
Vertical scalability (scale up): add or remove resources to a node in a system.
Also known as Mean Time Between/To Failures or MTBF/MTTF. This requirement refers to the consistency in the anticipation of software operations. Therefore unreliability is the result of unanticipated results of software operations.
A common metric to measure reliability is the number of software faults (known as bugs), expressed as faults per thousand lines of code.
The best way to mitigate bugs in software is to do good testing strategy, therefore a software architecture easy to test could be more reliable than other architecture harder to test.
Concurrency refers to the capacity of handle multiple computations executing simultaneously, and potentially interacting with each other.
A software architecture with high concurrency have clearly identified parts that can execute concurrently. E.g. a Pipe and Filter software architecture with multiple pipelines at the same time will be more concurrent than a Batch Sequential software architecture that execute tasks in batches.
Concurrency also refers to the minimum, average and maximum number of simultaneous users using the software.
Performance refers to the amount of work accomplished by a system and means the limiting factor in the end usability of the system.
Is totally dependent of the needs of the project, but good performance involves different means:
For UI refers to a low latency, less execution time.
At server code refers to high throughput, that is the rate of processing of work.
In embedded architectures refers to low utilization of computing resources.
A Blackboard software architecture has a good performance because all listeners and subscribers in this architecture can work in parallel.
Security is a process of risk management that balances likely security risks against the cost of guarding against them.
This requirement allows the owners of resources in the system to reliably control who can perform what actions on particular resources. It implies many actions, some of them:
Sensitive resources identification and protection: permission evaluation over every action over every resource.
Identification and authorization.
Continuous monitorization of vulnerabilities and threats.
Availability is the capacity of a software architecture to be fully or partially operational when is required, and to effectively handle failures that could affect it.
Some tactics and actions related to availability:
High-Availability hardware and load balancing.
Zero downtime deployments.
Design for failure.
Backup and disaster recovery solutions.
A service oriented architecture like microservices can use load balancing between instances and ensure more availability than a client server architecture with server as a single point of failure.
Simplicity implies reduce responsibilities through software decomposition and separation of concerns using clear interfaces. The main goal of simplicity is to reduce complexity, this contributes to more maintainable and less costly systems.
A well-known rule is KISS (Keep It Simple, Stupid), that states that most systems work best if they are kept simple rather than made complicated. Designing simple solutions is often a foundation to providing all other system qualities.
A centralized architecture will be more simpler than a distributed architecture because the inherent communications that distributed environment requires.
Reusability in software architecture refers to the degree in which parts of the architecture can be used in other software systems. It brings cost reduction due to the reuse of known and tested software components.
Service Oriented architecture is a good candidate for reusability, e.g. a microservice can be reusable in different systems.
Flexibility refers the ability for the software architecture to adapt to possible or future changes in its requirements. A software architecture is flexible when its parts have low coupling.
When a system can evolve with only adding things, it says that system is very flexible. Conversely, if it is needed to change architecture parts in order to evolve it, then it's not flexible.
Layered architecture brings a lot of flexibility because parts of architecture are clear separated and can be evolved.
Portability in software architecture refers to degree in which the same architecture can be usable in different environments.
One key factor element of portability is a clear abstraction between business logic and system interfaces.
Layered architecture is very portable because parts of it architecture are clear separated and can be separated to another environment. Conversely, Blackboard architecture is less portable because of dependency between data store and its agents.
Testability refers to the degree to which a software part of architecture supports testing in a given test context. High testability implies more facility to find software faults or bugs, that improves reliability.
Batch Sequential is a very good candidate for testability because provides simpler divisions on subsystems that can be tested separately, using mock data between them.
Maintainability is about how easy the software system can be modified to correct faults, improve performance, or other attributes, or adapt to a changed environment.
These are some metrics used to measure maintainability:
Source Lines Of Code (SLOC)
Besides that, a key factor to ensure maintainability is Mean Time To Repair (MTTR), the average time required to repair a specific item or component from notification of a failure until to return it to working status.
In Continuous Integration cycles static code analysis are executed in order to measure previous metrics, SonarQube is a good option to do it.
Layered architecture is a good candidate for maintainability due to separation of concerns.
In this post is explained what are requirements in software engineering, and Non Functional Requirements at a deep level.
There are software architecture styles that performs better than others for a specific non functional requirements, therefore its crucial to evaluate a style for all of them before to select the best style for a project.
There are a lot of Non Functional Requirements to take in account, but the most important are: supportability, usability, lifetime, cost, scalability, reliability, concurrency, performance, security, availability, simplicity, reusability, flexibility, portability, testability and maintainability.
Arquitecto Software makes this process automatically, evaluating Non Functional Requirements against architecture styles and showing which one is the best option.
Post also published on Medium.