The Idea
You can understand a simple thing by just observing it from the outside.
If a thing is not simple, you won't be able to understand it by observing it just from the outside. To understand it, you split it into smaller things that you can understand by just observing from the outside. Usually, you can't really split the thing: the parts will still interact with one another. A good decomposition will lead to small and simple interactions between the parts.
One simple thing
Three parts
A good architecture makes it easy to find the effects of an action. The less dependencies you have between the components, the easier it is to follow the path from the action to the effects. So, a good architecture decomposes a system in parts that minimizes dependencies between the parts.
Complex
When the system is decomposed into only a few (e.g. 3) parts, a system architecture where every part depends on every other part may not seem unnecessarily complex.
Simple
When a system is decomposed into only a few (e.g. 3) parts, a system architecture where the parts depend only on one other part looks a bit simpler, but may not seem worth the effort. If you start like this it is important to realize that adding more parts will lead to a mess.
Nine parts
Complex
Simple
What is a good decomposition?
A good decomposition is generally one that makes it easier to understand the system.
Approach A - Minimize the number of connections per module
With this approach, we calculate the ratio between the connections and the possible connections. You get a number between 0 and 1 with lower values indicating a better decomposition. A value of 0 is the perfect decomposition, 1 is the worst decomposition possible (using this metric). One part of the work of an architect is to minimize this value.
As an example, let's have a look at a decomposition of a system in the components A, B and C. This leads to 3 * 2 = 6 possible connections (AB, AC, BA, BC, CA, CB). A bidirectional connection A ↔ B counts as two connections (A → B and B → A).
If your decomposition has 0 connections, its quality score is 0 — the best possible value. This will be the case if you can decompose the system into modules that are completely independent of one another.
If they are not independent, 2 connections will be as good as possible, the quality of your decomposition is $\frac{2}{3 \times 2} = \frac{1}{3}$.
If you have 6 connections (all three components are bidirectionally connected), the quality of your decomposition is $\frac{6}{3 \times 2} = 1$, which is the worst value possible.
Approach B - Change in Environment to Change in System relationship
List possible environment changes with their probabilities. Then calculate what percentage of the system each change affects. Do this for several decompositions. The smaller the percentage, the better the decomposition.
| Change in Environment (Probability) | System affected (0=nothing, 1=all) | Total |
| Inform via letter instead of email (0.1) | 1 | 0.1 * 1 = 0.1 |
| Prices calculated daily automatically (0.05) | 1 | 0.05 * 1 = 0.05 |
| Not only one but multiple sites (0.5) | 1 | 0.5 * 1 = 0.5 |
| Responsible can define a delegate (0.8) | 1 | 0.8 * 1 = 0.8 |
| Total | 0.1 + 0.05 + 0.5 + 0.8 = 1.45 |
| Part A (0.2 of the system) affected | Part B (0.4 of the system) affected | Part C (0.4 of the system) affected | Total | |
| Inform via letter instead of email (0.1) | 0.2 | 0 | 0 | 0.1 * 0.2 = 0.02 |
| Prices calculated daily automatically (0.05) | 0 | 0.4 | 0 | 0.05 * 0.4 = 0.02 |
| Not only one but multiple sites (0.5) | 0 | 0 | 0.4 | 0.5 * 0.4 = 0.2 |
| Responsible can define a delegate (0.8) | 0.2 | 0 | 0.4 | 0.8 * (0.2 + 0.4) = 0.48 |
| Total | 0.02 + 0.02 + 0.2 + 0.48 = 0.72 |
Some simple decompositions
Layering
|
User Interface Layer
|
|
Business Logic Layer
|
|
Data Access Layer
|
Tiering
The idea here is, that you run every layer on a separate computer. The presentation tier runs on the users computer (e.g. in a browser or terminal). The business logic in the backend (e.g. a web server) and the data tier on a database server.
|
Presentation Tier
|
|
Application Tier
|
|
Data Tier
|
Feature Folders
The idea here is, that you decompose by feature first (so, a feature folder containing all layers/tiers necessary for the feature).
|
Feature 1
User Interface
Business Logic
Data Access
|
Feature 2
User Interface
Business Logic
Data Access
|
Feature 3
User Interface
Business Logic
Data Access
|
Structural elements for decomposition in C
| Project |
| Directory |
| Source File |
| Function |
| Statement |
Structural elements for decomposition in C#
| Solution |
| Project |
| Namespace (~path) |
| Class (~file) |
| Method |
| Statement |