What I learned in Software Architecture
Let’s start with a what Software Architecture even is:
Software Architecture is the design of the software system from a high level viewpoint. At the Architecture level, we are concerned about how fully built modules, services, systems, and applications will interact with each other and what they should be responsible for. If a software system were a house, a software engineer might be responsible for coding up the wooden cabinets for the kitchen or the pipes needed for plumbing, but it would be the job of the architect to decide where in the house the kitchen should go, what type of kitchen we should use for the house, and what pros and cons the kitchen offers for the house. This then begs the question…
Why should we care about the architecture of software?
There are many ways to build a system. If all you care about is functionality (i.e. that the software does what it is supposed to do) then architecture doesn’t really matter at all. You can have a monolithic application or write your entire project in one file and get the functionality right. It turns out Functionality is not the only quality that matters for software systems. There are other Code Qualities and the qualities we care most about help inform our choice of software architecture.
Okay. So while Requirements Engineering is about how to figure out (as best you can) what the customer actually wants their software to do, and codifying that into a list of, well Requirements…Software Architecture is about taking the requirements and fulfilling them at a high level.
So what are Code Qualities?
Code Qualities refer an attribute of a software system. They can be quantitative aspects like performance, efficiency, and availability or they can be qualitative aspects like usability, readability, and maintainability. Each code quality deserves its own blog post frankly but I will list a brief summary of some of the code qualities here:
Availability: How likely your system is to be online and ready to use at a given time
Interoperability: How well your system works with other systems
Performance: How well or how efficiently a task is accomplished in code
Security: How well prepared your system is against vulnerabilities and threats
Modifiability: How easily your system is able to be changed without disrupting other parts of the codebase
Reliability: How likely your system is able to perform its tasks without failures
Testability: How easily your code is to write tests for
Reusability: How easily your system or software can be used again in another application or product. This might be useful for product lines and families of systems
Scalability: How well your system can grow in size while still being useful
These code qualities will be more important or less important for every individual application and the reasons for this will come from the domain and use case of the software systems. If your system is a big data application you will want high availability, and scalability in order to meet spikes in demand and service millions of users at a time. This may come at the cost of some code qualities like consistency.
Okay we know what code qualities aim for, but how can we define them better for our system?
We can use the concept of Scenarios to understand how well our system fulfills different code qualities. Scenarios describe events that happen to our system, how our system responds to the events, and a measurement for the response. For example we can have a scenario where 1,000,000 users log on to our application. A scenario will take that one million users logging on as the Stimulus or event arriving at our system. How our system handles the one million log ons will be the Response in the scenario. We can then measure this response in say average time to process a log on. This scenario could be used to understand the Performance code quality of our system. I’ll give some more definitions below to fully flesh out what goes into a scenario.
Stimulus: The Event happening to your system
Source: Where the stimulus coming is from
Artifact: The part of your system being affected by the stimulus
Environment: Where the stimulus is occurring. This could be a software environment or a real world environment (a train station, Mars, a server room)
Response: What our system does when the stimulus happens
Response Measure: How we measure the response. This could be in Time, Dollars, Bugs, Lines of Code
The below image is an example of a concrete scenario:
Scenarios are useful tools for requirement elicitation. The response measure is testable, the scenario as a whole is testable, and the artifact gives traceability between requirements and code.
If we have an existing application, how can we improve the code qualities?
This is where Tactics come in to play. Tactics are small design options that you can implement to help you better achieve a certain code quality. If you want to improve the security code quality for example, you can implement the tactic of authenticating users upon login. Performance tactics may include adding concurrency or scheduling to the artifact.
A couple more things:
There are patterns around to achieve code qualities. These often combine multiple tactics. Software Architecture in Practice 4th Ed. details some of them
Coupling: how intertwined/overlapped two modules are. We can measure this by looking at the probabiliity that a change to one module will result in having to change the other module. Highly coupled modules are very tightly intertwined and changes to one will likely result in having to change the other. Low Coupled modules may have very little or no connectedness to the each other; a change to one module would result in very little or no change to the other.
Cohesion: a measure of how strongly the responsibilities of a module are related. we can measure this by the probability that a change to one of the modules responsibilities will affect other responsibilities. Highly cohesive modules are well separated in their concerns. Low cohesive modules are not well separated in their concerns.
How will this help me as a Software Engineer?
I will be able to interface with architects better
I understand what code qualities are - this will help me defend changes I make or propose by allowing me to properly explain why we need it and what the benefits are
I can see the codebase and applications from a bigger picture
If I’m asked to extend the architecture I can use scenarios to definitively plan out the new architecture and its code quailities
I can use tactics to improve an existing codebase and move towards certain code qualities