I am developing a console application using domain driven design, i tried to keep the domain logic as much as possible into domain entities, but some how, some logic leaked into domain services, so now, do i need to test the domain services, if yes how to do it?
Yes, if they contain logic, they have to be tested.
If the service was properly decoupled, it should be possible to test it with unit tests and dependency injection.
First always make sure that your domain services are stateless.
The usual roles of domain services is stuff like validation and persistence. In those cases simply create mocks/stubs/dummies of infrastructure services that they use, pass them in, inside a unit test and assert certain behavior on those mocks. Business as usual. Sometimes the domain services need entities. Mock and pass those in as well. Assert as usual.
Inevitably someone will chime in with the venerable statement of: "but domain services aren't about persistence". If a domain service deals/uses some persistence mechanism (repository/gateway) to accomplish some responsibility, then it's perfectly reasonable 'english' to state 'its usual role is stuff like persistence'.
With that out of the way. DDD does not make decoupling goals. Good DDD is allowing ALL your business logic to happen in the domain. Making Domain Services stateless accomplishes that. Like VO It makes DS safe to pass around from outside layers. Keeping the API of DS consistent with your ubiquitous language insures they remain as a coherent unit of organization within your domain.
"But DS are not about persistence".. only if the ubiquitous language is not, and it often isn't, so the DS API shouldn't in those cases reflect a persistence mechanism. But it sure as hell can have internal methods that use a hell lot of persistence, and you will need to use mocks/stubs/dummies to get at those suckers in unit tests. Domain Services aren't some architectural scaffolding for keeping your layers separate. They are a unit of organization for higher level domain logic.
Domain Services are all about domain logic, so they should definitely be tested.
It's all the more simple to do since they have very few dependencies, and especially usually no coupling to infrastructure classes doing slow I/O stuff.
The domain layer is at the center of your application and isn't tightly coupled to any other layer, most calls will stay inside its boundaries. If Domain Services want to communicate to the outside world, they'll often use events. Therefore, you should need little to no mocks or stubs when testing them.
It depends on the framework you use. Using C# and depending on project complexity, I would take advantage on DI and factories (if any), or implement some functional tests (retrospectively) with SpecFlow and Moq, given interface contracts you should have written when implementing your domain services. The starting point would consist in installing SpecFlow, and then, you should create a dedicated test project...
http://www.specflow.org/getting-started/
Related
I’m designing a shipping application and trying to use Clean Architecture and DDD. Deep in the core of the domain layer we have many configurable business rules. For example, there are business rules for determining the optimal carrier of a shipment, determining shipping mode, determining the payment type, etc. Each business rule selects data from the database so I plan on using a BizRule Repository. The problem is that according to my understanding of DDD principles, Domain Entities (e.g. Shipment) should not call repositories(e.g. BizRuleRepository). The Use Case layer should be the one that calls repositories. If I take this approach then I will have to move many complex business rules to the Use Case layer and I'm not sure if that is the best approach. In this case, does it make sense to make an exception and have the domain entity call a repository? Thank you in advance.
Should a Domain Entity call a repository?
Generally speaking, no; it doesn't make sense for an entity (which is a domain concern) to be communicating directly with a repository (which is plumbing).
Evans, when organizing his book, assigned these ideas to different chapters
A Model Expressed in Software -- describes Entities
The Life Cycle of a Domain Object -- describes Repositories
It's a problem of language; Repositories normally have collection or persistence semantics, which are not (typically) part of the ubiquitous language of the domain.
That said, there is a loop hole; domain services can describe data retrieval using the ubiquitous language, and delegate that work to application or infrastructure services.
So (assuming for the moment that the business rules are a domain concept), you would have a domain entity that knows which business rule it needs, and a domain service that knows how to retrieve a business rule, and then the entity that knows how to use it.
If business rules are not a domain concept, then some of the work shifts from the entity into the domain service, but the core of the pattern remains the same -- the entity passes arguments to the service, the service returns a domain value the entity understands, the entity decides how to apply that value in its current processing.
We can solve any problem by introducing an extra level of indirection
It's a bit of a shell game; under the covers, we're still using the plumbing; but the domain model only sees the porcelain.
That extra layer of indirection can be really handy when you want to unit test the domain logic without dragging in the entire world of plumbing dependencies: you replace the domain service with a test double.
If it is just for readings it should be ok, maybe it can be cleaner having an interface/service (also with just 1 method) that express the desired query to your store, decoupling your entity from the repository.
In this way you can easily mock the query during tests, and in the future the lookup method can be easily improved in its own class (or you can also pass different strategies/implementation for the lookup).
Problem arises when you use repositories to write inside entities.
Onion Architecture Mockups
Above are two images that depict my understanding of Onion Architecture.
They are slightly different from the drawings found online, because they address an agenda that I cannot find an answer to.
Infrastructure, as far as I can tell, are things like persistence, logging, etc. I have written examples of them in italics. However, a lot of the time, infrastructure components, as well as UI, tend to need to communicate with one another. The UI might want to audit or log something, the persistence project may need to log something. Logging being one of the harder to fit items in onion architecture, my understanding is that a lot of people have different opinions on where you should and shouldn't log.
In my first drawing, I have put an Infrastructure Interfaces layer in the diagram to allow cross communication without any one component knowing the implementation of another component. This is something that I have seen in a few examples.
The second drawing is my preference, it uses a mediator to cross communicate between infrastructure, UI, and its basically a way to allow the core services to communicate with infrastructure indirectly (assume Service Interfaces is called Core Services on the right diagram). The logger would subscribe itself to certain events, as would the database etc.
The first diagram allows only pocos and interfaces in all layers except the outer layer (excluding the dependency resolver). The second allows domain and business logic in the core service layer and allow the infrastructure layers to do their jobs in isolation.
I justified the infrastructure components by ensuring that they had an output of some sort. Auditing and Logging would usually use a db of some sort, cache would usually store in memory and db should probably have been called persistence. However, there is a library called AutoMapper. I have seen it wrapped in some instances, so that its interface can go in the Core to be used in pretty much any infrastructure, but it seems like over abstraction to me. Automapper is kind of like the Events object in that all infrastructures use it to translate between itself and the domain, but I'm not sure if it fits in that layer since it is not a service.
Question: Which of the two is closest to the definition of onion architecture and where would you fit in a tool like auto mapper, and do you think trying to wrap something like that is over abstraction?
Thanks!
I've used Auto Mapper and the Onion Architecture. We configured AutoMapper in the MVC Global.asax file, that typically calls a Config Method in the AutoMapperConfig Class in the App Start directory.
Regarding your graphics, it appears one of them has a separate layer for the Mediator and Observer Patters. They're not necessarily needed but it entirely depends on your approach. Just as you can use Model-View-Controller Pattern in the Onion Architecture or Model-View-Presenter or Model-View-ViewModel. They're just coupling separate Patterns to incorporate some added benefit.
Here's where I first came across the Onion Architecture Jeffery Palermo. If you're wanting to a see a more pure graphical representation.
I am quite new to DDD and have come across a scenario that i'm not to sure how to handle.
I have an application that is used to track vehicles. This application is what will be implementing the "core" of the domain for the business i am working for. Not only is this application going to be used, there will be other utility programs that must be created and used in order to help this "core/main" application function.
for example:
there is an windows service needed that will perform configured queries on a database and return results to an external database that my routing application will use. This windows service has the concept of a QuerySettings class that can be created and is then executed by this application.
Question1:
What do you call utility applications like the above described in DDD? ( it definitely isn't the main core of the domain but it's needed in order for the core application to work )
QUestion2:
Is QuerySettings a domain model? if not what is it and where should it be placed within following the onion architecture?
For question1: You may have a look at Bounded context, I think Bounded context contains a group of Domain models that represent concepts in a subdomain(or a core domain). You may need to map or share domain models in different bounded contexts to handle your business, this depends on your bounded context strategy, share-kernal, anti-corruption-layer(to name a few).
For question2: I have little information of how QuerySettings works but in general it is a domain model but in a generic subdomain, not in your vehicle tracking core domain. In core domain's view, it maybe an infrastructure concept.
Probably similar questions have been asked many times but I think that every response helps to make the understanding of DDD better and better. I would like to describe how I perceive certain aspects of DDD. I have some basic uncertainties around it and would appreciate if someone could give a solid and practical anwser. Please note, these questions assume a 'classic' approach to DDD. This means using ORM's etc. Approaches like CQRS and event sourcing are not considered here.
Aggregates and entities are the primary objects that implement domain logic. They have state and identity. In this context, I perceive domain logic as the set of all commands that mutate that state. Does that make sense? Why is domain logic related exclusively to state? Is it legal to model domain objects that have no identitiy or no state? Why can't a domain object be implemented as a transaction script? Example: Consider an object that recommends you a partner for a dating site. That object has no real state, but it does quite a lot of domain logic? Putting that into the service layer implies that the domain model cannot cover all logic.
Access to other domain objects. Can aggregates have access to a repository? Example: When a (stateful) domain object needs to have access to all 'users' of the system to perform its work, it would need access them via the repository. As a consequence, an ORM would need to inject the repository when loading the object (which might be technically more challenging). If objects can't have access to repositories, where would you put the domain logic for this example? In the service layer? Isn't the service layer supposed to have no logic?
Aggregates and entities should not talk to the outside world, they are only concerned about their bounded context. We should not inject external dependencies (like IPaymentGateway or IEmailService) into a domain object, this would cause the domain to handle exceptions that come from outside. Solution: an event based approach. How do you send events then? You still need to inject the correct 'listeners' every time you instantiate a domain object. ORM's are about restoring 'data' but are not primarly intended to inject dependencies. Do we need an DI-ORM mix?
Domain objects and DTO's. When you query an aggregate root for its state does it return a projection of its state (DTO) or the domain objects themselves? In most models that I see, clients have full access to the domain data model, introducing a deep coupling to the actual structure of the domain. I perceive the 'object graph' behind an aggregate to be its own buisness. That's encapsulation, right? So for me an aggregate root should return only DTO's. DTO's are often defined in the service layer but my approach is to model it in the domain itself. The service layer might still add another level of abstraction, but that's a different choice. Is that a good advice?
Repositories handle all CRUD operations at the aggregate root level. What about other queries? Queries return DTO's and not domain objects. For that to work, the repsitory must be aware of the data structure of the domain which introduces a coupling. My advice is similar to before: Use events to populate views. Thus, the internal structure is not made public, only the events carry the necessary data to build up the view.
Unit of work. A controller at the system boundary will instantiate commands and pass them to a service layer which in turn loads the appropriate aggregates and forwards the commands. The controller might use multiple commands and pass them to multiple services. This is all controlled by the unit of work pattern. This means, repositories, entities, services - all participate in the same transaction. Do you agree?
Buisness logic is not domain logic. From a buisness perspective the realization of a use case might involve many steps: Registering a customer, sending an email, create a storage account, etc. This overall process can impossibly fit in a domain aggregate root. The domain object would need to have access to all kind of infrastructure. Solution: Workflows or sagas (or transaction script). Is that a good advice?
Thank you
The first best practice I can suggest is to read the Evans' book. Twice.
Too many "DDD projects" fail because developers pretend that DDD is simply OOP done right.
Then, you should really understand that DDD is for applications that have to handle very complex business rules correctly. In a nutshell: if you don't need to pay a domain expert to understand the business, you don't need DDD. The core concept of DDD, indeed, is the ubiquitous language that both the coders, the experts and the users share to understand each other.
Furthermore, you should read and understand what aggregates are (consistency boundaries) by reading Effective Aggregate Design by Vernon.
Finally, you might find useful the modeling patterns documented here.
Despite my comment above, I took a stab at your points. (note: I'm not Eric Evans or Jimmy Nilsson so take my "advice" with a grain of salt).
Your example "Consider an object that recommends you a partner for a dating site.", belongs in a Domain service (not an infrastructure service). See this article here - http://lostechies.com/jimmybogard/2008/08/21/services-in-domain-driven-design/
Aggregates do not access repositories directly, but they can create a unit of work which combines operations from multiple domain objects into one.
Not sure on this one. This should really be a question by itself.
That's debatable, in theory, the domain entities would not be directly available outside the aggregate root, but that is not always practical. I consider this decision on a case-by-case basis.
I not sure what you mean exactly by "queries". If modeling all possible "reading" scenarios in your domain does not seem practical or provide sufficient performance, it suggests a CQRS solution is probably best.
Yes, I agree. UOW is a tool in your toolbox that you can use in various layers.
This statement is fundamentally wrong "Business logic is not domain logic". The domain IS the representation business logic, thus one reason for using ubiquitous language.
I'm trying to figure out the best way to build an easily maintainable and testable architecture. Having gone through several projects, I've seen some pretty bad architectures and I want to avoid making future mistakes on my own projects.
Let's say I'm building a fairly complex three layer application and I want to use DDD. My question is, where should I place my business logic? Some people say it should be placed in services (service layer) and that does make sense. Having a number of services which adhere to Single Responsibility Principle makes sense.
However, some people said that this is an anti pattern and that business logic shouldn't be implemented in the service layer. Why is this?
Let's say we have IAuthenticationService which has a method with bool UsernameAvailable(string username) signature. The method would implement all required logic to check whether the username is available or not.
What is the problem here according to the "this is an antipattern" crowd?
If you put all your business logic in an (implicitly stateless) service layer you're writing procedural code. By decoupling behavior from data, you're giving up on writing object-oriented code.
That's not always bad: it's simple, and if you have simple business logic there's no reason to invest in a full-fledged object-oriented domain model.
The more complex the business logic (and the larger the domain), the faster procedural code turns into spaghetti code: procedures start calling each other with different pre- and post-conditions (in incompatible order) and they begin to require ever-growing state objects.
Martin Fowler's article on Anemic Domain Models is probably the best starting point for understanding why (and under what conditions) people object to putting business logic in a service layer.
A service layer in itself is not an anti-pattern, it is a very reasonable place to put certain elements of your business logic. However, you do need to apply discretion to the design of the service layer, ensuring that you aren't stealing business logic from your domain model and the objects that comprise it.
By doing that you can end up with a true anti-pattern, an anaemic domain model.
This is discussed in-depth by Martin Fowler here.
Your example of an IAuthenticationService isn't perhaps the best for discussing the problem - much of the logic around authentication can be seen as living in a service and not really associated with domain objects. A better example might be if you had some sort of IUserValidationService to validate a user, or even worse a service that does something like process orders - the validation service is stripping logic out of the user object and the order processing service is taking logic away from your order objects, and possibly also from objects representing customers, delivery notices etc...
You have to have 4 layers with DDD: Presentation, Application, Domain, and Infrastructure.
The Presentation layer presents information to the user, interprets user commands.
All dependent on use-cases logic (application entities, application workflow components, e.g. DTOs, Application services) goes to the Application layer (Application logic). This layer doesn’t contain any business logic, does not hold the state of business objects, can keep the state of an application task’s progress.
All invariant to use-cases logic (business entities, business workflow components, e.g. Domain model, Domain services) goes to the Domain layer (Domain logic). This layer is responsible for concepts of the business domain and business rules.
The Infrastructure layer may have IoC, Cache, Repositories, ORM, Cryptography, Logging, Search engine, etc.