-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add existing decisions from arch-as-code repo
Copied from https://github.com/ministryofjustice/hmpps-architecture-as-code/tree/2d61d29da26ae24cec3446ca1d9bf6a35c9fc4c4/decisions/interventions That repository will pull the decisions from this place.
- Loading branch information
Showing
4 changed files
with
267 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# hmpps-interventions-docs | ||
|
||
Decisions and other shared documentation that spans across all applications in Interventions. | ||
|
||
- [Architecture decisions](doc/adr/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# 1. Split user and business interfaces by default | ||
|
||
Date: 2020-11-02 | ||
|
||
## Status | ||
|
||
Accepted | ||
|
||
## Context | ||
|
||
### Need for sustainable services | ||
|
||
The Ministry of Justice 2022 Digital Strategy defines "Building sustainable services" as a priority. | ||
|
||
As the domain model of HM Prisons and Probation Service (HMPPS) is big, we aim to build sustainable services | ||
around [bounded contexts][bounded-context], making it necessary to integrate with other contexts. | ||
|
||
### Domain and business logic | ||
|
||
Historically, many systems built in HMPPS did not expose an API for the business logic and/or were managed by third | ||
parties, leading to difficult integration: we see business APIs beneficial to have from the start. | ||
|
||
Existing APIs that are thin layers over a database (entity services) are easy to write but hard to use as it pushes | ||
the need to handle business logic back to the clients. | ||
|
||
We have seen services with a frontend/backend split where frontend clients accumulated business logic as the | ||
backend service fell back to provide a CRUD entity service over the database; this is not sustainable. | ||
|
||
_Sam Newman_ writes in _Monolith to Microservices_ (O'Reilly, 2019): | ||
|
||
> Fundamentally, in a system that consists of multiple independent services, there has to be some interaction between | ||
> the participants. In a microservice architecture, _domain coupling_ is the result—the interactions between services | ||
> model the interactions in our real domain. | ||
We want to aim for domain-level coupling to avoid business logic drifting into current and future clients. | ||
|
||
### Languages in "adopt" | ||
|
||
HMPPS Digital is heading towards using Java/Kotlin and node.js as their primary language choices. | ||
|
||
The [current HMPPS Digital tech radar][radar] elects the mentioned languages in _adopt_. It also mentions Ruby (for London); | ||
however, the current direction is to reduce regional differences as it is difficult to hire developers who are comfortable | ||
and happy working with multiple languages. | ||
|
||
The department's talent pool reflects this split; there are: | ||
|
||
- many node-focussed frontend specialists, | ||
- many Java/Kotlin-focussed backend specialists, | ||
- a few full-stack developers. | ||
|
||
## Decision | ||
|
||
We will **create standalone business interfaces (business/domain APIs) by default**. | ||
|
||
We will **split the user interface** from the API's component to enforce the use of the business API by default | ||
and better utilise the talent we have. | ||
|
||
We realise this is an optimisation to build durable domain-coupled systems at the cost of some team autonomy. | ||
|
||
## Consequences | ||
|
||
**Benefits** | ||
|
||
- The APIs we create can be used by other teams if they wish to hook into our business processes. | ||
- There are reusable best practices already available from DPS for separate API components. | ||
- The pool of talent who can join our team from HMPPS is larger. | ||
|
||
**Challenges** | ||
|
||
- We need to be more careful on what services we create and what API they have. This increases _governance_, | ||
which we must keep lightweight. | ||
- Contracts between the UI and the service components will take a while to stabilise, creating churn in the beginning. | ||
- Expectations between the parts have to be clear to avoid blocking others or taking up time. [Consumer-driven contract testing][cdct] can mitigate. | ||
|
||
In short, we gain _sustainability_ benefits by trading off _governance_ around the API contracts. | ||
|
||
[radar]: https://ministryofjustice.github.io/hmpps-digital-tech-radar/docs/index.html | ||
[cdct]: https://www.thoughtworks.com/radar/techniques/consumer-driven-contract-testing | ||
[bounded-context]: https://martinfowler.com/bliki/BoundedContext.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# 2. Decouple with events | ||
|
||
Date: 2020-11-02 | ||
|
||
## Status | ||
|
||
Accepted | ||
|
||
## Context | ||
|
||
The Dynamic Framework interventions are the first intervention type onboarded by this system. | ||
|
||
### Many new teams | ||
|
||
In the current probation programme landscape, we expect | ||
|
||
- many new digital teams, | ||
- many changes to existing systems, | ||
- different times when integration happens as teams will have separate priorities. | ||
|
||
Specifically, we will have other teams to | ||
|
||
- assess risks and needs, | ||
- manage a sentence, | ||
- manage a supervision in the community, | ||
- manage my progress. | ||
|
||
All of these teams would have interest in actions carried out in interventions. | ||
|
||
### Nature of probation | ||
|
||
Additionally, probation | ||
|
||
- reacts to what happened in real-life with the supervised service users, | ||
- has various priorities, depending on what happened. | ||
|
||
## Decision | ||
|
||
The above qualities point towards a decentralised way of integration and notifying each other. | ||
|
||
**We will use _domain_ events to decouple** from other production services. | ||
|
||
Our domain event payloads will contain: | ||
|
||
- transport-specific concerns, e.g. request and tracking IDs, publishing timestamps, etc. | ||
- domain context, e.g. URL on how to find out more, intervention ID, service user ID, etc. | ||
- core domain data, which is required to make sense of the event | ||
|
||
The payloads will **not** contain further data by default. **Consumers can request further details via the business API**. | ||
|
||
We do not intend to build event sourcing. We will **not** build event logs by default. | ||
|
||
**Examples** | ||
|
||
For example, our events may be: | ||
|
||
- intervention completed | ||
- service user appointment booked | ||
- (many others) | ||
|
||
## Consequences | ||
|
||
We will build our intervention services to emit known significant domain events by default. | ||
|
||
**Benefits** | ||
|
||
- The decoupling allows us developing almost all user stories without waiting on endpoints to be finished. | ||
- New and old systems can join as consumers any time. | ||
- We contribute to an event _vocabulary_ for probation, enabling systems with similar responsibilities to | ||
start publishing the same events. | ||
- Same events from different systems enables us to start using the strangler fig pattern | ||
by moving the source of those events elsewhere. | ||
|
||
**Challenges** | ||
|
||
- This architecture is asynchronous and distributed: | ||
- Request tracking and error handling needs to be built-in to understand what happens in production. | ||
- It is harder to set up a certain state for pre-production testing as we have to know what events have to happen. | ||
- Lack of atomic transactions: | ||
- We must not use events that need to be rolled back as a result of a consumer failing to process them. | ||
- Creation, maintenance, and governance of the event contracts is difficult: | ||
- We need to version the events from the beginning, to avoid backwards-incompatible changes blocking consumers. | ||
- We need to use event names that are aligned and understood by everyone in HMPPS. | ||
- We need to document which services emit which events to make discovery and testing easier. | ||
|
||
In short, _governance_ will have a much more important role. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# 3. Use Git commits to explain our work | ||
|
||
Date: 2020-11-24 | ||
|
||
## Status | ||
|
||
Accepted | ||
|
||
## Context | ||
|
||
We are going to be developing a new software system as a team. | ||
|
||
### Understanding decisions | ||
|
||
At any point in time, our codebase will be an aggregate of many influences. It | ||
reflects, for example: | ||
|
||
- conversations that we’ve had as a development team | ||
- conversations with other members of the project team | ||
- conversations with stakeholders | ||
- technical facts we’ve learned from outside sources | ||
- things we’ve learned from failed attempts | ||
- ideas we’ve had as individual developers | ||
- compromises that we’ve had to make in the interests of time | ||
|
||
As the team develops the service, it is very likely that we’re going to have | ||
questions about why the codebase is the way that it is. We might see a certain | ||
piece of functionality that doesn’t make sense, or a piece of code that | ||
seemingly could have been written more simply. In order to know whether we can | ||
change these things, we need to first understand the context in which they were | ||
originally done, so that we can assess whether the same conditions still hold. | ||
Without being able to understand the motivation, we’ll find it difficult to | ||
confidently make changes that affect these areas. | ||
|
||
The answers to these questions might live in people’s memories. But people | ||
forget things, so maybe not. Also, the development team is not static - today’s | ||
developers might not be here tomorrow. This is especially true on this project, | ||
where several developers come from external organisations and will leave the | ||
project in the relatively near future. | ||
|
||
We need a way to record these decisions so that they can be easily discovered by | ||
the team at any point in the future. | ||
|
||
Every change to the codebase is accompanied by a Git commit. The commit message | ||
for this commit provides us with a space to explain any relevant context that | ||
lives behind the change. | ||
|
||
### Reviewing work | ||
|
||
When we develop software in a team, we spend quite a lot of time reviewing other | ||
developers’ code. Sometimes, multiple developers will review a single pull | ||
request. We want to make sure that reviewing a pull request is not a | ||
time-consuming process. | ||
|
||
As developers opening a pull request, we should think about how we present our | ||
work to others. We should make sure that we present our work in a way which is | ||
easy for others to understand. We could do this by splitting our work into | ||
logical Git commits, each of which make a single change, with an accompanying | ||
commit message which explains the change and addresses any questions that we | ||
think a reviewer might have about the change. | ||
|
||
We should also consider how merge commits can impact the reviewability of our | ||
pull requests. Merge commits stop the pull request from being a simple linear | ||
sequence of commits. Also, the diff of a merge commit, as presented by GitHub, | ||
can often be hard to understand. | ||
|
||
### The Git repository is probably immortal | ||
|
||
There are other places where some of the codebase’s influences might be recorded | ||
— deliberately or not. For example, Trello cards and their comments, GitHub pull | ||
request messages, GitHub pull request comments. There is sometimes a temptation | ||
to think that these tools will be around forever, but this is not true. The Git | ||
repository is the one of the few things that we can be pretty sure will be | ||
around for the lifetime of the project. | ||
|
||
## Decision | ||
|
||
When we open a pull request, we will make sure that we present our work with a | ||
Git commit history that tells a clear story of the work that we’ve done and why | ||
we’ve done it that way. | ||
|
||
Our pull requests will have a linear history, meaning that they will not contain | ||
any merge commits. | ||
|
||
The pull request message will be a summary of the work that we’ve done, but | ||
any important information that it contains will also be in the commit messages. | ||
|
||
If we make changes to a pull request, we will re-structure our commits to make | ||
sure that they continue to tell a useful story. | ||
|
||
When we merge a pull request into the main branch, we will preserve that pull | ||
request’s commits, and not squash them into a single commit. | ||
|
||
## Consequences | ||
|
||
It takes time to produce good commits. It might take even more time if a | ||
developer needs to become familiar with some Git functionality that they haven’t | ||
used before, like rebasing. This might slow down an individual developer working | ||
on a feature. But, even just the time saved by making code review easier for | ||
multiple developers is likely to mitigate this. |