How to expose internal domain access only to the repositories - c#

Lets consider this simplified model:
a Subscription class:
public class Subscription
{
public string Name { get; }
public ReadOnlyCollection<Subscriber> Subscribers => _subscribers.AsReadOnly();
private readonly List<Subscriber> _subscribers;
public Subscription(string name)
{
Name = name;
_subscribers = new List<Subscriber>();
}
public Subscriber AddRecipient(Recipient recipient, ReceivingMethod receivingMethod)
{
var subscriber = new Subscriber(this, receivingMethod, recipient);
_subscribers.Add(subscriber);
return subscriber;
}
internal bool RemoveSubscriber(Subscriber subscriber)
=> _subscribers.Contains(subscriber) && _subscribers.Remove(subscriber);
}
a Recipient class:
public class Recipient
{
public Guid Id { get; }
public string Address { get; set; }
public Recipient(string address) : this(Guid.NewGuid(), address)
{
}
internal Recipient(Guid id, string address)
{
Id = id;
Address = address;
}
public Subscriber Subscribe(Subscription subscription, ReceivingMethod receivingMethod)
=> subscription.AddRecipient(this, receivingMethod);
}
and a Subscriber
public class Subscriber : Recipient
{
public Subscription Subscription { get; set; }
public ReceivingMethod ReceivingMethod { get; set; }
internal Subscriber(Subscription subscription, ReceivingMethod method, Recipient recipient)
: base(recipient.Id, recipient.Address)
{
Subscription = subscription;
ReceivingMethod = method;
}
public bool Unsubscribe()
=> Subscription != null && Subscription.RemoveSubscriber(this);
}
A Subscriber results as a Recipient subscribes to a Subscription and as such the instanciation of that object is internally prohebited. At this point I need to load and populate existing Subscribers from within a repository, which implementation resides in a different namespace (.Infrastructure) and cannot access internals of the domain due its protection level.
I strugle to find the right approach. I considered adding the infrastructure layer as a friend to the domain and allowing internal access, but this would make the domain dependend on the infrastructure, while I wan't it to be independent. Right now the domain holds the repositories interfaces, I could add abstract implementations of these, containing access to the models and requiring additional implementation and the injection of a persistence context but this doesn't feel right.
Can someone explain how this is usually done in a rich domain model.
P.S.: This is an architectureal question at application level and as such I think it fits best in SO.

As #maxdoxdev stated: there probably isn't much wrong with rather having domain classes with a public constructor.
If you feel that you definitely do not want public constructors then you could opt for a public factory method on the relevant class or use primitives in your Add methods in order for the method itself to internally instantiate the required object(s).

I feel like there is nothing wrong to expose Domain models to repositories as well as the other layers of onion architecture. It would be wrong other way round (expose other layers to Domain).
Furthermore - if your domain model is well encapsulated, and classes are protecting themselves from being created (or put) in anyhow incorrect state, blocking access to those classes seems to be pointless, as nothing wrong can happen to them being instantiated anywhere in your application as long as that part of application has enough information to create those objects.
Onion architecture is allowing dependency to the inside of the onion (so towards the domain).
Please refer to that image:
https://www.codeguru.com/imagesvr_ce/2236/Onion1.png
or the full article: https://www.codeguru.com/csharp/csharp/cs_misc/designtechniques/understanding-onion-architecture.html
Exposing Domain to outer layers of onion architecture is giving you some possibilities like implementing the CQRS pattern, still maintaining Queries, Commands inside the Domain - and therefore maintaining validations in one place etc.
EDIT:
Another thing that I am using a lot is the Application Layer, that is an orchestrator of all the dependencies, and holder of public API.
Application is holding the Interfaces of repositories, infrastructures and other external dependencies. Those interfaces are implemented in various layers and altogether is injected in the Persistence (UI) layer with IoC.
That gives you the flexibility to replace implementations from outer layers, still having application layer not touched at all, as it only relays on abstractions.
Example:
Controller - accepts DTO and maps it to Query or Command
Application - handles Query or Command by calling abstractions from outer layers and real implementations of Domain
Domain - has rich models that know how to do business actions
Repositories - just implementations of data access
Take a look at this GitHub:
https://github.com/matthewrenze/clean-architecture-demo
That is also related to great Pluralsight video if you are interested.

