The software system in the period of active growth is a really wild beast. Excited developers with creative minds and feature obsessed marketers consistently add the fuel to this fire of software creation.
Uncontrollable growth, race for features and engineering wonders sometimes give rise to a monster – a software system bloated with useless features, over-engineered internals and erratic behavior.
At some point, developers stop understanding the system and start fearing it while doing less and less productive attempts to fix and grow it under pressure from screaming users and management.
What is happening during this transformation of the bright promising software idea into a scary monster system?
Here is a complete state diagram of a wild young software system growth:
The root reason of this scary transformation is get-out-of-control complexity. Eventually, Success Loop dries up and Failure Loop takes over and lead the software system to disaster.
What could prevent this pitiful descent and ensure long-term health of the software system?
Here comes Architecture!
The primary goal of the software architecture is taming complexity of the functionally growing software system under physical load from demanding users, harsh environmental impact and psychological pressure from managers. Architecture attacks and reduces effects of the software development Failure Loop.
Good architecture strengthens and aligns system ideas, muscles and structures in areas most impacted by stress, changes and expansion.
Three Architecture Responsibilities:
- Explain and carry The Theory of the system. Align new ideas and needs with system realities.
- Guide system Organization. Enable fast growth and modifications.
- Support required system Qualities (stability, performance, security, etc). Make system behave well.
1. Architecture Carries The Theory of The System
A theory is the more impressive the greater is the simplicity of its premises, the more different are the kinds of things it relates and the more extended the range of its applicability. – Albert Einstein
Creating Software Architecture means building a common theory that explains the software system. It is an attempt to join many fragmented pieces into a package that is consistent and easy to digest for human brains Architecture creates bird’s-eye view on mundane torrent of code details, states and behaviors.
Architecture is the essence of what, why and how of the software system. It is a set of ideas and explanations that allow humans to make sense of the system. A small system require little help to understand. A large complex system requires a lot of explanation – volumes of information, pictures and tales from people who had firsthand account of the battle for the system.
- Simplicity - fight complexity on every possible level. Simple systems are easy to grow and maintain. More complex system lead to stressed minds and broken hearts.
- Clarity - tune everything about the system (ideas, design, code, documentation, etc.) for better digestion by human brains.
- Interpretation - how close the system reflects the business concepts in implementation. Is it direct translation that guides system organization and logic or irrelevant pile of technical ideas?
- Domain Driven Development is an excellent approach for translating customer domain into relevant architecture
- Conceptual models translate vague business ideas into formal description of the problem space.
- Metaphors and abstractions bring disjointed ideas into coherent whole that is easier to digest.
- Shared language and domain-driven naming synchronize customer domain and technical ideas.
- Storytelling, user personas and usage scenarios help to convert overwhelming information massives into easy to remember chunks that are friendly for developer’s brains.
2. Architecture Guides System Organization
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
The software system is a system (not surprisingly) with elements, structures, connections. All this stuff is a projection of the theory into practice.
- Flexibility - ease of change without painful struggle, breaking the system and causing unexpected butterfly effects (side-effects).
- Integrity - alignment and good fit of parts with each other and overall theory of the system that create coherent tight assembly.
- Preservation - ease of keeping original system intent and healthy organization without hacks and workarounds.
Structure and Dependencies
Complexity and problems are often coming from internal mess and tangled dependencies.
- Separation of Concerns – breaking down and taming smaller groups of related elements reducing overall complexity of the system (modules, hierarchies, layers, etc.)
- Restrain dependencies – reduce elements connections (with isolation) and side-effects (with orthogonality).
- Generalization - rely mostly on abstractions and interfaces, hide concrete implementation on lower level.
- Federation of specialized components – favor reusable smaller components with narrow responsibilities to big rigid elements or procedures suited only for one scenario.
- Design and Architecture patterns are an excellent source of design ideas and their trade-offs.
Every piece of knowledge must have a single, unambiguous, and authoritative representation within a system. – The Pragmatic Programmer
Producing more code inevitably increase complexity and reduce mental control. Architecture helps to focus on keeping clean minimal codebase for needed functionality.
- Use 3d party – integration with existing libraries, components and services could significantly reduce system codebase and required effort. Certainly, there are some risks and shortcomings.
- Maximize reuse & follow DRY – avoid duplication and cloning
- Refactoring – continuously improve system design to keep it in minimal, optimal and clean state
- Abstraction - synthesize system concepts and elements to avoid different solutions to similar problems.
A system should be open for extension but closed for modification – The Open Closed Principle
A software system should provide an easy way to extend and add new features without invasive surgery on already tested and working parts. Architecture helps to consciously establish this way.
- Published API – stable and officially endorsed set of interfaces that open ways for safe and supported way to manipulate a system.
- Extension points – clear definition of intent to extend through interfaces, inheritance, etc.
- Pluggable architecture – allow to add elements in formalized way with open framework infrastructure and component specifications (WordPress, jQuery)
3. Architecture supports System Qualities
Better to be rich and healthy than poor and sick. – Russian proverb
Correct, secure and responsive system is much better than buggy, vulnerable and slow. However complex software systems under heavy unpredictable usage could easily degrade to a pitiful state of sick unruly monster. Proper architecture could prevent this bad behavior and keep the system within borders of correct, well-performing and stable state in most situations.
There are three important characteristics: Stability, Performance and Protection.
- Resilience and self-healing – ability to survive and recover from surges and failures
- Elements packaging and release management – the way to package and release elements to avoid disruptive shocks to the system on updates.
- End-to-end testability, automated testing and sandbox environments – ability to completely simulate the system live behaviour in short time before release into wild
- Freeze published interfaces and provide legacy support for dependant subsystems
- Monitoring, signal system and self-assessment – promptly alert when something goes wrong
- Operational manageability and control - easy to manage and configure
- Optimize processing, data flows and storage - achieve right balance between fresh data and cache, throughput and latency, processor cycles and memory.
- Scalabiliy - ability to scale the system with increased load (replication, distribution, partitioning / sharding)
- Elimination of bottlenecks and easing of stress lines
Protection – from threats, disasters and surges
- Security, proactive defence, threat assessment and detection - resist hackers and vandals
- Backups, standby reserves / redundancy, multiple locations - avoid single points of failure and have ability to fully restore in case of bad crashes and losses.
- Prepare for worst - closely monitor points of failure; simulate and train people to recover from disasters.
As any theory, software architecture could be bad or great, helpful or misleading, clear or convoluted. Architecture directly impacts the fate of any non-trivial software system.
The real architecture is not a static theory or prescription how to build the software system. This is a theory that emerges with the growth of the system, refined by discoveries and failures. Developers adapt this theory to fit harsh realities of the external world, confusing requirements, management pressure and user demands. And in return, good architecture helps to keep the system consistent, stable and controllable over the time.
The main benefit of architecture is ability to effectively grow the system that embrace demands, bring market success and makes people happy. Tame your software monster and make it obedient machine!