There’s a huge misconception into what a software architecture must cover to be considered “good”. You will always find purists that claim that “only when reaching The State-Of-The-Art level is when your architecture is ‘good'”; others, more pragmatical, will define a good architecture as “the one that can translate to a paycheck quicker than the other choices”.
And, of course, at some point you will have to deal with “architects” that say “an architecture is only good if I designed it, or when I say so”.
You have read about architecture principles and best practices and all (if not, you will read about that in part 3), but no one really have set a tangible acceptance criteria of “when you have reached a good architecture level”. And that’s what I will try to accomplish with these article-series.
So, what does “software architecture” actually mean?
Long story short, “Software Architecture is what defines how a software piece is structurally organized and how it will behave/interact with other components.” I made the definition short so that I could focus more on the characteristics of SW architecture below; nevertheless, if you feel like life isn’t short enough, you can always read a more philosophical definition in here.
- Now, what is a software piece? It could be a dummy “hello world” test app, a device driver, BIOS firmware, or even a complex system that governs the vitals of a space shuttle.
- And what do you mean by components? I mean other software pieces, servers, I/O interfaces, machines, conveyors, humans and basically everything else. Components can be internal or external.
My definition excluded purposely the degree of quality of the architecture. This implies that basically any piece software piece will always have an architecture. It just that there are good and there are bad software architectures, just as much as there are good and bad housing architectures.
If you don’t agree with me, just look into these two examples:
Good vs bad, can you guess which one is which? (see the answer below**)
The fact that you have a poorly designed building, is not enough to disqualify it from meeting the bare definition of building. You still have a building in front of you, is just that its architecture sucks. Same thing happens with software architecture.
How to measure the quality of your software architecture?
How good or how bad your architecture is depends totally on what your software piece’s requirements are. The only way to measure the quality of your software architecture is by checking how many requirements of your software piece were covered effectively.
- The more requirements that got effectively covered, the better your architecture is.
- The more [effectively covered] requirements that got efficiently covered, the better your architecture is.
Effectively strictly refers to “Got covered? (true|false)”. Efficiently strictly refers to “Is optimized? (true|false)”. You cannot talk about efficiency if you don’t have effectiveness.
Notice that effectively covering the requirements is enough to conclude you have a good software architecture; efficiency just adds value. A combination of both is what makes great architectures to emerge.
And what are the requirements?
Here’s the key piece: By requirements I refer both functional and non-functional ones, and, unfortunately, the later ones will usually remain hidden. Bare with me.
Enlisting functional requirements is typically less difficult than enlisting to non-functional ones. It’s not that functional requirements are easy either, is just that usually every software piece request is generated from a need that was brought by someone; based from that need, functional requirements are usually discussed and defined.
However, non-functional must be usually discovered by the development team. Good architects would usually discover the most critic non-functional requirements on early phases.
Guideline to discover non-functional requirements
When discovering non-functional requirements you must take in consideration a lot of things, such as:
- Quality-attributes (security, fault-tolerance, high-availability, etc.).
- Infrastructure architecture (tiers, servers, platforms, load-balancers, firewalls, etc)
- Environment variables (invasive antivirus software, network disconnections, high-latency, paranoid-network-settings, army-occupied facilities, forbidden-hardware, temperature/humidity/pressure levels, VMs vs bare-metal, etc.)
- Compliance laws, policies and standards (import/export laws, antiterrorism checks, restricted countries, personal data treatment, company’s policies, contractor’s policies, audit logging, RFCs, protocols, etc.)
- Team constraints (remote vs local, geolocations, time zones, attrition level, expertise level, amount of heads, full/temp contracts, type of tech roles, cross-functional teams involved, amount of travels, etc.)
- Tools constraints (OS, equipment, IDEs and versions, licenses, programming languages, DBMS, deployment environments, etc.)
- Project constraints (budget, required software licenses, time to market, lack of dedicated office cubes, etc.)
- Users constraints (spoken languages, education degree, working shifts, holidays, rotation-level, users’ roles, cultural behaviors, etc.)
- Technical management constraints (source control, coding standards, branching strategy, deployment strategy, frameworks to use, etc.)
- Project life-cycle (expected number of years to support it, estimated grow in new features, projected releases by year, teams that will transition to, etc.)
- Performance constraints (expected transactions per second, max concurrent users, hardware capabilities, max available threads, locking-mechanisms, etc.)
- Other constraints (handling daylight-saving time transitions, leap seconds, clocks skew, power-saving capabilities, etc.)
For those who didn’t TL;DR my explanation above, I’m pretty sure the list shocked you. And I’m pretty sure you would think many of the example items listed above do not affect your software architecture outcome. I will give more examples about this on part-2, so have some faith on my expertise on this, we’ll get there.
Many of the things listed above will come up implicitly when discussing with your customer (you might need to sharp your skills to read-between-the-lines). For those that you consider a must-know, you’ll have to explicitly ask.
All I can assure you is that the biggest-more-expensive issues your software piece and development team will struggle with for the rest of the project’s life-cycle will be derived from how you effectively discovered non-functional requirements on time.
Soon I will publish the part-2 of this article.
** The picture of the right is the bad one.