In my previous post I explained that, as a developer, you do not create applications but in fact systems, living entities that react to their environment (browsers, servers, …). On this post I will describe a process that you can follow in order to create systems. This process has been inspired by the amazing work of Donella H. Meadows, the B-Method that I learned at the University and the Domain Driven Design.
This process is composed of 5 steps:
- Understand the problem
- Design your system
- Agree on the design
- Refine your design
- Generate your system
1. Understand the problem
Always remember that you are human
In order to create systems you need first to realize that you perceive things and understand the world as a human beeing. It means that when we think to a specific problem, we resolve it with our own mental representation of the world. We are never objective when we think. We are limited by our culture, life experience, mother tongue, … We can miss useful informations because we can not see them from our perspective. As a result the more you are and diverse you are to solve a problem, the better solution you get. So create the most diverse team you can and invite them to a meeting to start designing the system.
First of all listen without interruption people that are asking for a feature/solving a problem/… . Then ask questions about the context. Get the maximum informations you can and make all the team talk. It is very important. Everybody needs to feel heard during the meeting in order to be able to share without difficulty their own understanding of the context.
Speak the same language
The main issue in project is always communication, so be sure that everyone speak the same language, the user language, and not a technical one. For that purpose note on a paper all the words you use to define the context and write their definitions. So that everyone will know what you are talking about.
2. Design your system
Take a paper and a pen
Because if you can not design it, you can not explain it to other.
Create the border
Draw a big circle that represents the border of the system. Then write all the words taken from the list you made.
Write inside the circle the concepts that you think are part of the system. Write outside the circle the concepts that you think are not part of the system.
The border depends on your comprehension of the system and could change from one perspective to another. For example: when designing a web app, you can include the server in the system… or not. It depends on where you put this border.
Find what are the events that provoke a response from the system
Then look at the concepts that you put outside the system. Think how these concepts can interact with your system.
Create arrows that go into the system for each message that could be send to the system. And name the event responsible for this message.
Create arrows that go out the system for each message that could be send from the system. And name the event responsible for this message.
Design the model
Now look at all the words that you put inside the system. Create a square around each word. Then draw a line between each square that you think are related together. Do not add information on the link, just draw a line. The idea is to have an global overview of the concepts and their relations.
Find the core components
Name the components that you need to have to start the system and draw little circles that represents them. We will call them the core components.
3. Agree on the design
Now we have a complete overview of the system. We know:
- what is the border of the system,
- what are the events that provoke a response from the system,
- what is the model of the system and
- what are the core components of the system.
Be sure that everyone agree on the design and understand how the system is composed.
4. Refine your Design
Describe the model
Now that everyone agree on the design, you can describe more precisely the model. To do that, you need to ask:
- What are the properties of the model?
- What are the behaviors of the model?
- What are the type of links. Are they collection, inheritance, …?
- What are the events send by the model?
I encourage you to use UML to define the model. But keep it simple like we did before. Always use design that everybody can understand.
Find the initial states of the core components
Find what are the initial values of the core components of the system. The question you have to answer is simple: at which states the core components needs to be in order to start the system?
I encourage you to describe these values in a JSON object. It is human readable format that you can easily update.
Define the messages
Define what are the types of the messages send to the system and returned by the system.
Use also UML to define the structure of the messages.
5. Generate your system
Now you have define the model and find the initial states of the core components, generate the system from the model. Do not start to code, otherwise your code will be always desynchronized with your model. Then implement the behavior of your system from the generated code.
Designing a system is a complex task that needs the work of everyone. Technical skills are not necessary to design a system, but human skills are mandatory.
It was a quick overview of the process I use when I create systems. I did not go into specific details, I only described the main steps of this process so that you can adapt it to your work.
In my next post I will go more deeper on the model designing process and explain how to have a model synchronized with your running system.
Credits: cover image by Sergey Zolkin.
Top comments (8)
While I'm okay with the general approach of system design, I'm opposed to anything getting to the detailed level of UML.
I believe it's a broken notion that there is a useful description of systems that can both be read at a high-level and directly converted to technical implementations.
You're also doing over-design and this ends up slowing down project process, and paralyses participants by preventing them from deviating from an agreed upon design. Technology driven systems need to be highly flexible during develpoment or face an increasing risk of failure.
UML and its relatives have a point if you're throwing specifications over the wall to another team you can't interact with directly (or vice versa). Then you really do need to have things laid out with that kind of detail.
If you're throwing stuff over a wall then your system is doomed to failure. I know this kind of spec and hand-off approach was popular at one point, but it's basically a failed development strategy.
You need a two-way communication with the teams involved in the development of a product.
UML is attempting to patch a fundamentally flawed approach.
Sure, it's flawed if not outright The Wrong Way To Do Things, but that doesn't mean it's not still happening for reasons which are often outside developers' control. And if you want to have any chance of getting something usable out of that kind of process, you need to set stuff in stone.
When you let people design something on their own, they usually draw only boxes with lines. My point is that, when refining your design, you need to use the same convention to describe things, a simple convention that everybody understand and UML can be the right choice for some teams.
A better approach would be to have a human readable format that helps you to make your design (this format could generate UML diagrams) and create also your system at runtime (this format could generate your classes and components). This is the approach I chose for my project (I will develop that in another post).
Before you start: make the "business knowledge" person agree to engage in the process. It's going to take days off time to find the aggregate roots.
Also, don't use UML. UML is great if you've got a very complex relational data model and you want to get your OO designed up front; otherwise it's not much use. You're not "being enterprise" by doing UML like this, you need UML up front and part of the system creation.
I tried this method before but I had trouble getting the customer to explain their problems in this way. None of them wanted to engage like this. Instead we got them to write down user stories that described their business processes and then built the aggregate roots, entities and messages from that.
Wow, this is awesome. Need to test it