Decomposing the major building blocks and designing the software

Once I understand the bigger pictures, I start to zoom in and decompose each container further. However you decompose your system is up to you, but I look for the major logical components and their interactions. This is about partitioning the functionality implemented a software system into a number of distinct components, services, subsystems, layers, workflows, etc.


Using a sheet of flip chart paper and a set of index cards is an excellent way to get started. In the diagram above, each index card represents a major logical component/service that has been annotated with a high-level list of its responsibilities (e.g. operations) and the technology that the component will be implemented in. This is very similar to Class-Responsibility-Collaboration (CRC) cards although we're thinking about components rather than classes and showing collaborations as explicit connections between the cards.

If you were building an Internet Banking system, you might have distinct business focussed components for banking, authentication and secure messaging services in addition to technical components for auditing, logging and exception management. These components are the fundamental building blocks of your system and you should be able to understand how a use case or story can be implemented across one or more of those components. If you can do this, then you've most likely captured everything. If, for example, you have a requirement to audit system access but you don't have an audit component, then perhaps you've missed something.

Decomposing your overall software into a number of components is software design at a slightly higher level of abstraction than classes and the code itself. An audit component might be implemented using a single class but treating it as a distinct component lets you also see it for what it is, which is a key building block of your architecture. Working at this level is an excellent way to understand how your system will be internally structured, where reuse opportunities can be realised, where you have dependencies between components, where you have dependencies between components and containers, and so on. Breaking down the overall problem into a number of separate parts also provides you with a basis to get started with some high-level estimation, which is great if you've ever been asked for ballpark estimates for a new project.

Designing a software system at this level of abstraction is something that can be comfortably done in a number of hours rather than days or weeks and sets you up well for tackling design at the class and interface level without worrying about the overall structure.