Exposing IUnitOfWork interface in Domain Layer violates Persistence Ignorance rule? - domain-driven-design

1) In most cases each Aggregate Root should define its own transactional boundary, in which case we don't need to expose IUnitOfWork interface in Domain Layer.
a) I assume in this situation a good option would be for a repository ( used by aggregate to enforce invariants applied within it ) to contain its very own instance of UoW ( if using EF, then this UoW instance could simply be of type DbContext )?
2)
a) But if for whatever reason transaction spans several aggregates ( thus more than one aggregate needs to be changed at one time ), then won't Domain Layer also need to contain IUnitOfWork interface?
b) Won't exposing IUnitOfWork interface in Domain Layer violate persistence ignorance rule?
c) If yes to b), doesn't then exposing IUnitOfWork defeat the purpose of having repositories?
Replying to Alexey Raga:
1)
I would advice against exposing repositories to aggregates. Repositories are there to give you aggregates, that's it.
a) Though I assume that majority of ddd architects don't have a problem with exposing repos to aggregates ( I'm only asking because I read several articles on repos and DDD and the impression I got is that authors ain't against exposing repos to aggregates - but now I'm not so sure anymore )?
b) So you're also against exposing repositories to domain services?
c) Judging by your answer I'm guessing that you consider exposing IUnitOfWork as a violation of PI?
2)Note that although my command handler (app service in a way)...
Do you normally implement command handlers as app services?
3)
public void Handle(ApproveOrderCommand command)
{
var order = Repository.Get(command.OrderId);
property.Approve(command.Comment, ServiceRequiredForOrderApproval);
Repository.Save(order);
}
Is property.Approve(...) a typo and you actually meant order.Approve(...)?
Thanx in advance

I would advice against exposing repositories to aggregates. Repositories are there to give you aggregates, that's it.
Look at it at that way: your domain is a "bubble" which only understands its own stuff. Meaning, it only understand its own value objects, domain services interfaces it declares, etc. I wouldn't include repositories in this set.
When your domain (an aggregate) needs something it should explicitly expose the dependency of what it needs, not just ask for some repository.
Services is what brings things together.
For example, my command handler could look like:
public class ApproveOrderCommandHandler : IHandle<ApproveOrderCommand>
{
//this might be set by a DI container, or passed to a constructor
public IOrderRepository Repository { get; set; }
public ISomeFancyDomainService ServiceRequiredForOrderApproval { get; set; }
public void Handle(ApproveOrderCommand command)
{
var order = Repository.Get(command.OrderId);
order.Approve(command.Comment, ServiceRequiredForOrderApproval);
Repository.Save(order);
}
}
Note that although my command handler (app service in a way) deals with repositories, my domain (order aggregate) is persistence ignorant. It doesn't know anything about repositories of UnitOfWorks.
When I do need to spin up a UnitOfWork I can compose it using a Chain Of Responsibility pattern:
public class WithUnitOfWorkHandler<T> : IHandler<T> {
private readonly IHandler<T> _innerHandler;
public WithUnitOfWorkHandler(IHandler<T> innerHandler) {
_innerHandler = innerHandler;
}
public void Handle(T command) {
using(var ouw = new UnitOfWork()) {
_innerHandler.Handle(command);
uow.Commit();
}
}
}
Now I can "chain" any of my command handlers by "decorating" it with WithUnitOfWorkHandler.
And some of the handlers may even touch more than one repository or aggregate. Still, aggregates don't know anything about persistence, unit of works, transactions, etc.

Persistence ignorance means: The business layer has no knowledge and no dependency whatsoever on the concrete persistence system that is used under the hood (e.g. MS SQL Server, Oracle, XML files, whatever).
Thus, exposing an interface that abstracts away the concrete type of the datastore can never violate this principle.