For completeness I will add an answer to my own question as the existing one while leading in the right direction but lacking concreteness about the example given, in case others are interested in a different approach / concrete implementation.
As the Subscriber is a product of a Recipient subscribing to a specific Subscription, which here is the aggregate root and as such initially responsible for creating the Subscriber, which it still does but in addition I made the constructor of the Subscriber public, in order to allow adding loaded entities.
Making the constructor of the Subscriber public introduced me to the challange to assure the new Subscriber is in a valid state. By this I mean that aswell the Subscriber points to a Subscription as that Subscription is also containing that Subscriber in it's collection of Subscribers and other dependencies that before were handled by the Subscription creation. The solution in the end seems rather simple (in the end) and consisted by adding an internal method to add the Subscriber to the Subscription's Subscribers and apply the other rules, which previously was only available by "subscribing" a Recipient.
So, I enrichted the Subscription class:
internal void AddSubscriber(Subscriber subscriber)
{
if (_subscribers.Contains(subscriber)) return;
_subscribers.Add(subscriber);
subscriber.Subscription = this;
}
And changed the Subscriber constructor:
public Subscriber(Subscription subscription, ReceivingMethod receivingMethod, Recipient recipient)
: base(recipient.EMailAdress, recipient.FirstName, recipient.LastName, recipient.Salutation)
{
Subscription = subscription;
ReceivingMethod = receivingMethod;
subscription.AddSubscriber(this);
}
Now the Repository is able to instanciate the Subscribers from the loaded persistence model.
I am still open to a better approach and/or details about the downsides of this approach.

Related

Using service classes and repository classes in projects?

I've been entering the advanced stage of C# recently and I've seen a lot of applications that implement losely coupling and dependency injection. I've seen the word "Service" a lot associated with classes, I suppose you would call them Service classes? I've also seen classes in this project which include the word Repository, say you has a called 'Player', there would be 2 more classes 'PlayerService' and 'PlayerRepository' classes.
I've checked Linda, TreeHouse, Udemy and many other sites. I've even google the subject but it seems to bring up hundreds of results all leading to different things. None of these links really answer my question in simple plain detail, atleast none that I can understand.
Can anyone help explain this? Why do I need them, when should I use them, what are they?
Well, hard to make a specific explanation without seeing the code but in general terms the concept of a Repository refers to data layer components and the term service - mostly in ASP.NET world refers to business layer components.
You separate these layers from each other so they can be maintained, tested, expanded in isolation. Ideal architectures expose the functionality of these layers via Interfaces - especially the Repository layer. On the Service layer you can take these dependencies through constructor as Interfaces. Using an IoC container and Dependency Injection patterns, you can then register concrete classes to these interfaces and build your objects in a central location aka. Object Composition Root. that allows you easily manage your dependencies in a central location, rather then each dependency instantiated, passed around in scattered places within your code.
This answer is just a pointer to give you an overview. These are topics you should delve deeper by self research and digest.
The Repository pattern is used to abstract away how a class is persisted. This allows you to change the underlying Database or ORM mapper without influencing the persisted classes. See Using Repository Pattern for Abstracting Data Access from a Cache and Data Store.
A service is used if multiple classes are taking part in a certain usecase and none of these classes should have the responsibility to coordinate the other classes. (Maybe these classes do not even hold direct references to each other.) In this case, put the code that handles the interplay between the classes into a service method and pass the affected objects to it.
Note that if the affected classes are in a direct parent-child relationship, you could let the parent coordinate its children directly, without introducing a service. But this might lead to code that is hard to understand.
Let me give an example: assume we want to commit Transactions. After a Transaction was commited, we want to update the Person who has the transaction with the (denormalized) timestamp of the most recent transaction. As you can see, Person does not hold a direct reference to the transaction.
public class Person {
public long Id { get; set; }
public string Name { get; set; }
public DateTime? LastTransactionTimestamp { get; set; }
}
public class Transaction {
public long Id { get; set; }
public long PersonId { get; set; }
public DateTime Timestamp { get; set; }
public void Commit() {
Timestamp = DateTime.Now;
}
}
Now we have the problem where we should put the logic. If we put it into the Person class, it would need Repository access to load the Transaction (because it holds no direct reference). But it should only be concerned with storing its own data, not loading unrelated data from the DB. If we put it into the Transaction class, it does not know if it was the latest Transaction for this Person (because it does not see the other transactions).
So the solution is to put the logic into a service. If the service needs DB access, we inject a repository into it.
public class PersonTransactionService {
private readonly IDbSet<Transaction> _allTransactions;
public PersonTransactionService(IDbSet<Transaction> allTransactions) {
_allTransactions = allTransactions;
}
public void Commit(Person person, Transaction transaction) {
transaction.Commit();
var mostRecent = _allTransactions
.Where(t => t.PersonId == person.Id)
.OrderBy(t => t.Timestamp)
.LastOrDefault();
if (mostRecent != null) {
person.LastTransactionTimestamp = mostRecent.Timestamp;
}
}
}

