System Design and Software Design in Distributed Systems
System Design and Software Design are often used interchangeably. This blog post shares how we define them and use them in the context of building distributed systems.
When you ask an engineer to provide clear cut definitions of System Design, System Architecture, Software Design, Software Architecture… the conversation suddenly has lots of hand waving, context-specific definitions, and “according to [insert popular engineering book]”.
The truth is that, as with many terms in software engineering, there isn’t a clear-cut, industry-wide definition. That’s because it’s both a broad area of study, but also because it’s a constantly moving target due to the rapidly evolving developments in the tech ecosystem.
Let’s reduce the hand waving
While building Multiplayer, we realized that we were also using these terms interchangeably. Our mission is to make visualizing, designing, and managing distributed systems effortless for developers, so it was inevitable that we would have to define the scope of “system design”, agree on what we expect when we say “system architecture”, and describe the people who are building the “software systems”.
Even without clear-cut definitions we would be able to get our point across, but we felt that in order to ensure full alignment, we needed clarity and a reduction in hand-waving in all of our communications. Both internally, in how we discussed our product and roadmap, and externally, in how we described our solution to other developers.
We came up with shared definitions for all these terms, specifically in the context of distributed systems, and we hope you find this useful as well.
There is a lively debate on where the boundaries of each term lie and many smarter people than us have written extensively about it. This is not meant to be a “glossary to rule them all”, but insight into how we think - and talk about - these topics.
Strategic vs Tactical
The best way to think about System Design vs Software Design is not in binary form, but as activities that fall on a spectrum from more strategic to more tactical.
Depending on your use case (e.g. Web Application, Mobile App , Embedded System, etc.) the final architecture and implementation can be very different. In fact, there is no “one-size-fits-all” approach and solution - expecting a single architecture to work for all use cases, or even most of them, is unrealistic, especially as it will change over time.
There are however, two immutable and universal “laws” that apply to both system and software design:
- Everything is a trade off
- Why is more important than how
Terms in Distributed Systems
1. Distributed Systems
Distributed Systems, also known as distributed computing, are a collection of multiple independent software components - located on different machines that communicate through a network - that split up the work, coordinating efforts to achieve common goals.
The ultimate goal of a distributed system is to enable the scalability, performance and high availability of applications - in fact, the vast majority of products and applications rely on them nowadays.
The size, complexity, and topology a Distributed System can vary significantly, from as few as three servers to a few thousand servers, making their design, development, and management a unique challenge.
2. System Design
“A system’s architecture is a representation of a system in which there is a mapping of functionality onto hardware and software components, a mapping of the software architecture onto the hardware architecture, and a concern for the human interaction with these components. That is, system architecture is concerned with the totality of hardware, software and humans.” - “Software Architecture in Practice”
System Design is the process of defining the System Architecture and how it will be implemented, to meet the requirements and expected functionality of the application.
In other words, it involves defining the high-level conceptual structure of an entire complex system (System Architecture) and all its major components and interactions - encompassing all aspects of the system (i.e. software, hardware, data, interfaces, and user interactions), to ensure that they work together effectively and efficiently to achieve specific goals.
System Architecture is often intended for a broader audience besides developers: it includes stakeholders, managers, and decision-makers who need to understand the system's design at a conceptual level.
- System Requirements Documentation - It records and explains the functional and non-functional requirements of the system, highlighting how they will drive the architectural decisions (or how the requirements might be influenced by the System Architecture).
- System Architecture Documentation - It outlines the goals, constraints, and rationale for the chosen architecture. This is the start of the Architecture Decision Records (ADRs), where significant architectural decisions will be recorded throughout the software development lifecycle.
- System Architecture Diagram - It provides a clear visual representation of all the components, services, and their interactions and relationships allowing you to create a full platform architecture view. Depending on its complexity, you may need to produce Sequence Diagrams and Network Diagrams (or other UML diagrams or flowcharts).
Keep in mind that System Design is an iterative process: it will evolve as the technology ecosystem evolves and as your application requirements change. For the System Architecture Diagrams to be effective tools, they need to be constantly updated and provide a real-time, accurate, and interactive view of your system.
Likewise, all the documentation mentioned should be always up-to-date, thorough and easily accessible - there are few things in the developer world as painful as incorrect or outdated documentation!
2.a Phases in the System Design Process
Here are some of the key phases of the System Design process:
- Technology selection: Choosing the appropriate technologies, frameworks, and tools for implementing the system.
- Capacity planning: Estimating the approximate scale of the system. In other words, doing “back of the envelope calculations” about active users, reads vs writes, queries per second, storage, throughput, number of instances required, etc. (Tip: these are numbers every developer should know)
- Scalability and performance analysis: Planning the best approach to accommodating future growth (e.g. vertical vs horizontal scaling), while also implementing strategies for maintaining and optimizing the system's performance, including load balancing, caching, and query optimization.
- Tradeoff analysis: Analyzing the impact of various design choices on the functional and non-functional requirements (e.g. reliability, data Integrity, privacy, etc.) and listing the reasons why certain approaches were discarded or chosen.
- Interface design: Listing out all the key interaction points between the users and the system (e.g. how users can add information, how a system represents information to users, etc.) and the interfaces between different components of the system, including APIs, protocols, and data formats.
- Data design: Defining the system’s data model, how data will flow between the different components and inputs/outputs of a system.
- Risk mitigation: Identifying potential bottlenecks in the system, risk factors and mitigating strategies. This also includes outlining the security practices planned (e.g. authentication, authorization, encryption, and data protection) and listing whether there is any known technical debt incurred by implementing the selected System Architecture.
2.b System Architecture Styles
As with many IT terms, “Architecture Styles” and “Architecture Patterns” are often used as a synonyms:
“An architectural style (Base et al. 1997) and an architectural pattern (Buschmann et al. 1996) are essentially synonymous.” - Practical Guide to Enterprise Architecture, James McGovern
"We are still far from having a well-accepted taxonomy of such architectural paradigms, let alone a fully-developed theory of software architecture. But we can now clearly identify a number of architectural patterns, or styles, that currently form the basic repertoire of a software architect.” - An introduction to software architecture, David Garlan and Mary Shaw
However, we’ve opted to distinguish between them and we define Architectural Styles as the overall structure and organization of a software system from a 10k feet view (i.e. it shows the highest level of abstraction of the system design).
Architecture Styles answer fundamental questions such as how the system components communicate, how data flows, and how the system is divided into modules or layers. Changes to Architectural Styles are significant and can be costly - they involve restructuring the fundamental aspects of the system and can have a long-term impact on the project.
System Architecture can often be categorized into two broad paradigms:
- Centralized, which are typically represented by client-server systems
- Decentralized, which are exemplified by peer-to-peer systems.
In this blog post we delve into the specifics of Architecture Styles such as:
- Monolithic
- Microservices
- Event-Driven
- Serverless
- Edge Computing
- Peer-to-Peer
However, there are many more to explore: Layered, Service-Oriented (SOA), Space-Based, Microkernel, Cell-Based, Cloud computing, etc.
2.c Distributed System Design Patterns
Distributed systems are ubiquitous in modern software and many businesses face common problems related to data storage, messaging, system management, and compute capability, which they solve with similar solutions. These frequently used solutions are considered Distributed System Design Patterns.
For example, here are top seven most-used Distributed System Design Patterns:
- Ambassador
- Circuit Breaker
- CQRS
- Event Sourcing
- Leader Election
- Publisher / Subscriber
- Sharding
These are two completely different terms although, understandably, they are easily confused.
A Design System is a collection of repeatable components that allows developers to create interfaces and experiences quickly; keeping a consistent look and feel in terms of colors, typography, spacing, etc. It goes beyond just a style guide and patterns library - it also includes standards and documentation on why and how to use the design components.
3. Software Design
“[…] software architecture consists of the structure of the system [i.e. Software Architecture Styles], combined with the architecture characteristics the system must support, architecture decisions, and finally design principles” -* Fundamentals of Software Architecture
* Availability, Reliability, Testability, Scalability, Security, Agility, Fault Tolerance, Elasticity, Recoverability, Performance, Deployability, Learnability
Software Design defines the Software Architecture, providing a blueprint / roadmap / high level structure of the entire software system
It zooms in on the nitty-gritty of how individual software components are crafted and communicate, and how the code is written (e.g. classes, functions, and modules).
Although Software Architecture has a narrower scope than System Architecture (i.e. it specifically focuses on the software), it is similarly dynamic: it evolves overtime, as the application requirements change.
- Detailed Software Design Documentation - It outlines the specifications for how each individual component, module, or subsystem will be implemented and all the interactions and dependencies between them (e.g. technical details, environment variables (with required, optionals, default values), algorithms, data structures, coding guidelines, run time configuration, etc.)
3.a Phases in the Software Design Process
Software Design is usually articulated into two phases:
- Conceptual Design phase: The initial phase of software design where you focus on creating a high-level, abstract representation of the software system. It involves defining the overall structure, major components, and the relationships between them.
- Technical Design phase: Also referred to as low-level design, is the subsequent phase where the high-level concepts from the conceptual design are translated into detailed specifications for the actual implementation of the software system. It delves into the specifics of algorithms, data structures, and coding standards.
Software Design is considered one of the initial steps of the Software Development Life Cycle (SDLC).
3.b Software Architecture Styles
Often there is no distinction between System and Software Architecture Styles, however, it’s worth mentioning some Architecture Styles outline specifically how to organize the information at the software level (and not at the system level). For example:
- Component-based Architecture
- Domain Driven Design (DDD) Architecture
- Object Oriented architecture
- Hexagonal Architecture (Ports and Adapters)
- Clean Architecture
- Functional Architecture
- Data Driven Architecture
3.d Software Design Patterns
Software Design Patterns are reusable solutions to commonly occurring problems in software design - e.g. specific coding and implementation issues with the design of classes, objects, and their interactions. They are akin to pre-made blueprints that you can customize to solve a recurring design problem in your code.
Changes to Design Patterns have a local impact, affecting a specific area of the code.
- Creational patterns
- Factory Method / Virtual Constructor
- Abstract Factory
- Builder
- Prototype / Clone
- Singleton
- Structural patterns
- Adapter / Wrapper
- Bridge
- Composite / Object Tree
- Decorator / Wrapper
- Facade
- Flyweight / Cache
- Proxy
- Behavioral patterns
- Chain of Responsibility / CoR, Chain of Command
- Command / Action, Transaction
- Iterator
- Mediator / Intermediary, Controller
- Memento / Snapshot
- Observer / Event-Subscriber, Listener
- State
- Strategy
- Template Method
- Visitor
Conclusion - TL;DR
To bring all of these terms together, lets consider a web-based e-commerce application.
- System Design → It would define the System Architecture and its implementation to meet the agreed requirements (e.g. handling user requests, having a product catalog, processing orders and payments).
- System Architecture Styles → It would clarify that the system should follow a Microservices Architecture to enable the modularization of functions like user account management, product catalog, and payment processing into distinct services.
- Distributed System Design Pattern → To address scalability and performance challenges it would implement a "Load Balancer" pattern to distribute incoming web traffic across multiple servers to ensure high availability and handle a large number of concurrent users.
- Software Design → It would focus on defining and implementing the Software Architecture - the overall structure of the software components (e.g., databases, web servers, major software modules), including the separation of concerns. For instance, it would define the separation of the presentation layer (user interface) from the application logic and data storage. It would address how to specifically implement user interface elements like product listings, shopping cart views, and order checkout. It would also address database design for storing user accounts, product data, and order history.
- Software Architecture Styles → It would use a Clean Architecture to guide how to organize components, ensuring that high-level policies (e.g., ordering process) are decoupled from low-level details (e.g., database operations).
- Software Design Patterns → To improve the maintainability and reusability of code, it might apply the "Factory Method" pattern for creating product objects with different attributes (e.g., color, size) and the "Singleton" pattern for ensuring a single instance of a shopping cart is available throughout the user's session.
Multiplayer allows you to design, develop, and manage your distributed software with a visual and collaborative tool. Visualize your system architecture, regardless of its style or complexity, from a 10,000 foot view down to the individual components and dependencies. Sign up for free to see for yourself! 😉