Looking at the ddd sample application, I cannot figure out why the Cargo Cargo.java object needs to have a separate reference to a RouteSpecification.
Wouldn't it be simpler to have origin, destination and arrivalDeadline part of cargo class and skip this RouteSpecification class altogether and expose methods such as updateDestination and satisfiedByItinerary
RouteSpecification is used to validate if an itinerary can satisfy the cargo route or not etc. But I don't see any reason why such a task cannot be handled by the Cargo class itself, What's the point of this separation?
public class Cargo implements Entity<Cargo> {
...
private Location origin;
private Location destination;
private Date arrivalDeadline;
...
Taking a documentation walk, there's a useful pointer in the version 1 introduction.
One of the most requested aids to coming up to speed on DDD has been a running example application. Starting from a simple set of functions and a model based on the cargo example used in Eric Evans' book
Given this, we can reasonably assume that the design had similar motivations to those in chapter 7 of the blue book.
Delivery Specification defines a delivery goal, which at a minimum would include a destination and an arrival data, but it can be more complex. This class follows the specification pattern.
This responsibility could have been taken on by the Cargo object, but the abstraction of Delivery Specification gives at least three advantages.
Without Delivery Specification, the cargo object would be responsible for the detailed meaning of all those attributes and associations for specifying the delivery goal. This would clutter up Cardo and make it harder to change.
This abstraction makes it easy and safe to suppress detail when explaining the model as a whole. For example, there could be other criteria encapsulated in the Delivery Specification, but a diagram at this level of detail would not have to expose it. The diagram is telling the reader that there is a specification of delivery, and the details of that are not important to think about (and, in fact, could be easily changed later).
This model is more expressive. Adding Delivery Specification says explicitly that the exact means of delivery of the Cargo is undetermined, but that it must accomplish the goal set out in the Delivery Specification.
But then why isn't origin a part of RouteSpecification?
I haven't gone digging through the whole project history, but my guess is that Cargo.origin and RouteSpecification.origin aren't actually interchangeable. (origin is part of the RouteSpecification, but the RouteSpecification can change over time).
From the version one javadoc
A cargo can be re-routed during transport, on demand of the customer, in which case a new route is specified for the cargo and a new route is requested.
It may also happen that a cargo is accidentally misrouted, which should notify the proper personnel and also trigger a re-routing procedure.
The version one code also indicates that cargo can be misdirected (which is not the same as misrouted).
If you look carefully at the different scenarios, you'll see that they handle misdirection in different ways; the newer version does so by replacing the route specification and then searching for a matching itinerary.
If you considered the consequences of completely refactoring out the RouteSpecification class from the solution, you would find that origin, destination and arrivalDeadline seem to get passed around together much of the time. This is a strong sign that the values are closely related. "Cohesion" is a principle of object oriented programming in which closely related concepts are located close together in code, so to follow this principle, you can bring these three concepts together in a single class.
Many programmers would agree that it is simpler to pass around a single RouteSpecification object everywhere these values are used rather than origin, destination and arrivalDeadline separately.
Related
I have read that with TDD we should approach the entity (function, class etc.) under test from the perspective of the user/caller of the entity. The gist being focusing on the public "interface". This in turn would drive the design and help reason about the design earlier.
But when we need to introduce mocks and stubs into our tests, isn't that an implementation detail?
Why would/should the "user" care about the other entities that are supposed to be there?
E.g.
How to start writing a test for the PlaceOrder service which should check with the credit card service if the user has enough money? Putting a mock for the credit card service whilst writing a test from the perspective of the PlaceOrder client looks out of place now - because it is an implementation detail; our PlaceOrder may call the credit card for each user or it can simply have a cache with scores provided at the creation time.
It's not clear-cut. As a catch-phrase says: Tests are specifications.
When you use Test Doubles you are, indeed, specifying how your System Under Test (SUT) ought to interact with its dependencies.
I agree that this is usually an implementation detail, but there will typically be a few dependencies of a more architectural character.
A common example is an email gateway. If your SUT should send email, that's an observable side effect that the user (or some other stakeholder) cares about.
While you can (and perhaps should?) also run full systems tests that verify that certain conditions produce real emails that land in certain real mailboxes, such test cases are difficult to automate.
Inserting a Test Double that can take the place of an email gateway and verify that the correct message was delivered to the gateway is not only an implementation detail, but an important part of the overall system. In such cases, using a Test Double makes sense.
Yes, Test Doubles specify behaviour, but sometimes, that's exactly what you want.
How much you should rely on this kind of design is an architectural choice. In addition to sending emails, you might choose to explicitly specify that a certain SUT ought to place a message on a durable queue.
You can create entire systems based on asynchronous messaging, which could imply that it'd be architecturally sound to let tests rely on Test Doubles.
In short, I find it a useful heuristic to use Test Doubles for architectural components, and rely mostly on testing pure functions for everything else.
For something like an order service, I wouldn't let the order service contact the payment gateway. Rather, I'd implement the order service operations as pure functions, and either pass in a payment token as function arguments, or let the output of functions trigger a payment action.
The book Domain Modeling Made Functional contains lots of good information about this kind of architecture.
On the other hand, the book Growing Object-Oriented Software, Guided by Tests contains many good examples of how to use Test Doubles to specify desired behaviour.
Perhaps you'll also find my article From interaction-based to state-based testing useful.
In summary: Tests are specifications. Test Doubles are specifications. Use them to specify the observable behaviour of the system. Try to avoid using them to specify implementation details.
But when we need to introduce mocks and stubs into our tests, isn't that an implementation detail?
Yes, in effect. A bit more precisely, it is additional coupling between your test and the details of your test subject's implementation.
There are two ideas in tension here. On the one hand, we want that our tests are as representative as possible of how our system will actually work; and on the other hand we each of our tests to be an controlled experiment of our implementation, without coupling to shared mutable state.
In some cases, we can disguise some of the coupling by using inert substitutes for our dependency as the default case, so that our implementation classes are isolated unless we specifically opt into a shared configuration.
So for PlaceOrder, it might look like using a default CreditCardService that always answers "yes, the customer has enough money". Of course, that design only allows you to test the "yes" branch in your code - to test a "no" branch, you are necessarily going to need to know how to configure PlaceOrder with a CreditCardService that declines credit.
For more on this idea, see the doctrine of useful objects.
More generally, in TDD we normally take complicated designs that are hard to test and refactor them into a design where something really simple but hard to test collaborates with something that is complicated but easy to test.
But for that to work at all, the components need to be able to talk to each other, and if you are going to simulate that communication in a test you are necessarily going to be coupled to the "implementation detail" that is the protocol between them.
For the case where that protocol is stable, having tests coupled to those details isn't, of itself, a problem in practice. There's coupling, sure, and cost of change, but if the probability of change is negligible then the expected cost of that coupling is effectively nothing.
So the trick is identifying when our tests would require coupling to an unstable implementation protocol, and figuring out how to best mitigate the risk of change.
I have found some old questions, but I doesn't really answer or clear my doubts.
Repository Pattern + Unit Of Work: it is from 2012, and they tell that really to the repository pattern is not needed nowdays. Really I would like to know if repository pattern implies always unit of work and another aspects. Anyway, it would be to know another opiniones more recents if really repository pattern is useful or not today.
DDD - the rule that Entities can't access Repositories directly: this is a good post, but it desn't talk about unit of work.
Also I have asked another questions that are not answered in this posts. So I open a new one.
I am reading some examples how to implement repository pattern, thinking in a DDD architecture.
The pattern is called repository pattern, but many of the examples that I have seen implement the both and it seems that it is a unit, it has no sense or it is not good to implement only repository pattern, that it is needed the unit of work too.
Here are some examples, that they have small difference but it is the same one to do:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
https://www.youtube.com/watch?v=rtXpYpZdOzM
In this examples, they use the repositories through the unit of work, so they don't use directly the repository to say in some way (really the repositories are uses because they are properties in the unit of work).
So my questions are various:
1.- When it is talked about pattern repository, really it means repository and unit of work or there is in some cases where it could be implemented only the repository?
2.- If it is implemented the unit of work, is it recommended to access the repositories only throuth it? Because in this examples, it is posible, in the consumer, instantiate the repositories and the unit of work. Wouldn't it be better to avoid the consumer to can use repositories and only create the unit of work?
3.- In the second link that I put, in the video, it is said that the repositories shouldn't have methods like update, that this is not the responsability of the repository, but in most cases of another examples, I always see the update method. So is it really a bad practice to have an update method in the repository? In this case, if I don't have this method and call the complete() method of the unit of work, it will work because behind the interface, the implementation uses an OR/M, but if another implementation doesn't use it, I have to notify in some way that the entity was changed. I guess an update method is the most easy to do it.
Well, in summary, I would like to know if really means to have the unit of work too or not.
Thanks.
When it is talked about pattern repository, really it means repository and unit of work or there is in some cases where it could be implemented only the repository?
From Evans, 2004
Leave transaction control to the client. Although the REPOSITORY will insert into and delete from the database, it will ordinarily not commit anything.... the client presumably has the context to correctly initiate units of work.
So Evans considers them to be separable ideas.
Implicit in Evans's writing is the idea that the information of the domain model is stored in a single relational database; which means that transactions spanning multiple aggregates are fine, because the database ensures that information is persisted atomically. But when you start looking at alternatives to a monolithic SQL database, robust persistence is... tricky.
A lot of modern writing eases some of this by adding a constraint that aggregate boundaries and transaction boundaries are aligned. In this kind of a design, you might reasonably factor the transaction management into the repository facade.
As a reader, we have to be really careful that we understand the implicit constraints of the author's context.
it is said that the repositories shouldn't have methods like update, that this is not the responsibility of the repository, but in most cases of another examples, I always see the update method
Evans again:
The ideal is to hide all of the inner workings from the client (although not the developer of the client) so that the client code will be the same whether the data is stored in an object database, stored in a relational database, or simply held in memory.
There are a couple problems with this ideal
Collections simply held in memory don't have distributed failure modes like the other candidate implementations
When is the change I made visible to others is an important design consideration
So you end up with people choosing different repository interfaces depending on how/if they decide to address these issues.
The important idea to recognize here is that REPOSITORY is a pattern; something we expect to have different expressions depending on the system of forces at play.
Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice. -- Christopher Alexander, A Pattern Language (emphasis added)
I'm trying to follow some of the more current design principles including SOLID and Domain Driven Design. My question is around how people handle "Initializing" Domain Objects.
Here's a simple example:
Based on SOLID, I should not depend on concretions, so I create an interface and a class. Since I'm taking advantage of Domain Driven Design, I create an object with relevant methods. (i.e. not anemic).
Interface IBookstoreBook
{
string Isbn {get; set;}
int Inventory {get; set;}
void AddToInventory(int numBooks);
void RemoveFromInventory(int numBooks);
}
public class BookstoreBook : IBookstoreBook
{
public string Isbn {get; set;}
public int Inventory {get; private set;}
public void AddToInventory(int numBooks);
public void RemoveFromInventory(int numBooks);
}
To help with testing and be more loosely coupled, I also use an IoC container to create this book. So when the book is created it is always created empty. But, if a book doesn't have an ISBN and Inventory it is invalid.
BookstoreBook(string bookISBN, int bookInventory) {..} // Does not exist
I could have 4 or 5 different classes that use a BookstoreBook. For one,
public class Bookstore : IBookstore
{
...
public bool NeedToIncreaseInventory(BookstoreBook book) { ...}
...
}
How does any method know is getting a valid book? My solutions below seem to violate the "Tell Don't Ask" principle.
a) Should each method that uses a Bookstore book test for validity? (i.e. should NeedToIncreaseInventory test for a books validity? I'm not sure it should have to know what makes a BookstoreBook valid.)
b) Should I have a "CreateBook" on the IBookstoreBook object and just "assume" that clients know they have to call this anytime they want to initialize a BookstoreBook? That way, NeedToIncreaseInventory would just trust that "CreateBook" was already called on BookstoreBook.
I'm interested in what the recommended appreach is here.
First off, I think your BookstoreBook doesn't have any really relevant methods, which means it doesn't have any relevant behavior, no business rules at all. And since it doesn't contain any business rules it actually is anemic. It just has a bunch of Getters and Setters. I would argue that having a method like AddToInventory that ends up just adding +1 to a property is no meaningful behavior.
Also, why would your BookstoreBook know how many of its type are in your Bookstore? I feel like this is probably something the Bookstore itself should keep track of.
As for point a): no, if you're creating books from user input you should check the provided data before you even create a new book. That prevents you from ever having invalid books in your system.
As for the creation of the object, the question is will you ever have more than one book type? If the answer is no you can drop the interface and just instantiate a book in a class that is responsible for creating new books from user input for example. If you need more book types an abstract factory may be useful.
First of all, a great way to make sure that entity state only can be set by behavior (methods) so to make all property setters private. It also allows you to make sure that all related properties are set when the state changes.
But, if a book doesn't have an ISBN and Inventory it is invalid.
There you have two business rules. Let's start with ISBN. If a book is not valid without it it HAVE to be specified in the constructor. Otherwise it's fully possible to create a book which is invalid. An ISBN also have a specified format (at least the length). So that format have to be validated too.
Regarding the inventory I believe that it's not true. You might have books that are sold out or books that can be booked before their release. Right? So a book CAN exist without an inventory, it's just not likely.
If you look at the relation between inventory and books from the domain perspective they are two separate entities with different responsibilities.
A book is representing something that the user can read about and use that information to decide whether it should be rented or purchased.
An inventory is used to make sure that your application can fulfill your customers request. Typically it can be done by a delivery directly (decrease the inventory) or by a backorder (order more copies from your supplier and then deliver the book).
Thus the inventory part of the application do not really need to know everything there is to know about the book. Thus I would recommend that the inventory only knows about the book identity (that's typically how root aggregates can reference each other according to Martin Fowler's book).
An inversion of control container is typically used to to manage services (in DDD the application services and the domain services). It's job is not to act as a factory for domain entities. It will only complicate things without any benefit.
To help with testing and be more loosely coupled, I also use an IoC container to create this book.
Why is your IoC container creating books? That's a bit strange. Your domain model should by container agnostic (wiring together the interfaces and the implementation is the concern of your composition root).
How does any method know is getting a valid book?
The domain model knows it is getting a valid book, because it says so right there in the interface.
The data model knows it is producing a valid book, because the constructor/factory method accepted its arguments without throwing an exception.
Should each method that uses a Bookstore book test for validity?
No, once you have a Book, it is going to stay valid (there shouldn't be any verbs defined in your domain model that would create an invalid data model).
Should I have a "CreateBook" on the IBookstoreBook object and just "assume" that clients know they have to call this anytime they want to initialize a BookstoreBook? That way, NeedToIncreaseInventory would just trust that "CreateBook" was already called on BookstoreBook.
It's normal to have a factory for creating objects. See Evans, chapter 6.
books can be created from a database and many other places. I'm assuming others have had to solve this issue if they are using DDD and I am wondering about their approach. Should we all be using factories - as you suggest that take the needed data as input?
There are really only two sources for data -- your own book of record (in which case, you load the data via a repository), and everywhere else (where you need to make sure that the data conforms to the assumptions of your model.
Based on SOLID, I should not depend on concretions
If you're referring to the Dependency Inversion principle, it does not exactly say that.
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
No domain entity is of a higher level than another and normally no object in the Domain layer is a "detail", so DIP usually doesn't apply to domain entities.
I also use an IoC container to create this book
Considering that BookstoreBook has no dependency, I'm not sure why you would do that.
How does any method know is getting a valid book?
By assuming that the book is Always Valid, always consistent. This usually requires having a single Book constructor that checks all relevant rules at creation time, and state-changing methods that enforce invariants about the Book.
a) ...
b) ...
You're mixing up two concerns here - making sure that Book is in a consistent state wherever it is used, and initializing a Book. I'm not sure what your question is really about in the end, but if you apply the "always valid" approach and forget about Book being an interface/higher level abstraction, you should be good to go.
I would like to have one or more libraries of reusable classes that are basically value objects, such as Address, PhoneNumber, EmailAdress, containing mostly properties and a few supporting methods. How can my Domain layer use these without breaking the rule that the Domain Layer should not contain external references, and without defining them as interfaces/abstract classes in the Domain Layer?
... without breaking the rule that the Domain Layer should not contain external references
I think your definition of 'external references' requires some reevaluation. It is hard to imagine a domain layer that does not reference anything. In C# and Java you will reference at least basic numeric types, dates and strings. I also don't see any harm in referencing external libraries like Noda/Joda time. On the other hand, you of course would not want to reference any heavy technical libraries like persistence, communication, UI etc.
So I would say that you can build your own reusable library referenced from domain but it requires a very careful consideration, and is often not worth the coupling that it will create. I would use a following criteria for every type:
Should be context-independent. EmailAddress for example is relatively independent of the context it is used from. Address on the other hand may have a different meaning depending on a Bounded context.
Should be stable (does not change often).
Should not hide any out-of-process communication (db, network etc)
Should not have any dependencies of its own (other than standard Java/C#)
I think that what you're referring to is a shared kernel.
Shared Kernel – This is where two teams share some subset of the
domain model. This shouldn’t be changed without the other team being
consulted.
While this looks great at first, since we are drilled not to repeat ourselves, be aware of the pitfalls:
The concepts should have the same meaning in every context. Some of these concepts hold subtle nuances depending on the context. Ask your domain expert.
Changes are more expensive; it might be cheaper to duplicate these few classes so that you can change them on your own than to have to consult multiple teams when something changes.
Stability cuts both ways. If you pull an entity out into each domain, then any changes have to be executed across multiple projects. If you don't, then changes have to be coordinated across multiple domains. The logistics of the former are easier than the latter, but the work involved in the latter can be greater. Either way, you have to test the changes on each platform.
And unless the entity is mature with a relatively well-defined semantics, my experience is that almost everything changes. So stability is nice, but might be a bit of a red herring.
That being said, I like (and +1) #Dmitry.
I am 80% sure I should not be asking this question because it might come across as negative and I mean no disrespect to anyone, especially the author of this book. I have seen several posts recommending this book and its companion project. I have not read the book, but I have spent a few hours today studying the project. And while it does look very complete, I am having a very hard time with how much the details of various things are scattered around. I am struggling in my own designs with how much I have to change if an entity changes, and this project does not make me very comfortable as a solution.
For example, there is a Employee object that inherits from a Person. Person has a constructor with first-name, last-name, etc. and therefore, so does Employee. Private to Employee are members for first name, last name, plus public properties for the same.
There is an EmployeeFactory that knows about both Employee and Person properties, as well as the SQL column names (to pull values from a reader).
There is an EmployeeRepository with unimplemented PersistNewItem and PersistUpdatedItem methods that I suspect, if implemented, would build SQL for INSERT and UPDATE statements like I see in CompanyRepository. These write the properties to strings to build the SQL.
There is a 'Data Contract' PersonContract with the same private members and public properties as Person, and an EmployeeContract that inherits from PersonContract like Employee does Person, with public properties mirroring the entities.
There is a static 'Converter' class with static methods that map entities to Contracts, including
EmployeeContract ToEmployeeContract(Employee employee)
which copies the fields from one to the other, including Person fields. There may be a companion method that goes the other way - not sure.
I think there are unit tests too.
In all I count 5-10 classes, methods, and constructors with detailed knowledge about entity properties. Perhaps they're auto-generated - not sure. If I needed to add a 'Salutation' or other property to Person, I would have to adjust all of these classes/methods? I'm sure I'd forget something.
Again, I mean no disrespect and this seems to be a very thorough, detailed example for the book. Is this how DDD is done?
Domain Driven Design is really simple. It says: make your Model classes mirror the real world. So if you have Employees, have an Employee class and make sure it contains the properties that give it its 'Employee-ness'.
The question you are asking is NOT about DDD, but rather about class architecture in general. I think you're correct to question some of the decisions about the classes you're looking at, but it's not related to DDD specifically. It's more related to OOP programming design patterns in general.
DDD s new enough (at least in some senses) that it may be a little early to say exactly "how it's done." The idea's been around for a fair long while, though, although we didn't make up a cool name for it.
In any case, the short answer (IMAO) is "yes, but...." The idea of doing a domain-driven design is to model the domain very explicitly. What you're looking at is a domain model, which is to say an object-oriented model that describes the problem domain in the problem domain's language. The idea is that a domain model, since it models the "real world", is relatively insensitive to change, and also tends to localize change. So, if for example your idea of what an Employee is changes, perhaps by adding a mailing address as well as a physical address, then those changes would be relatively localized.
Once you have that model, though, you have what I maintain are architectural decisions still to be made. For example, you have the unimplemented persistence layer, which might indeed be simply construction of SQL. It could also be a Hibernate layer, or use Python pickling, or even be something wild like a Google AppEngine distributed table structure.
The thing is, those decisions are made separately, and with other rationales, than the domain modeling decisions.
Something I've experimented with to some good result is doing the domain model in Python and then building a simulator with it instead of implementing the final system. That makes for something the customer can experiment with, and also potentially allows you to make quantitative estimates about the things the final implementation must determine.
to me, what makes DDD different from "mere" model-driven design is the notion of "aggregate roots", i.e. an application is only allowed to hold references to aggregate roots, and in general you will only have a repository for the aggregate root class, not the classes that the aggregate root uses
this cleans up the code considerably; the alternative is repositories for every model class, which is "merely" a layered design, not DDD