The ubiquitous language (UL) is used in a whole bounded context, both the domain model and the application layer right? Ok. Then the name of the methods of an application service belongs to the UL. But the arguments of the method, as domain objects shouldn't be expose to the users, won't (cannot) be terms from the UL. If you used UL vocabulary to name method args, then you would be exposing domain objects outside the application.
How do you explain this contradiction about naming application services parameters?
Maybe the question seems a little bit philosophical, but so is DDD, it's a philosophy on software development, and it is based on the UL.
UPDATE
Someone asked for an example, not just philosophy. Well let's say our domain is about a shop selling products. One method of an application service could be:
addProductToShoppingCart ( Product product, ShoppingCart shoppingCart );
But Product and ShoppingCart are entities/value objects of the domain model, and we shouldn't expose it to clients.
So args should be DTOs or primitive types. But such types don't belong to the UL. Product and ShoppingCart do belong to the UL and should be the args of the method, but by doing it you break the rule of exposing domain to clients.
I think the application service layer should strive to reflect the UL as much as it can without leaking details from the domain model technical solution. In other words, you want the application service public API to be expressed using terms of the ubiquitous language, but you do not want the client code to be couple on the domain model layer.
"If you used UL vocabulary to name method args, then you would be exposing domain objects outside the application."
That's a misconception: method arguments should be named using UL terms where you can, but argument types shouldn't leverage types defined in the domain package. This is for technical reasons only as that segregation lets you change the domain model independently from the public application's API.
An example would be much better to discuss than just the "philosophy". But..
The contradiction is that most DDD designs do not in fact follow the UL rigorously enough. Look at almost any publicly available "DDD" design, for example Vaughn Vernon's Github repository.
The "Domain" (i.e. Value Objects and Entities) usually are modeled as data-only "objects", with little if any business logic. Right there the method names already left the UL and are purely in technical terrain (setters, getters usually).
Same with Services. Services are not part of the "Domain" at all. Try telling a business person that you've implemented a PasswordService, I guarantee a blank stare back. Services are also purely technical on the outside, with some business-related methods in them, that could actually belong to some Value Object or Entity.
So, while I agree with the "philosophy" part, the building blocks defined by Eric Evans as used today are far from an optimal implementation of that philosophy.
Take a look at my presentation about exactly this issue: https://speakerdeck.com/robertbraeutigam/object-oriented-domain-driven-design
Related
I am new to domain driven design and trying to learn and implement in my project. My project structure up till now similar to this.
Maintainance Folder Maintainance.Data(Class
Library) Maintainance.Domain(Class Library)
Maintainance.Domin.Tests(test project)
MovieBooking Folder MovieBooking.Data(Class
Library) MovieBooking.Domain(Class Library)
MovieBooking.Domain.Tests(test project)
SharedKernel Common things
Web Application MovieBooking MVC Web
Application(which have reference to MovieBooking Domain)
In Maintainance boundned context I am keeping all CRUD, GetAll type things for say Movie, Country, Category, Subcategory entities in Maintainance DBContext.
Now in MovieBooking data layer I will also need to use these entities (mostly to display name or dropdown fills in view, kind of subset needed - not all properties needed, only few like Id, name)
There are few ways I can access this entities in Movie booking Bounded Context
Via web services - Need to create web api for common entities like Movie,Country,Category,Subcategory and call web api in web project (to fill Dropdowns or get name from entities)
Via Reference Context (Seperate Dbcontext) - Need to configure Dbset and then map a database view (with only require fields) to Dbset
Example :
modelBuilder.Entity().ToTable(ViewName);
For (1) it can be long term implmentation solution for me
(2) I have to create view (with only few properties) for each require table and it will increase my number of views in my DB drastically as I have enterprise level application.
Is there any other way I can achieve this? Anything I am missing in DDD to look for ?
Option 2, while it will save you time, is actually a very bad idea from the DDD perspective as it allows for violations of the transactional boundary guarantees that each aggregate is meant to enforce\represent.
Option 1 seems a better option, although there are still quite a bit of wiggle room for interpretation based on your brief description of your proposed solution. If I understood correctly, it is generally recommended to follow the below:
Do not expose your aggregate state directly since this exposes internals and increases coupling. Simple create meaningful DTO's and use something like Automapper to map your Aggregates to DTO's easilly and with little effort before sending it over.
Have a duplicate of the DTO definition in your client. This will reduce coupling and allow for easier deployments.
I strongly recommend reading the DDD orange book although I have to say that I cannot recall specifically on which chapter this is discussed. You will also benefit a lot by reading about hexagonal architecture (and I would search for that term in the orange book to find more info about your question).
There is actually one alternative that I can think of: if you're publishing events from your BC's you can create a workflow to translate the domain events to "public" events and then in the other BC listen for the public events that you need to and store the data that you need somewhere inside there. The difficulty of this ranges from very easy to quite problematic depending on your infrastructure. Be aware that it is not a very good idea to re-use your domain events for transmitting data to other BC's since this closely couples the two BC's.
I hope this helps. Please do not hesitate to elaborate if I did not understood the question well enough.
I've got an issue with REST naming convention and backend endpoints placement. Let's assume that we have a system which has domain objects like: Product and Survey. Each product has some survey attached to it. Survey is a form which has questions which users fill when they rate the product. I would like to have operation like 'get survey for product with concrete id'. Possible endpoints in my opinion are:
/survey/product/{idProduct}
/product/{idProduct}/survey
More logical and natural is the second option. But now problem is with Controllers. We have ProductController and SurveyController. ProductController is mapped by root URI /product and SurveyController is mapped with /survey URI. So each method which starts with /product should be placed in ProductController, same with /survey.
If we choose second option then we should put concrete method which gets survey for product in the ProductController. But it can be confusing that ProductController serves Survey. It should rather operate on Product. More natural way for developer is that SurveyController returns Survey. It does not matter that ProductController uses SurveyService e.g. to get survey for concrete product. We can always use mapping in SurveyController where we put method which returns survey for concrete product and is mapped by URI /product/{id}/survey but this can be also confusing and time consuming for developer to find method declaration and we cannot annotate controller with some root URI path.
What is better? To use strict convention that URI which starts with e.g. /product is always assigned with ProductController and developer can quickly find method by URI, but method can serve different domain objects, not only Product or to use different URIs with some root path across different controllers?
Problem can look simple if we have few controllers and few domain objects. But what when we consider system with about 100 domain objects?
With 100 domain objects, one has usually some kind of structure for orientation. That means a dependency graph which somewhat dictates how to split the domain, even into separate projects, or separate runnable applications (microservices). So incidentally a larger model actually is "easier".
I would probably think about which resource is at the core of my model. For example if a Product may exists without a survey, but a Survey does not make sense without a Product, I would perhaps make the media-type of Survey link to a Product, rather than the other way. Which would probably look like:
/survey/123 <-- contains link to /product/456
In practice this means that you don't have to actually provide "subresources" like what you proposed.
REST has a uniform interface constraint which is the following in a very zipped opinion based format.
You have to use standards like HTTP, URI, MIME, etc...
You have to use hyperlinks.
You have to use RDF vocabs to annotate data and hyperlinks with semantics.
You do all of these to decouple the client from the implementation details of the service.
DDD with CQRS (or without it) is very similar as far as I understand.
By CQRS you define an interface to interact with the domain model. This interface consists of commands an queries classes.
By DDD you define domain events to decouple the domain model from the persistence details.
By DDD you have one ubiquitous language per bounded context which expresses the semantics.
You do all of these to completely decouple the domain model from the outside world.
Is it possible to map the REST uniform interface to the domain interface defined by commands and queries and domain events? (So the REST service code would be generated automatically.)
Is it possible to map the linked data semantics to the ubiquitous languages? (So you wouldn't need to define very similar terms, just find and reuse existing vocabs.)
Please add a very simple mapping example to your answer, why yes or why not!
I don't think this is possible. There is a term which I believe describes this problem, it is called ontology alignment.
In this case have have at least 3 ontologies:
the ubiquitous language (UL) of the domain model
the application specific vocab (ASO) of the REST service
the linked open data vocabs (LODO) which the application specific vocab uses
So we have at least 2 alignments:
the UL : ASO alignment
the ASO : LODO alignment
Our problem is related to the UL : ASO alignment, so let's talk about these ontologies.
The UL is object oriented, because we are talking about DDD and domain model. So most of the domain objects entities, value objects are real objects and not data structures. The non-object-oriented part of it are the DTOs like command+domainEvent, query+result and error on the interface of the domain model.
In contrast the ASO is strictly procedural, we manipulate the resources (data structures) using a set of standard methods (procedures) on them.
So from my aspect we are talking about 2 very different things and we got the following options:
make the ASO more object oriented -> RPC
make the UL less object oriented -> anaemic domain model
So from my point of view we can do the following things:
we can automatically map entities to resources and commands to operations by CRUD, for example the HydraBundle does this with active records (we can do just the same with DDD and without CQRS)
we can manually map commands to operations by a complex domain model
the operation POST transaction {...} can result a SendMoneyCommand{...}
the operation GET orders/123/total can result a OrderTotalQuery{...}
we cannot map entities to resources by a complex domain model, because we have to define new resources to describe a new service or a new entity method, for example
the operation POST transaction {...} can result account.sendMoney(anotherAccount, ...)
the operation GET orders/123/total can result in an SQL query on a read database without ever touching a single entity
I think it is not possible to do this kind of ontology alignment between DDD+CQRS and REST, but I am not an expert of this topic. What I think we can do is creating an application specific vocab with resource classes, properties and operations and map the operations to the commands/queries and the properties to the command/query properties.
You have posed some interesting questions here.
To start with I do not quite agree with
By DDD you define domain events to decouple the domain model from the
persistence details.
I think you might be confusing Event Sourcing ES with DDD, ES can be used with DDD but its very much optional in fact you should give it a lot of thought before choosing it as your persistence mechanism.
Now to the bulk of your question, of whether REST and DDD get along if yes how ?
My take on it, yes they do get along, however generally you do not want to expose your domain model via a REST interface, you want to build a abstraction over it and then expose that.
You can refer to this answer here, for a little more detail.
However i cannot recommend enough the Implementing Domain-Driven Design book, Chapter 14 Application deals with your concern to a fair degree.
I could not have explained it more thoroughly than the book and hence referring you there :)
When designing a RESTful API should resources which are dependent on others be modeled as sub-uris or should they simply reference each other?
E.g. presuming a door is always dependent on a house then
/house/73/door/1
or
/house/73
/door/1044
where house and door include references to each other?
Most RESTful APIs I have found are quite flat so I would value references to any which do have more complex relationship dependencies.
Regards
In UML terms, if the relationship is that of Aggregation, then you use a flat hierarchy with links between things, whereas if the relationship is that of Composition (i.e., the lifetime of a door is strictly bounded by the lifetime of a house) you use sub-resources.
I'm not suggesting drawing a UML diagram! But it does help to have in mind that distinction. (You could also model the Aggregation case by having sub-resources that are just redirect to the real ones; redirects are RESTful. OTOH, I don't actually like doing that; I prefer to make any relationships explicit and to keep the number of redirects down.)
Just remember that URIs are an implementation detail of the server. If you can model them as flat resources then do so. It will be easier for the server to handle them.
If the identifier for the door is not unique across all houses, then your server is going to need to know the house and therefore you need to include the house in the URI.
The relationships between the resources should be modeled by links within the returned representations. i.e. Your house representation should probably contain links to all of the door resources in that house. I would recommend trying to avoid using the URL structure as having some domain meaning.
Only use a hierarchy if it is needed to uniquely identify the resource.
What is the difference between
A simple fields-accesors-mutators class
A rich-modeled class
What constitutes rich modeling in business-domain classes?
"Rich" as used here implies "rich behavior" (as opposed to state).
There is technical behavior and domain behavior. Accessors and mutators are technical; they lack the "why" which defines business interest.
Domain objects represent the "why" and encapsulate the "how". Actually, all objects do that; domain objects do it specifically for business value.
Let's say you, as an employee domain object, have to request a day off of work. You have 2 options:
Tell your manager and he marks the schedule.
Ask your manager for the schedule and mark it.
Model 1 is rich. The "why" (vacation time) encapsulates the "how" (marking the schedule).
Model 2 relegates the manager to a simple property bag and leaks the scheduling abstraction.
When your business logic is encapsulated in your business objects. In other words, you have a Business Objects (Domain Model) layer, without the need for a separate Business Logic layer.