Persistence Ignorance is a guideline, it is almost impossible to reach with actual languages and technologies. The Repository pattern and the Unit Of Work abstract the persistence related stuff and "hide" the Data Access Layer to the business code, but it is more a trick (a clean one) than an absolute solution. The presence or the need for something (an interface, a base class, an attribute...) that says "heyyy, there is something in here we want to hide..." violates PI. But for the moment, there is no better solution.

Related

DDD - domain service to store entity in not primary infrastructure

I am thinking about scenario in a way of Domain Driven design, where I have entity, lets say Cv (Curriculum vitae), which state is saved in database via repository.
Now I need to store part of the Cv in another system (ElasticSearch), which is crucial for whole app functionality like searching.
How to handle it? I am thinking about these 2 options:
1. Use domain service IndexCvGatewayServiceInterface (as interfaces implemented in infrastructure)
class CvEntity
{
public function approve(CvRepositoryInterface $cvRepository, IndexCvGatewayServiceInterface $indexService)
{
$cvRepository->update($this);
$indexService->update($this);
}
}
2. Listen to domain event (create infrastructure listener)
class CvEntity
{
public function approve(CvRepositoryInterface $cvRepository, EventDispatcheInterface $dispatcher)
{
$cvRepository->update($this);
$dispatcher->dispatch(new CvApprovedEvent($this));
}
}
I like option 2. because it separates logic for non state change purposes into infrastructure, but there is also concern, that we should know about searching as important part of our app.
You're facing here Write and Read model. Ideally after persist your entity/aggregate in the write model you should dispatch the uncommitted events of this entity and listing/subscribe to them to generate the projections (partials in elastic in your use case). For reference: https://github.com/jorge07/symfony-5-es-cqrs-boilerplate/blob/symfony-5/src/Infrastructure/User/ReadModel/Projections/UserProjectionFactory.php#L17
IMO, Entity should not contain the repository.

Query remote rest service from ddd aggregate

