Modular System Implementation Flow
written on June 6, 2019I (and probably lots of people working in partially modern software industry) are constantly facing the questions regarding the best flow for a modular system design and implementation.
The question of what technologies do we use, how do we use them and what will be the order of usage has been popping up many times for me in the recent years and they have been answered differently each time, resulting in trying different approaches and learning from the results.
My intention in this rather short summary is to sum it all up in an intentionally technology and language agnostic way, even though I will provide some key player names.
It's also important to know, I'm not going to justify any approach here, its rather a summary of experience on more than five medium to large projects I have been part of in past four years and a rather self-note to keep an eye on.
Where to start? How to progress?
- first API design (specification) in language agnostic technology, like OpenAPI
- then contract design, Consumer Driven Contract in language/technology agnostic way, like Spring Cloud Contract as external project
- finally code the actual producer and/or the client against spec and test it using the contract
Starting to code is the first reaction of most developers when a new idea occurs to their mind. This however will take more time and increased chance that the idea will be lost or missed in the processes.
Specification first, then contracts, then code.
Start by documenting your idea, first in rather format-free text. Then improve it to a structured spec and just afterwards start to do any coding. This will prevent the goal from being lost in minimal details.
What to generate?
Code generation is a tempting trap that many-a-lot even experienced devs fall into it. Reconsider it! many times fighting with a tool takes way more time than writing a 5 line long class.
But in a more structured way, following possibilities can be discussed regardless of available tooling or possibilities.
- Generating contract from spec:
The fact is, contract might (and have to) include way more than a spec. For example a system might have a public facing API (which is described in spec) but also uses and publishes information over a messaging system for internal usage of other components or systems. A contract might cover both aspects: public and internal interfaces expectations. Whereas an API spec shall only contain public API. This means driving and generating contract from spec is not always (almost never!) an option. - Generating spec from contract:
Also in this case, spec might contain more than contract. Spec could include information and documentation targeted for humans which are not and in many cases can not be described in contracts, depending on the technology used for contracts or even logically seen. Also here the conclusion is that a good spec can not be derived from a contract without having missing bits and details. - Generating server and/or clients from spec/contact:
This, might be a feasible solution depending on tooling and other parameters. However, it is important not to be bound and trapped by it. Specially if code generation is used blindly and as part of the build process. Which means no tuning is done inside generated code.
What might be a better approach is to generate code offline, copy it to own source, further tune it and then use it. This might even happen in form of partially generating code. Like just generating DTOs, or only API interfaces. This idea matches partially the Generation Gap pattern.
All in all what should be kept in mind is the quality of code and resulting software and not how many lines of code I'm sparing myself or my team.