Are Single-Page Applications Bounded Contexts — and what the heck is inside a Bounded Context?
In the previous article in this series we arrived at a simple, but rather abstract definition of what a Bounded Context(BC) is. This definition seemed to confirm my intuition that a Single-Page Application(SPA) should be part of the same BC as its server-side API, but does it really?
To my mind, if in the SPA I’m dealing with a
ProductViewModel, the data for which I received from the
api/product/:id endpoint, endpoint that was custom made for the particular use case served by
ProductComponent by members of my team, then we're talking the same Ubiquitous Language.
I’ll admit that due to the abstract nature of the definition of a Bounded Context, someone could arrive at a different conclusion. My conclusion is influenced by the fact that I’m a full-stack developper and usually work on multi-disciplined teams who do vertical slices.
But what if the people in charge of developing the
api/product/:id endpoint are technically not on my team and teams are split between client-side and server-side 🤮? Also, the
ProductViewModel might not be a perfect 1 to 1 mapping of the server-side
Product entity, doesn't that mean that when I'm thinking of a Product I'm not thinking of exactly the same thing as my server-side brethren?
A Bounded Context is composed of more than a domain model.
By that logic though, even in a standard MVC type app, where the pages are rendered on the server, you would have to say that the Bounded Context excludes the Controller, the View and the Model. Is that what Vernon envisions when he sees a BC? Does a BC only contain the classes and interfaces that are part of the domain model (entities, value object, domain services, domain events and repositories) or does it extend to the classes (application services, controllers, etc.) in other layers?
To those questions, at least, Vernon offers precise and satisfying answers, with an accompanying diagram no less. He says that “There is another question that you may have wondered about. What’s inside a Bounded Context? Using this Ports and Adapters architecture diagram, you can see that a Bounded Context is composed of more than a domain model.
These layers are common in a Bounded Context: Input Adapters, such as user interface controllers, REST endpoints, and message listeners; Application Services that orchestrate use cases and manage transactions; the domain model that we’ve been focusing on; and Output Adapters such as persistence management and message senders.”
So there we have it. When talking about Bounded Contexts, Vernon, at least, is talking about the entire stack. A bit like a vertical slice or slices.
But surely Vernon didn’t have SPAs in mind when he said this? SPAs are different, they are more than just UI, some even have a bit of business and application logic. Plus, they are separate applications (it’s in the name after all), that run on a different machine, surely BCs do not cross process boundaries?
To this I answer, really? Why not? Where in the definitions of a Bounded Context or the Ubiquitous Language do we see any mention of anything that has to do, even remotely, with the concept of deployment location or process boundaries? Nowhere, that’s where.
To add some weight to the argument that it is absolutely not antithesis to DDD for a Bounded Context to span multiple deployment artifacts or processes, here’s what Vernon says in ‘Implementing DDD’: “A Bounded Context does not dictate the creation of a single kind of project artifact. It’s not an individual component, document, or diagram. So it’s not a JAR or DLL, but these can be used to deploy a Bounded Context as described later in the chapter.”
A Bounded Context does not dictate the creation of a single kind of project artifact. It’s not an individual component, document, or diagram.
So a BC does not equal a package, project or any other kind of deployment artifact. It can, but it doesn’t have to. For example, a DLL could contain more than one BC and one BC could span several DLLs.
Regarding the idea that a BC can also span several processes and physical or virtual machines Vernon gives the following explanation while talking about an example application that deals with Scrum-based software project management: “some consider a microservice to be much smaller than a DDD Bounded Context. Using that definition, a microservice models only one concept and manages one narrow type of data. An example of such a microservice is a Product and another is a BacklogItem. If this is the granularity that you consider a worthy microservice, understand that both the Product microservice and the BacklogItem microservice will still be in the same larger, logical Bounded Context. The two small microservice components have only different deployment units, which may also have an impact on how they interact. Linguistically they are still within the same Scrum-based contextual and semantic boundary.”
Yes he is talking about microservices, but the same principles apply when talking about a SPA. The fact that it runs in a different process and is deployed separately is not a valid reason not to consider the SPA as part of the same BC as the rest of the server-side BC. These factors are orthogonal to the concept of a BC.
Keep reading, in the next article we will illustrate our findings using Uncle Bob’s famous Clean Architecture and discuss WHY it is preferable to view the SPA as part of its server-side API’s Bounded Context.