I've read about the Double Dispatch pattern, which enables to pass service interfaces into aggregate methods: https://lostechies.com/jimmybogard/2010/03/30/strengthening-your-domain-the-double-dispatch-pattern/, http://blog.jonathanoliver.com/dddd-double-dispatch/.
In my domain I have a BitbucketIntegration aggregate, which is local copy of a remote bitbucket account with some additional domain specific data. Now, I have to synchronize repositories and teams, etc.. from the cloud to be able to do business operations on them. In my first implementation I was using a service to access the Bitbucket Cloud, then set the aggregate's repositories, teams, account. This way I had a DDD mixed with Anemic Domain Model, since half of the aggregates state was set using setter-like methods from the service. With Double Dispatch I can pass e.g. a BitbucketService interface into method arguments. This way, the aggregate can protect it's invariants more, since some of the data can only be verified by connecting to the rest service (e.g. if the aggregate's accessToken, bitbucketAccount and repositories are in sync), which was the service's responsibility. One more thing that smells is that I have an accessToken field in my aggregate, which is only a technical concern.
Are there any recommended patterns for keeping a copy of a remote resource in a ddd aggregate? Also, how to keep the technical side out of it? Or was the first method with a domain service good enough?
Now the code looks something like:
class BitbucketIntegration extends Aggregate<UUID> {
accountId: BitbucketId
repos: List<Repository>
localData: ...
// ... and more
Single integrateWith(accessToken, queryService) {
var id = queryService.getAccountAsync(accessToken);
var repos = queryService.getReposAsync(accessToken);
return Single.zip(id, repos,
(i, r) -> new BitbucketIntegratedEvent(accessToken, i, r))
.onSubscribe(event -> apply(event))
}
Observable doSomeBusinessLocally(data) { ... return events; }
// this is triggered by a saga
Single pollForChanges(queryService) {
var dataFromRemote = queryService.synchronizeAsync(this.accessToken);
....
return event;
}
}
class CommandHandler {
queryService: BitbucketService
Completable handle(integrateCmd) {
aggregate = repo.get(integrateCmd.id);
return aggregate.integrateWith(integrateCmd.accessToken, queryService)
.flatMap(event -> repo.store(event));
}
}
As a side note, I only query Bitbucket.
EDIT:
Martin Fowler writes about accessing an external system, including the definition of an Anti-Corruption Layer, which translates the remote resource representation to domain types.
If you inject infrastructure services into your Aggregate (by constructor or by method invocation) then you won't have a pure domain model anymore. This includes even services that have interfaces defined in the domain layer. It affects testability and introduces a dependency on the infrastructure. It also breaks the Single responsibility principle and it forces the Aggregate to know things it does not really need to.
The solution to this is to call the service before and pass the result to the Aggregate's method (i.e. in the Application layer).

Domain driven design external systems and technical dependencies

I am designing a system using domain driven design concepts and I am struggling with a few things. The "domain" is essentially a business system for the company I work for. I am also using dependency injection. So, in my model I have things related to any typical business system (Employee, Order, Invoice, Deposit, etc..). Right now I am trying to create a cash posting application in which users (aka Employees) can create deposits and apply them to unpaid invoices. The problem that I am having is that we are also using an external business system (Microsoft Dynamics Nav) to handle our accounting transactions. So essentially I am dealing with two different databases. So, for the cash posting application I have modeled the domain objects Deposit and DepositLine. I also have in my domain an IDepositRepository interface that is responsible for persisting the deposits. To get a deposit from the system I just want to grab it directly from the database. However, in order to create a deposit I have to use the Dynamics Nav web services because there is certain logic that gets executed behind the scenes that I don't know about. I started looking at the concept of an Anti Corruption layer in which I could translate my version of the deposit object into a deposit object suitable for the web service. So here is what I am envisioning right now:
Domain Layer
- Models
- Deposit
- DepositLine
- Repositories
- IDepositRepository
Infrastructure Layer
- Data
- Repositories
- DepositRepository
- DynamicsNav
- Services
- INavCashManagementService
- Translators
- IDepositTranslator
- Adapters
- INavAdapter
Now I thought i might implement the DepositRepository like so:
public class DepositRepository
{
private INavCashManagementService navCashManagementService;
public DepositRepository(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public Deposit GetDeposit(int id)
{
// use nhibernate to get directly from the database
}
public void SaveDeposit(Deposit deposit)
{
this.navCashManagementService.CreateDeposit(deposit);
}
}
First of all, is this an appropriate design? My next problem is that users are also going to have to "Post" deposits. The Nav web services will also have to be used to run the posting routine. But, this is more of a business process rather than a persistence issue, so I don't see it fitting into the repository. So I am wondering how/where I should call the posting routine. Should I create a domain service like this:
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
public CashPostingDomainService(INavCashManagementService navCashManagementService)
{
this.navCashManagementService = navCashManagementService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
}
}
One confusion I have with domain driven design is external dependencies. Doesn't the CashPostingDomainService class now have an external dependency on Nav? I know the implementation isn't in the domain layer, but doesn't the interface itself make it a dependency? The same goes with other technical concerns like sending emails. If I have an IEmailService interface and want to send an email once the deposits are posted, would I inject the interface into the CashPostingDomainService class? Or would that be part of the application workflow? So which one of these options make the most sense (if any):
1
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
private IEmailService emailService;
public DepositController(
ICashPostingDomainService cashPostingDomainService,
IEmailService emailService)
{
this.cashPostingDomainService = cashPostingDomainService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
2
public class DepositController
{
private ICashPostingDomainService cashPostingDomainService;
public DepositController(
ICashPostingDomainService cashPostingDomainService)
{
this.cashPostingDomainService = cashPostingDomainService;
}
public void PostDeposits()
{
this.cashPostingDomainService.PostDeposits();
}
}
public class CashPostingDomainService
{
private INavCashManagementService navCashManagementService;
private IEmailService emailService;
public CashPostingDomainService(
INavCashManagementService navCashManagementService,
IEmailService emailService)
{
this.navCashManagementService = navCashManagementService;
this.emailService = emailService;
}
public void PostDeposits()
{
this.navCashManagementService.PostDeposits();
this.emailService.NotifyDepositsPosted();
}
}
Thanks for the help!
is this an appropriate design?
It seems fine to me. The important thing is for your Repository to stay oblivious of the Nav side of things and let the anticorruption layer handle that. You might want to have a look here for a similar example.
I know the implementation isn't in the domain layer, but doesn't the
interface itself make it a dependency?
You may have that feeling because the name of your (supposedly agnostic) service interface contains "Nav". To reflect a service abstraction that could have Nav or any other ERP as an implementation, you should rename it to ICashManagementService.
If I have an IEmailService interface and want to send an email once
the deposits are posted, would I inject the interface into the
CashPostingDomainService class? Or would that be part of the
application workflow?
It's your architectural decision to choose one or the other.
Option 1. means that sending an email is an intrinsic part of the deposit posting domain operation. If you take your domain module and reuse it in another application, posting deposits will automatically result in sending an email whatever that application is about. This might be the right thing to do in your context, or you might want to make things a little more generic (like, sending feedback after the operation but not deciding in the domain service whether this feedback should be mail, a log file, etc.)
Option 2. means that the sequence of events that happen after posting the deposits is application specific, that is at the use case level rather than business/domain level. It is up to the Controller (or Application Service) to decide which actions to take -send an email or anything else. Consequently, different applications based around your domain layer could decide to take different actions. This also means possible code duplication between these applications if several of them chose to send mails.

Interface with service layer or domain objects themselves? (DDD)

I'm still learning about DDD and I have these two (probably simple) questions:
If a Factory creates new object/graph/aggregate instances, but also "reconstitutes" objects/graphs from the Repository, then:
(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioural method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.
(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?
You can see I'm all over the place. Please help.
(1) Does your service layer functions/jobs/tasks/unit-of-work call into the Factory or a behavioral method on the Entity instance or a DomainService function? I'm lost as to the call stack based on the responsibility of these components.
Usually - top level retrieves necessary aggregate root and calls a function on it. Sometimes top level retrieves multiple aggregate roots and pass them to domain service, but not often because domain service is a quite strong sign that there is unrecognized aggregate root. At the end - top level ensures aggregate root is persisted.
(2) Do Entity instances even have "behavioural methods" like above? For example does a Post have p.UpdatePost(string bodyText) or is that not a concern of the domain model and so the same should be achieved with the Repository? Or the service layer function, should it be calling the Repository in this case and the entity instance simply have behavioural methods that are specific to the domain and not persistence? But then, why does it sound like "updating a post" is a domain function when that's the user's goal?
Yes, they do. Domain model should be aware of it's state changes. And that's much more beneficial as it seems at first. Great thing about this is that You gain extensibility point. If client will walk week later to You and say that he wants system to check additional things when user updates post - instead of searching every line of post.bodyText="new value", You will be able to go straight to post.UpdatePost method and attach necessary things there.
On the other hand - CRUD is not mutually exclusive with domain driven design. E.g. - in my application, management of users and their roles is uninteresting enough that I'm not even trying to model it granularly. You need to recognize parts what matters in business Your application is describing and working with.
Keep in mind that domain driven design makes sense for complex applications only. Simple blog application doesn't need it.
(3) Am I wrong in assuming that a service layer (not Domain Services) should encapsulate how an interface interacts with the Domain Layer?
As I see it - application services are more for orchestrating infrastructure. If there is no infrastructure involved - then application service loses value:
Application services basically are just facades. And every facade is bad if complexity it adds overweights problems it solves.
Inside domain:
//aggregate root is persistence ignorant.
//it shouldn't reference repository directly
public class Customer{
public string Name {get; private set;}
public static Customer Register(string name){
return new Customer(name);
}
protected Customer(string name){
//here it's aware of state changes.
//aggregate root changes it's own state
//instead of having state changed from outside
//through public properties
this.Name=name;
}
}
//domain model contains abstraction of persistence
public interface ICustomerRepository{
void Save(Customer customer);
}
Outside of domain:
public class CustomerRepository:ICustomerRepository{
//here we actually save state of customer into database/cloud/xml/whatever
public void Save(Customer customer){
//note that we do not change state of customer, we just persist it here
_voodoo.StoreItSomehow(customer);
}
}
//asp.net mvc controller
public class CustomerController{
public CustomerController(ICustomerRepository repository){
if (repository==null)throw new ArgumentNullException();
_repository=repository;
}
public ActionResult Register(string name){
var customer=Customer.Register(name);
_repository.Save(customer);
}
}

Do I must expose the aggregate children as public properties to implement the Persistence ignorance?

I'm very glad that i found this website recently, I've learned a lot from here.
I'm from China, and my English is not so good. But i will try to express myself what i want to say.
Recently, I've started learning about Domain Driven Design, and I'm very interested about it. And I plan to develop a Forum website using DDD.
After reading lots of threads from here, I understood that persistence ignorance is a good practice.
Currently, I have two questions about what I'm thinking for a long time.
Should the domain object interact with repository to get/save data?
If the domain object doesn't use repository, then how does the Infrastructure layer (like unit of work) know which domain object is new/modified/removed?
For the second question. There's an example code:
Suppose i have a user class:
public class User
{
public Guid Id { get; set; }
public string UserName { get; set; }
public string NickName { get; set; }
/// <summary>
/// A Roles collection which represents the current user's owned roles.
/// But here i don't want to use the public property to expose it.
/// Instead, i use the below methods to implement.
/// </summary>
//public IList<Role> Roles { get; set; }
private List<Role> roles = new List<Role>();
public IList<Role> GetRoles()
{
return roles;
}
public void AddRole(Role role)
{
roles.Add(role);
}
public void RemoveRole(Role role)
{
roles.Remove(role);
}
}
Based on the above User class, suppose i get an user from the IUserRepository, and add an Role for it.
IUserRepository userRepository;
User user = userRepository.Get(Guid.NewGuid());
user.AddRole(new Role() { Name = "Administrator" });
In this case, i don't know how does the repository or unit of work can know that user has a new role?
I think, a real persistence ignorance ORM framework should support POCO, and any changes occurs on the POCO itself, the persistence framework should know automatically. Even if change the object status through the method(AddRole, RemoveRole) like the above example.
I know a lot of ORM can automatically persistent the changes if i use the Roles property, but sometimes i don't like this way because of the performance reason.
Could anyone give me some ideas for this? Thanks.
This is my first question on this site. I hope my English can be understood.
Any answers will be very appreciated.
Should the domain object interact with repository to get/save data?
No, it should not. Reason for that is simple - encapsulation. If we take away everything persistence related from our domain model, we can describe our domain much clearer.
If the domain object doesn't use repository, then how does the Infrastructure layer (like unit of work) know which domain object is new/modified/removed?
Simplest version is - it doesn't. You retrieve and save it back (after operation on aggregate has completed) as a whole:
var user = users.Find(guid);
user.AssignRole(Role.Administrator);
users.Save(user);
I personally rely on NHibernate - it tracks changes itself. If I optimize queries with proper eager/lazy loading, save changes only on http request end, don't forget about transactions, use caching - there is no performance penalty. But for a price - it takes some knowledge to handle that.
One more thing - think twice before using domain driven design for development of forum. This approach fits only for unknown (yet) and complex business domains. It's an overkill for simple applications.
And another thing - stop being ashamed of Your English. It will get better in no time. :)

Resources