As with many other disciplines of engineering, in software engineering we build models of the system before embarking on the effort to construct and assemble the finished product.
Depending on the complexity of the project, it is useful to realise that there can be many levels of modelling fidelity that can be employed. The initial steps can be the more traditional and “softer” modelling approaches, such as:
- stories for simple tasks, where it might be sufficient to capture a basic written story. This might highlight the key elements of the design and position the implementation relative to the design intent.
- design documents for slightly more complex systems, where it may become necessary to create a more complete and formal document of the design. This would generally contain strict definitions of terms, enumerations of subsystems, and details of user or stakeholder roles, as well as diagrams detailing how the system is to be decomposed and linked.
However, as the system complexity increases I start to introduce more explicit forms of modelling, such as:
- process models for some systems where the key element that needs to be captured is the process flow. That is, the flow of data across many disparate subsystems. The actual implementation may require performing complex operations in each of these subsystems, however, often it is useful to model only the data flows. That is, the base message types that will need to move between systems and the primary states and data dependencies in those systems.
- system models in other systems where more attention may need to be given to the internal state machines of different subsystems. However, for the purpose of modelling we can factor out and ignore issues of data persistence or subsystem replication.
For both of the more complex modelling requirements, the actor model of programming is well suited to building models. It allows for defining light-weight concurrent elements where the focus is on the state machines and the message flows.
In taking this approach, our architectural models become a far more stringent documentation of the design. That is, the design is in fact documented as code. Additionally, these models can be verified with a greater degree of surety since the models can be executed and their behaviour can be observed.
The nett results are:
- earlier verification of design correctness.
- more formal communication between design and implementation phases with much less ambiguity in intent.
- earlier opportunity for identifying areas for improvement or potential dead ends.
- a more natural stage for testing out new ideas that arise from changes in the business context or understanding, while not needing to immediately disrupt implementation efforts.
When further combined with mechanisms for verifying the alignment between these models and production code, we are then able to close the loop between development and architecture.
Ultimately, the projects are more focused and successful, as developers can focus on the details and minutia of the implementation, without having to tease out many of the necessary design decisions as a side effect of the software development process.
This increase in focus allows for more rapid delivery to production, with faster feedback to business and closure on projects.