DDD (Domain Driven Design) Application Layer

I have been trying to build an application based on DDD but I have some questions.
Some layers that I have:
- Presentation Layer - MVC
- Application Layer
- Domain Layer
...
First of all, I would like to know if I can do this in the ApplicationLayer (get family info > get default message info > send an email > updated the database):
public ApproveFamilyOutput ApproveFamily(ApproveFamilyInput input)
{
Family family = _familyRepository.GetFamily(input.Username);
family.Approve();
DefaultMessage defaultMessage = _defaultMessageRepository.GetDefaultMessage(MessageTypes.FamilyApproved);
_email.Send(family.GetEmail(), defaultMessage.Subject, defaultMessage.Message);
_familyRepository.Update(family);
bool isSaved = _familyRepository.Save();
return new ApproveFamilyOutput()
{
Errors = Helper.GetErrorIfNotSaved(isSaved)
};
}
Am I thinking well? Is the Application layer responsible to do that job?
The second question is: I need to send some data to the presentation layer according to the privileges that the user has. These privileges are defined in the database. Example:
- The object Family have the Name, LastName, PhoneNumber, Email properties and the user can show/hide each of the values.
How can I handle with this?
Can I do something like in the Application Layer:
public GetFamilyOutput GetFamily(GetFamilyInput input)
{
Family family = _familyRepository.GetFamily(input.Username);
FamilyConfiguration familyConfiguration = _familyConfigurationRepository.GetConfigurations(family.Id);
//ProcessConfiguration will set to null the properties that I cannot show
family.ProcessConfiguration(familyConfiguration);
return new GetFamilyOutput
{
//Map Family Object to the GetFamilyOutput
};
}
Note: The Family, DefaultMessage and FamilyConfiguration are domain objects created inside the Domain Layer.
What is your opinion?
Thanks :)
Edited:
Note: I liked all the answers below and I used a little of all :) (I can´t mark all answers as acceptable)
What your application service is doing in #1 is perfectly valid: it coordinates the workflow with very little to no business logic knowledge.
There are certainly few improvements that could be done however, for instance:
I do not see any transactions? The email should only be sent upon a successfully comitted transaction.
Sending the email could be seen as a side-effect of the family's approval. I suppose the business experts could have stated: "when a family is approved then notify interested parties by email". Therefore, it could be wise to publish a FamilyApproved domain event and move the email sending logic in an event handler.
Note that you want the handler to be called asynchronously only
after the domain event was persisted to disk and you want to persist
the event in the same transaction as the aggregate.
You could probably further abstract the mailing process into something like emailService.send(MessageTypes.FamilyApproved, family.getEmail()). The application service wouldn't have to know about default messages.
Repositories are usually exclusive to aggregate roots (AR), if DefaultMessage is not an AR then I'd consider naming the DefaultMessageRepository service differently.
As for #2, although authorization checks could be done in the domain, it is much more common to relieve the domain from such task and enforce permissions in the application layer. You could even have a dedicated Identity & Access supporting Bounded Context (BC).
"//ProcessConfiguration will set to null the properties that I cannot
show"
That solution wouldn't be so great (just like implementing the IFamilyProperty solution) because your domain model becomes polluted by technical authorization concerns. If you are looking to apply DDD then the model should be as faithful as possible to the Ubiquitous Language (UL) and I doubt IFamilyProperty is something your domain experts would mention or even understand. Allowing properties to become null would probably violate some invariants as well.
Another problem with such solution is that the domain model is rarely adapted for queries (it's built for commands), so it's often preferrable to bypass it entirely and favor going directly to the DB. Implementing authorizations in the domain would prevent you from doing that easily.
For at least these reasons, I think it is preferrable to implement authorization checks outside the domain. There your are free to use whatever implementation you want and suits your needs. For instance, I believe that stripping off values from a DTO could be legitimate.
I also was doubting if it's ok to place some logic to Application Service or not. But things got much cleaner once I read Vladimir Khorikov's Domain services vs Application services article. It states that
domain services hold domain logic whereas application services don’t.
and illustrates the idea by great examples. So in your cases I think it's totally fine to place these scenarios to Application Service as it doesn't contain domain logic.
Ad 1
I usually move that logic into domain layer - services.
So then the application layer just calls:
public ApproveFamilyOutput ApproveFamily(ApproveFamilyInput input)
{
var approveService = diContainer.Get<ApproveService>(); // Or correctly injected by constructor
var result = approveService.ApproveFamily(input);
// Convert to ouput
}
And domain service (AppproveService class) looks like:
public ApproveResult ApproveFamily(ApproveFamilyInput input)
{
var family = _familyRepository.GetFamily(input.Username);
family.Approve();
_familyRepository.Update(family);
bool isSaved = _familyRepository.Save();
if(isSaved)
_eventPublisher.Publish(family.raisedEvents);
// return result
}
To make it work (and following hexagonal/onion architecture), domain layer defines all interfaces for its dependencies (IFamilyRepository, IDefaultMessageRepository, etc) and application layer injects specific implementation into domain layer.
To make it clear:
1. domain layer is independent
2. domain objects are pure - consist of entities, value objects
3. domain objects don't call repositories, it is up to the domain service
4. domain objects raise events
5. unrelated logic is handled by events (event handlers) - for example sending emails, it follows open-closed principle
class FamilyApprovedHandler : IHandle<FamilyApprovedEvent>
{
private readonly IDefaultMessageRepository _defaultMessageRepository;
private readonly IEmailSender _emailSender;
private readonly IEmailProvider _emailProvider;
// ctor
public Task Handle(FamilyApprovedEvent event)
{
var defaultMessage = _defaultMessageRepository.GetDefaultMessage(MessageTypes.FamilyApproved);
var email = _emailProvider.Generate(event.Family, defaultMessage.Subject, defaultMessage.Message);
_emailSender.Send(email);
}
}
As for #1:
Theoretically, the application layer can do what you have described. However, I personally prefer to separate concerns further: there should be a persistence layer. In your case, a developer needs to know to:
Get the family from the repository.
Call the method to approve the family object.
Update the family back in the repository.
Persist the repository.
Handle any possible errors if there were persistence errors.
I would argue that 2-3-4 should be moved to a persistence layer, to make the code look like:
Family family = _familyRepository.GetFamily(input.Username);
family.Approve().Notify(_email);
This approach gives one more flexibility in how to handle errors and some business logic improvements. For example, you would not be sending an e-mail if you encounter persistence errors.
Of course, you'd need to have some additional types and extension methods implemented (for "Notify()" as an example).
Finally, I'd argue that e-mail service should be implemented using a repository pattern too (so you have two repositories) and have a persistence-level implementation. My point of view: anything persisted outside of the application requires repository & persistence implementation; e-mails are persisted outside of the application in user's mailbox.
As for #2:
I would strongly recommend against nullable properties and clearing them out. It gets really confusing really fast, very hard to unit-test and has a lot of "hidden" caveats. Instead, implement classes for your properties. For example:
public class UserPriviledge { //... your db-defined privileges }
public interface IFamilyProperty<T>
{
public string PropertyName { get; }
public T PropertyValue { get; }
public List<UserPriviledge> ReadPriviledges { get; }
public bool IsReadOnly { get; }
}
public class FamilyName : IFamilyProperty<string>
{
public static string PropertyName => "Name";
public string PropertyValue { get; }
public List<UserPriviledge> ReadPriviledges { get; }
public bool IsReadOnly { get; private set; }
public FamilyName(string familyName) {
this.PropertyValue = familyName;
this.ReadPriviledges.Add(someUserPrivilege);
this.IsReadOnly = false;
}
public void MakeReadOnly() {
this.IsReadOnly = true;
}
}
public class Family
{
public int Id { get; }
public List<IFamilyProperty> LimitedProperties { get; }
}
With this kind of implementation you can have the same kind of method that removes the values instead of obfuscating the value or applies even more complicated logic:
public void ApplyFamilyPermissions(Family family, UserEntity user)
{
foreach (var property in family.LimitedProperties) {
if (property.ReadPriviledges.Intersect(user.Priviledges).Any() == false) {
family.LimitedProperties.Remove(property);
} else if (property.IsReadOnly == false && HasPropertyWriteAccess(property, user) == false) {
property.MakeReadOnly();
}
}
}
Note: the code was not verified and I'm pretty sure has some syntax mistakes, but I believe it communicates the idea clearly.

Who is responsible for entity's mutation when domain event is raised? DDD

I've been learning about CQRS/ES. Looking at small example projects I often see events mutating the entity state. For instance If we look at the Order aggregate root:
public class Order : AggregateRoot {
private void Apply(OrderLineAddedEvent #event) {
var existingLine = this.OrderLines.FirstOrDefault(
i => i.ProductId == #event.ProductId);
if(existingLine != null) {
existingLine.AddToQuantity(#event.Quantity);
return;
}
this.OrderLines.Add(new OrderLine(#event.ProductId, #event.ProductTitle, #event.PricePerUnit, #event.Quantity));
}
public ICollection<OrderLine> OrderLines { get; private set; }
public void AddOrderLine(/*parameters*/) {
this.Apply(new OrderLineAddedEvent(/*parameters*/));
}
public Order() {
this.OrderLines = new List<OrderLine>();
}
public Order(IEnumerable<IEvent> history) {
foreach(IEvent #event in history) {
this.ApplyChange(#event, false);
}
}
}
public abstract class AggregateRoot {
public Queue<IEvent> UncommittedEvents { get; protected set; }
protected abstract void Apply(IEvent #event);
public void CommitEvents() {
this.UncommittedEvents.Clear();
}
protected void ApplyChange(IEvent #event, Boolean isNew) {
Apply(#event);
if(isNew) this.UncommittedEvents.Enqueue(#event);
}
}
when OrderLineAddedEvent is applied it mutates Order by adding new order line. But I don't understand these things:
if it is a right approach how then the changes made are persisted?
Or should I publish the event somehow to a corresponding handler from Order? How do I implement this technically? Should I use a service bus to transmit events?
I am also still experimenting with ES so this is still somewhat of an opinion rather than any guidance :)
At some stage I came across this post by Jan Kronquist: http://www.jayway.com/2013/06/20/dont-publish-domain-events-return-them/
The gist of it is that event should be returned from the domain rather than being dispatched from within the domain. This really struck a chord with me.
If one were to take a more traditional approach where a normal persistence-oriented repository is used the Application Layer would handle transactions and repository access. The domain would simply be called to perform the behaviour.
Also, the domain should always stick to persistence ignorance. Having an aggregate root maintain a list of events always seemed somewhat odd to me and I definitely do not like having my ARs inheriting from some common base. It does not feel clean enough.
So putting this together using what you have:
public OrderLineAddedEvent AddOrderLine(/*parameters*/) {
return this.Apply(new OrderLineAddedEvent(/*parameters*/));
}
In my POC I have also not been using an IEvent marker interface but rather just an object.
Now the Application Layer is back in control of the persistence.
I have an experimental GitHub repository going:
https://github.com/Shuttle/shuttle-recall-core
https://github.com/Shuttle/shuttle-recall-sqlserver
I haven't had time to look at it for a while and I know I have already made some changes but you are welcome to have a look.
The basic idea is then that the Application Layer will use the EventStore/EventStream to manage the events for an aggregate in the same way that the Application Layer would use a Repository. The EventStream will be applied to the aggregate. All events returned from the domain behaviours would be added to the EventStream after which it is persisted again.
This keeps all the persistence-oriented bits out of the domain.
An Entity doesn't update itself magically. Something (usually a service) will invoke the update behaviour of the entity. So, the service uses the entity which will generate and apply the events, then the service will persist the entity via a repository, then it will get the new events from the entity and publish them.
An alternate method is when the Events Store itself does the publishing of the events.
Event Sourcing is about expressing an entity state as a stream of events, that's why the entity updates itself by generating and applying events, it needs to create/add the changes to the events stream. That stream is also what it's stored in the db aka the Event Store.
Lately I am splitting my entities into two objects.
First is what I call a Document object. This is mostly a state only, ORM class with all the configuration related with how the information is persisted.
Then I wrap that Document with an Entity object, which is basically a mutation service containing all the behaviour.
My entities are basically stateless objects except of course for the contained document, but in any case, I mostly avoid any exposure to the outside world.

Where to call repository.update in DDD?

I have a real scenario that is a perfect Domain Model design.
It is a field that has multiple quadrants with different states on every quadrant.
So my aggregate root is the field.
Now i have one important question:
I want to have a persitant ignorat domain model, which i think makes sense. so where should i call the update on the repository methods? not in the domain model, right?
So how should the aggregate root child entities update in the database when there is no change tracking proxy of this objects and the repository should not be called in the entities?
Or do i misunderstand the domain model pattern?
is my question clear? :)
thank you in advance
best
laurin
So where should i call the update on the repository methods?
In a stereotypical DDD architecture the repository is usually called by an application service. An application service is a class which serves as a facade encapsulating your domain and implements domain uses cases by orchestrating domain objects, repositories and other services.
I'm not familiar with your domain, but suppose there is a use case which shifts a State from one Quadrant in a Field to another. As you stated, the Field is the AR. So you'd have a FieldApplicationService referencing a FieldRepository:
public class FieldApplicationService
{
readonly FieldRepository fieldRepository;
public void ShiftFieldState(int fieldId, string quadrant, string state)
{
// retrieve the Field AR
var field = this.fieldRepository.Get(fieldId);
if (field == null)
throw new Exception();
// invoke behavior on the Field AR.
field.ShiftState(quadrant, state);
// commit changes.
this.fieldRepository.Update(field);
}
}
The application service is itself very thin. It does not implement any domain logic; it only orchestrates and sets the stage for execution of domain logic which includes accessing the repository. All code dependant of your domain, such as the presentation layer or a service will invoke domain functionality through this application service.
The repository could be implemented in a variety of ways. It can be with an ORM such as NHibernate, in which case change tracking is built in and the usual approach is to commit all changes instead of calling an explicit update. NHibernate provides a Unit of Work as well allowing changes to multiple entities can be committed as one.
In your case, as you stated, there is no change tracking so an explicit call to update is needed and it is up to the repository implementation to handle this. If using SQL Server as the database, the Update method on the repository can simply send all properties of a Field to a stored procedure which will update the tables as needed.
The Aggregate Root (AR) is updated somwehere. Using a message driven architecture, that somewhere is a command handler, but let's say for general purpose that is a service. THe service gets the AR from a repository, calls the relevant methods then saves the AR back to repository.
The AR doesn't know about the repository, it is not its concern. The Repository then saves all the AR modficications as a unit of work (that is all or nothing). How the Repo does that, well, that depends on how you decided your persistence strategy.
If you're using Event Sourcing, then the AR generates events and the Repo will use those events to persist AR state. If you take a more common approach, that AR should have a state data somewhere exposed as a property perhaps. It's called the memento pattern. The repository persist that data in one commit.
Bu one thing is certain: NEVER think of the persistence details, when dealing with a Domain object. That is don't couple the Domain to an ORM or to some db specific stuff.
The "application code" should call the repository. How the application code is hosted is an infrastructure concern. Some examples of how the application code might be hosted are WCF service, as a Winforms/WPF application, or on a Web server.
The repository implementation is responsible for tracking changes to the aggregate root and its child entities as well as saving them back to the db.
Here is an example:
Domain Project
public DomainObject : AggregateRootBase //Implements IAggregateRoot
{
public void DoSomething() { }
}
public IDomainObjectRepository : IRepository<DomainObject>, IEnumerable
{
DomainObject this[object id] { get; set; }
void Add(DomainObject do);
void Remove(DomainObject do);
int IndexOf(DomainObject do);
object IDof(DomainObject do);
IEnumerator<DomainObject> GetEnumerator();
}
Implementation Project
public SqlDomainObjectRepository : List<DomainObjectDataModel>, IDomainObjectRepository
{
//TODO: Implement all of the members for IDomainObjectRepository
}
Application Project
public class MyApp
{
IDomainObjectRepository repository = //TODO: Initialize a concrete SqlDomainObjectRepository that loads what we need.
DomainObject do = repository[0]; //Get the one (or set) that we're working with.
do.DoSomething(); //Call some business logic that changes the state of the aggregate root.
repository[repository.IDof(do)] = do; //Save the domain object with all changes back to the db.
}
If you need to transactionalize changes to multiple aggregate roots so the changes are made on an all or nothing basis, then you should look into the Unit of Work pattern.
Hope this helps clarify things!
My solution is the aggregate root will raise some events to event handlers outside. Those event handlers will call repository to update the database. You will also need a ServiceBus to register and dispatch events. See my example:
public class Field: AggregateRoot
{
public UpdateField()
{
// do some business
// and trigger FieldUpdatedEvent with necessary parameters
....
// you can update some quadrants
// and trigger QuadrantsUpdatedEvent with necessary parameters
}
}
public class FieldEventHandlers: EventHandler
{
void Handle (FieldUpdatedEvent e)
{
repository.Update(e.Field);
}
}
public class QuadrantEventHandlers: EventHandler
{
void Handle (QuadrantsUpdatedEvent e)
{
repository.Update(e.Quadrant);
}
}

Managing persistence in DDD

Let's say that I want to create a blog application with these two simple persistence classes used with EF Code First or NHibernate and returned from repository layer:
public class PostPersistence
{
public int Id { get; set; }
public string Text { get; set; }
public IList<LikePersistence> Likes { get; set; }
}
public class LikePersistence
{
public int Id { get; set; }
//... some other properties
}
I can't figure out a clean way to map my persistence models to domain models. I'd like my Post domain model interface to look something like this:
public interface IPost
{
int Id { get; }
string Text { get; set; }
public IEnumerable<ILike> Likes { get; }
void Like();
}
Now how would an implementation underneath look like? Maybe something like this:
public class Post : IPost
{
private readonly PostPersistence _postPersistence;
private readonly INotificationService _notificationService;
public int Id
{
get { return _postPersistence.Id }
}
public string Text
{
get { return _postPersistence.Text; }
set { _postPersistence.Text = value; }
}
public IEnumerable<ILike> Likes
{
//this seems really out of place
return _postPersistence.Likes.Select(likePersistence => new Like(likePersistence ));
}
public Post(PostPersistence postPersistence, INotificationService notificationService)
{
_postPersistence = postPersistence;
_notificationService = notificationService;
}
public void Like()
{
_postPersistence.Likes.Add(new LikePersistence());
_notificationService.NotifyPostLiked(Id);
}
}
I've spent some time reading about DDD but most examples were theoretical or used same ORM classes in domain layer. My solution seems to be really ugly, because in fact domain models are just wrappers around ORM classes and it doens't seem to be a domain-centric approach. Also the way IEnumerable<ILike> Likes is implemented bothers me because it won't benefit from LINQ to SQL. What are other (concrete!) options to create domain objects with a more transparent persistence implementation?
One of the goals of persistence in DDD is persistence ignorance which is what you seem to be striving for to some extent. One of the issues that I see with your code samples is that you have your entities implementing interfaces and referencing repositories and services. In DDD, entities should not implement interfaces which are just abstractions of itself and have instance dependencies on repositories or services. If a specific behavior on an entity requires a service, pass that service directly into the corresponding method. Otherwise, all interactions with services and repositories should be done outside of the entity; typically in an application service. The application service orchestrates between repositories and services in order to invoke behaviors on domain entities. As a result, entities don't need to references services or repositories directly - all they have is some state and behavior which modifies that state and maintains its integrity. The job of the ORM then is to map this state to table(s) in a relational database. ORMs such as NHibernate allow you to attain a relatively large degree of persistence ignorance.
UPDATES
Still I don't want to expose method with an INotificationService as a
parameter, because this service should be internal, layer above don't
need to know about it.
In your current implementation of the Post class the INotificationService has the same or greater visibility as the class. If the INotificationService is implemented in an infrastructure layer, it already has to have sufficient visibility. Take a look at hexagonal architecture for an overview of layering in modern architectures.
As a side note, functionality associated with notifications can often be placed into handlers for domain events. This is a powerful technique for attaining a great degree of decoupling.
And with separate DTO and domain classes how would you solve
persistence synchronization problem when domain object doesn't know
about its underlying DTO? How to track changes?
A DTO and corresponding domain classes exist for very different reasons. The purpose of the DTO is to carry data across system boundaries. DTOs are not in a one-one correspondence with domain objects - they can represent part of the domain object or a change to the domain object. One way to track changes would be to have a DTO be explicit about the changes it contains. For example, suppose you have a UI screen that allows editing of a Post. That screen can capture all the changes made and send those changes in a command (DTO) to a service. The service would load up the appropriate Post entity and apply the changes specified by the command.
I think you need to do a bit more research, see all the options and decide if it is really worth the hassle to go for a full DDD implementation, i ve been there myself the last few days so i ll tell you my experience.
EF Code first is quite promising but there are quite a few issues with it, i have an entry here for this
Entity Framework and Domain Driven Design. With EF your domain models can be persisted by EF without you having to create a separate "persistence" class. You can use POCO (plain old objects) and get a simple application up and running but as i said to me it s not fully mature yet.
If you use LINQ to SQL then the most common approach would be to manually map a "data transfer object" to a business object. Doing it manually can be tough for a big application so check for a tool like Automapper. Alternatively you can simply wrap the DTO in a business object like
public class Post
{
PostPersistence Post { get; set;}
public IList<LikePersistence> Likes { get; set; }
.....
}
NHibernate: Not sure, havent used it for a long time.
My feeling for this (and this is just an opinion, i may be wrong) is that you ll always have to make compromises and you ll not find a perfect solution out there. If you give EF a couple more years it may get there. I think an approach that maps DTOs to DDD objects is probably the most flexible so looking for an automapping tool may be worth your time. If you want to keep it simple, my favourite would be some simple wrappers around DTOs when required.

Categories

Resources