I’m looking at the great NDDDSample source from http://code.google.com/p/ndddsample to learn about DDD. Am confused with something
The CargoRepository has a Find() method which is called by BookingService.AssignCargoToRoute() and CargoTrackingController.Search() :
Cargo cargo = CargoRepository.Find(trackingId);
CargoRepository also has a Store() method called from BookingService.AssignCargoToRoute() :
Cargo cargo = cargoRepository.Find(trackingId);
if (cargo == null)
{
throw new ArgumentException("Can't assign itinerary to non-existing cargo " + trackingId);
}
cargo.AssignToRoute(itinerary);
cargoRepository.Store(cargo);
My confusion is that there seems to be nothing to stop the CargoTrackingController from calling CargoRepository.Store() which would bypass the business logic in the BookingService.AssignCargoToRoute()
Why is this allowed in DDD? Should the repository be split into two, one for read for the application/ui/domain/service and one for write for the domain/services?
In DDD, Services are not the holders of all business logic. They only represent verbs, actions of the domain that are cross-concern to several objects and thus wouldn’t fit into one of the entities or aggregate roots without breaking single responsibility principle and creating tight couplings that would muddle the entity.
In your example, Cargo.AssignToRoute(itinerary) and BookingService.AssignCargoToRoute() seem to be redundant. The existence of these 2 ways to bind a cargo to a route creates confusion. You could keep either of them, depending on whether you think it is the responsibility of the Cargo to assign itself a route, or that it overloads the entity with functionality that doesn’t belong in it.
Other than that, it is perfectly legitimate for a Controller to call a Repository method directly. Services are not the single point of access for Controllers.