Where to access persistance in DDD - c#

I am looking into Domain Driven Design (yes, I am quite late for that party) and so far I have come to the realization that the Domain Model should be the center of the universe. The data persistance is merely a practical detail.
However, if this is true, then I have a hard time figuring out where the communication with the persititance part (e.g. a repository) should be.
For instance, if I want to be able to add a new grade to a student, should I call the repository from inside the student domain model, like this?
interface IGradeRepository
{
void SaveGrade(int courseId, string grade);
// ...other methods
}
class Student
{
IGradeRepository _gradeRepository;
List<Grade> _grades = new List<Grade>();
public Student(IGradeRepository gradeRepository)
{
_gradeRepository = gradeRepository;
}
int StudentId { get; set; }
void AddGrade(int courseId, string grade)
{
var grade = new Grade(this.StudentId, courseId, grade);
_grades.Add(grade);
// Do I put the call to the data persistance here?
_gradeRepository.SaveGrade(grade);
}
}
As you can see, my best bet is to access the repository from inside the domain model. However, I am not sure if this is the way to go about it. It seems to be one of the things that is left out in many tutorials.
So to summarize: From where do I access the data layer, when doing Domain Driven Design?
Update
As some have commented, it is not clear from my example, how I would access the student class. I would probably do that from a view model or through some sort of use case service.
Example with view model:
class StudentGradesViewModel
{
// (...) all sort of VM-stuff
private Student _student;
private Course _selectedCourse;
public void AddGrade(string grade)
{
_student.AddGrade(_course.CourseId, grade);
}
}

First of all: The repository should only refer to aggregate. In your case, you have student which can have multiple grades.
So, you repository should always be the persistance for the aggregate, not an entity inside an aggregate.
Here is the solution with the way I would choose:
Aggregate in Domain Layer:
class Student
{
List<Grade> _grades = new List<Grade>();
int StudentId { get; set; }
public Student()
{
}
void AddGrade(int courseId, string grade)
{
var grade = new Grade(this.StudentId, courseId, grade);
_grades.Add(grade);
}
}
Repository Interface in Domain Layer:
interface IStudentRepository
{
void SaveStudent(int studentId);
// ...other methods
}
Of course, as it was mentioned in posts above, the implementation of Repository should take place infrastructure layer.
You should create Application Service or CommandHandler (if you're using CQRS) in order to integrate domain logic and infrstructure:
class AddGradeService
{
private readonly IStudentRepository _studentRepository;
public AddGradeService(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
void Handle(int studentId, int courseId, string grade)
{
Student student = _studentRepository.Get(studentId);
student.AddGrade(courseId, grade);
_studentRepository.Save(student);
}
}
This is how it should be done :)
You can also refer to my example od DDD if you want: https://github.com/czarek-szok/DDD.Ecommerce/

The best time to join the party is right now so no worries. You should not access the data persistence directly from your domain model, instead this should be done in the infrastructure layer. If you are familiar with Onion Architecture, it explains this nicely. You can look it up here or here. The same principles described in the links can be applied to your case.
Accessing the persistence layer (usually named infrastructure) is via executing your use-cases which are usually placed in the application layer and implemented via commands (manipulating the state of entities) or queries (reading the state of entities in persistance)

should I call the repository from inside the student domain model, like this?
That's not the usual pattern.
Instead, it is more common that the interaction with the repositories happens at the application layer, rather than within the domain layer.
The repositories give the application access to the aggregate root, and the application interacts with the aggregate root only. So the simple pattern looks something like
using transaction():
Root root = _repository.get(rootId)
root.doSomeCoolDomainThing(...)
The assumption here being that root has access to all of the persisted information required to maintaining its domain invariant while doing the cool thing (which normally means that the entire graph of information is available in memory).
In some cases, you'll see the save of the root into the repository be made more explicit:
using transaction():
Root root = _repository.get(rootId)
root.doSomeCoolDomainThing(...)
_repository.save(root)
What is the root when you get all the way to the bottom?
Root is a domain model entity; it's the one that is "in charge", so to speak, of all of the other entities in that particular aggregate.
Here, I'm just using it as a stand in. In a real project, the spelling would reflect the language of your domain -- Student, GradeBook, ReportCard, etc.

Related

Understanding rich domain models and dependencies

I'm trying to get my head around rich domain models and how to build semantic functionality into domain entities, where the domain entities are not tightly coupled to objects that provide implementations for semantic behaviour
For example, I want to build a User entity into my domain model, but I want it's implementation to be driven by identity framework
class User
{
public string Email { get; set; }
... All of the other IdentityUser properties...
public void DisableUser()
{
...behaviour to disable a user, most likely requires UserManager
}
public void AddToRole(Role role)
{
... most likely requires RoleManager
}
}
So now that I have a domain model that behaves according to the business rules, and is ignorant to persistence and implementation.
But how exactly are DisableUser() and AddToRole() supposed to work when they have no dependencies and aren't in any way coupled to UserManager and RoleManager?
Generally, what am I missing?
Should domain entities have dependencies on objects that provide behavior?
How should I decouple my domain model from implementation providers?
What I do is that I have each of my rich domain model entities receive a reference to the central domain object as a constructor parameter, and store it as a readonly member.
This is easy because the domain acts as the factory of its entities, so whenever it news one of them, it passes this as the first constructor parameter. (Entities are supposed to have assembly-internal constructors so that they cannot be instantiated by anyone but the domain itself.)
And if you really dig into the documentation of ORM frameworks you will usually find that they tend to allow you to supply a factory for your entities, so you can do things like that.
So, since each entity has a reference to the domain, it can obtain from it whatever it needs to do its job. (Presumably, your domain object will contain a reference to a UserManager and to a RoleManager, no?) This is essentially taking a pragmatic step back from dependency injection: you inject the domain object with its dependencies, but you have each entity of the domain fetch its dependencies from the domain object.
Here is an example in java:
package ...
import ...
public final class StarWarsDomain extends Domain
{
private static final Schema SCHEMA = ...
public StarWarsDomain( LogicDomain logicDomain, S2Domain delegeeDomain )
{
super( logicDomain, SCHEMA, delegeeDomain ); //these get stored in final members of 'Domain'
}
public UnmodifiableEnumerable<Film> getAllFilms()
{
return getAllEntitys( Film.COLONNADE ); //method of 'Domain'
}
public Film newFilm( String name )
{
assert !StringHelpers.isNullOrEmptyOrWhitespace( name );
Film film = addEntity( Film.COLONNADE ); //method of 'Domain'
film.setName( name );
return film;
}
}
A well crafted domain model should have no dependencies on any other architectural layers or services. With respect, domain model objects should be (in my case) POCOs (Plain Old CLR Objects). Services and layers such as business logic or persistence layers should then depend on these objects and return instances of them.
There are several keys to building a domain model that respects low coupling, high cohesion and persistence ignorance. In one statement, the secret to this is "write the code you wish you had".
Domain Model Example
public class Student
{
// Collections should be encapsulated!
private readonly ICollection<Course> courses;
// Expose constructors that express how students can be created.
// Notice that this constructor calls the default constructor in order to initialize the courses collection.
public Student(string firstName, string lastName, int studentNumber) : this()
{
FirstName = firstName;
LastName = lastName;
StudentNumber = studentNumber;
}
// Don't allow this constructor to be called from code.
// Your persistence layer should however be able to call this via reflection.
private Student()
{
courses = new List<Course>();
}
// This will be used as a primary key.
// We should therefore not have the ability to change this value.
// Leave that responsibility to the persistence layer.
public int Id { get; private set; }
// It's likely that students names or numbers won't change,
// so set these values in the constructor, and let the persistence
// layer populate these fields from the database.
public string FirstName { get; private set; }
public string LastName {get; private set; }
public int StudentNumber { get; private set; }
// Only expose courses via something that is read-only and can only be iterated over.
// You don't want someone overwriting your entire collection.
// You don't want someone clearing, adding or removing things from your collection.
public IEnumerable<Course> Courses => courses;
// Define methods that describe semantic behaviour for what a student can do.
public void Subscribe(Course course)
{
if(courses.Contains(course))
{
throw new Exception("Student is already subscribed to this course");
}
courses.Add(course);
}
public void Ubsubscribe(Course course)
{
courses.Remove(course);
}
}
Granted, this domain model object was written with Entity Framework in mind, but it's a far cry from the usual Entity Framework examples (which are anemic domain models by contrast). There are a few caveats that need to be considered when crafting domain model objects in this way, but Entity Framework will persist them (with a little jiggery-pokery), and you get a domain model object that defines a clean, semantic contract to layers that depend on it.

Migrate from CRUD to DDD

Now I want to try to start from the objects of my model according to the dictates DDD but I have some difficulty in understanding how to migrate my thought patterns because I can not turn the examples that I find lying around on my specific case .
My main concept are the activities , each activity has an indicative code , a description , a status that changes over time and a quarter each Result.
Users want to be able to see the history of all the states hired from the activities, with the dates on which the changes were made . In addition, they also want to be able to create new states, change the description of the existing ones and possibly prevent the use of some of these while maintaining the value for the previous activities .
Each quarter, users want to be able to insert an Result that contains Outcome and recommendations, a rating and the date of formulation of the outcome .
The ratings must be a list freely maintainable by users.
Thinking to my old way I would create classes like this:
public class Activity
{
public int ID;
public string Desc;
public IList<ActivityStatus> ActivityStatusList;
public IList<Result> ResultList;
}
public class ActivityStatus
{
public Activity Activity;
public Status Status;
public DateTime StartDate;
public DateTime EndDate;
}
public class Status
{
public int ID;
public string Desc;
public bool Valid;
}
public class Result
{
public Activity Activity;
public int Quarter;
public string Outcome;
public string Recommendations;
public Rating Rating;
}
public class Rating
{
public int ID;
public string Desc;
public bool Valid;
}
than i will implement a DataAccessLayer mapping this class to a new db (created from this class) with NHibernate and add repository to grant user CRUD operation to all of this object
According to DDD are there better ways?
I'd recommend to read the book or at least the Wikipedia article.
DDD is about focussing on domain logic and modelling this first - in an object-oriented way. Persistence is a technical concern, which should not be the starting point of your design and (usually) not determine, how you will design your domain classes.
If you're eager to code and believe you understand the domain well, I would suggest a BDD test-first approach. Use tools like SpecFlow to describe your business processes in plain english, then gradually fill in the steps and functionality as you go, using mocks, design patterns, inversion of control etc.
Background reading is a must if you're unfamiliar with DDD. Read the book that EagleBeak suggests, get clued up on SOLID principles and experiment yourself.
I canĀ“t tell if there are better ways but what you said would be one way to solve this problem in a DDD fashion.
In my data access layer I typically use an abstract factory of respositories. This way I can plug an specific implementation for data access such as NHibernate.
public interface IRepositoryFactory {
T Repository<T>();
};
public class NHibernateRepositoryFactory {
T Repository<T>() {
..... // find class that implements T in Assemblies with reflection
return repository;
}
};
public static class Persistence {
IRepositoryFactory Factory { get; set; }
};
This way you can call your repository without referencing any specific implementation:
User user = Persistence.Factory.Get<IUserRepository>().FindByEmail("john#tt.com");
user.name = "James";
Persistence.Factory.Get<IUserRepository>().save(user);
Another advantage of using abstract factories for repositories as above is that you can test your code by pluging a fake implementation for the repository.
public class FakeRepositoryFactory {
T Repository<T>() {
..... // find class that implements T in Assemblies of fake repositories
return repository;
}
};
public class FakeUserRepository : public IUserRepository {
User FindByEmail(string email) {
// create mocked user for testing purposes ....
return userMock;
}
};
Your code will not and should not know where the user data is coming from with abstract factories for persistence. This way switch from one way to another can be done in a transparent way.

Exposing an object through a 'view' interface

I've been trying to find a flexible way of exposing an object through a 'view'. I'm probably better off explaining by way of example.
I have an Entity Framework entity model, and a web service that can be used to query it. I am able to return the entity classes themselves, but this would include some fields I might not want to share - IDs, for examples, or *Reference properties from any associations in the entity model.
I figure what I need is a view of the data, but I don't particular want to write a view wrapper class for every return type. I'm hoping I'll be able to define an interface and somehow make use of that. For example:
interface IPersonView
{
string FirstName { get; }
string LastName { get; }
}
-
// (Web service method)
IPersonView GetPerson(int id)
{
var personEntity = [...];
return GetView<IPersonView>(personEntity);
}
However, in order to do something like this, I'd have to have my entities implement the view interfaces. I was hoping for a more flexible 'duck-typed' approach as there may be many views of an object, and I don't really to want to have to implement them all.
I've had some success building a dynamic type by reflecting the interface and copying fields and properties across, but I'm not able to cast this back to the interface type in order to get strong typing on the web service.
Just looking for some comments and advice, both would be welcome. Thanks.
You shouldn't ever really be passing entities directly out to a client, they should be used for persistance only. You should introduce DTOs/POCOs tailored to whatever data your API wants to return e.g.
public class PersonDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
// public API method
public PersonDto GetPersonApi(int id)
{
var personEntity = // pull entity from db
return new PersonDto()
{
FirstName = personEntity.FirstName,
LastName = personEntity.LastName
};
}
This keeps a clean separation between your persistence layer & public interface. You can use a tool like AutoMapper to do the legwork in terms of mapping the data across. Just setup a mapping once e.g. in your global asax:
protected void Application_Start()
{
Mapper.CreateMap<Person, PersonDto>();
}
...
// public API method
public PersonDto GetPersonApi(int id)
{
var personEntity = // pull entity from db
return Mapper.Map<Person, PersonDto>(personEntity);
}
I typically see this done with AutoMapper or a similar tool. It makes mapping between similar classes much simpler. You still have to create the Views (which in an MVC-context would be a Model), but the most tedious part (the mapping) is taken care of for you so long as you use the same field names.
As a side note, sharing IDs and other reference data will be necessary if you want to update the data, since you'll need to know the keys in order to know which record(s) to update.

Rich domain model with behaviours and ORM

After watching NDC12 presentation "Crafting Wicked Domain Models" from Jimmy Bogard (http://ndcoslo.oktaset.com/Agenda), I was wandering how to persist that kind of domain model.
This is sample class from presentation:
public class Member
{
List<Offer> _offers;
public Member(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
_offers = new List<Offer>();
}
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<Offer> AssignedOffers {
get { return _offers; }
}
public int NumberOfOffers { get; private set; }
public Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc)
{
var value = valueCalc.CalculateValue(this, offerType);
var expiration = offerType.CalculateExpiration();
var offer = new Offer(this, offerType, expiration, value);
_offers.Add(offer);
NumberOfOffers++;
return offer;
}
}
so there are some rules contained in this domain model:
- Member must have first and last name
- Number of offers can't be changed outside
- Member is responsible for creating new offer, calculating its value and assignment
If if try to map this to some ORM like Entity Framework or NHibernate, it will not work.
So, what's best approach for mapping this kind of model to database with ORM?
For example, how do I load AssignedOffers from DB if there's no setter?
Only thing that does make sense for me is using command/query architecture: queries are always done with DTO as result, not domain entities, and commands are done on domain models. Also, event sourcing is perfect fit for behaviours on domain model. But this kind of CQS architecture isn't maybe suitable for every project, specially brownfield. Or not?
I'm aware of similar questions here, but couldn't find concrete example and solution.
This is actually a very good question and something I have contemplated. It is potentially difficult to create proper domain objects that are fully encapsulated (i.e. no property setters) and use an ORM to build the domain objects directly.
In my experience there are 3 ways of solving this issue:
As already mention by Luka, NHibernate supports mapping to private fields, rather than property setters.
If using EF (which I don't think supports the above) you could use the memento pattern to restore state to your domain objects. e.g. you use entity framework to populate 'memento' objects which your domain entities accept to set their private fields.
As you have pointed out, using CQRS with event sourcing eliminates this problem. This is my preferred method of crafting perfectly encapsulated domain objects, that also have all the added benefits of event sourcing.
Old thread. But there's a more recent post (late 2014) by Vaughn Vernon that addresses just this scenario, with particular reference to Entity Framework. Given that I somehow struggled to find such information, maybe it can be helpful to post it here as well.
Basically the post advocates for the Product domain (aggregate) object to wrap the ProductState EF POCO data object for what concerns the "data bag" side of things. Of course the domain object would still add all its rich domain behaviour through domain-specific methods/accessors, but it would resort to inner data object when it has to get/set its properties.
Copying snippet straight from post:
public class Product
{
public Product(
TenantId tenantId,
ProductId productId,
ProductOwnerId productOwnerId,
string name,
string description)
{
State = new ProductState();
State.ProductKey = tenantId.Id + ":" + productId.Id;
State.ProductOwnerId = productOwnerId;
State.Name = name;
State.Description = description;
State.BacklogItems = new List<ProductBacklogItem>();
}
internal Product(ProductState state)
{
State = state;
}
//...
private readonly ProductState State;
}
public class ProductState
{
[Key]
public string ProductKey { get; set; }
public ProductOwnerId ProductOwnerId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<ProductBacklogItemState> BacklogItems { get; set; }
...
}
Repository would use internal constructor in order to instantiate (load) an entity instance from its DB-persisted version.
The one bit I can add myself, is that probably Product domain object should be dirtied with one more accessor just for the purpose of persistence through EF: in the same was as new Product(productState) allows a domain entity to be loaded from database, the opposite way should be allowed through something like:
public class Product
{
// ...
internal ProductState State
{
get
{
// return this.State as is, if you trust the caller (repository),
// or deep clone it and return it
}
}
}
// inside repository.Add(Product product):
dbContext.Add(product.State);
For AssignedOffers : if you look at the code you'll see that AssignedOffers returns value from a field. NHibernate can populate that field like this: Map(x => x.AssignedOffers).Access.Field().
Agree with using CQS.
When doing DDD first thing, you ignore the persistence concerns. THe ORM is tighlty coupled to a RDBMS so it's a persistence concern.
An ORM models persistence structure NOT the domain. Basically the repository must 'convert' the received Aggregate Root to one or many persistence entities. The Bounded Context matters a lot since the Aggregate Root changes according to what are you trying to accomplish as well.
Let's say you want to save the Member in the context of a new offer assigned. Then you'll have something like this (of course this is only one possible scenario)
public interface IAssignOffer
{
int OwnerId {get;}
Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc);
IEnumerable<Offer> NewOffers {get; }
}
public class Member:IAssignOffer
{
/* implementation */
}
public interface IDomainRepository
{
void Save(IAssignOffer member);
}
Next the repo will get only the data required in order to change the NH entities and that's all.
About EVent Sourcing, I think that you have to see if it fits your domain and I don't see any problem with using Event Sourcing only for storing domain Aggregate Roots while the rest (mainly infrastructure) can be stored in the ordinary way (relational tables). I think CQRS gives you great flexibility in this matter.

Repository pattern to query multiple databases

This is a very weird architecture. Please bear with me.
We have an existing tiered application (data, logic/service, client).
The latest requirement is that the service layer should access two data sources!!!! (no other way around)
These two data sources have the same DB schema.
As with most tiered architectures, we have read and write methods like:
IEnumerable<Product> GetAllProducts(),
Product GetProductById(ProductKey id),
IEnumerable<Product> FindProductsByName(string name)
the product DTOs are:
class Product
{
public ProductKey Key { get; set;}
...
}
class ProductKey
{
public long ID { get; }
}
We narrowed it down to two possible solutions:
Alternative 1:
Add a parameter into the read methods so that the service knows what DB to use like so:
Product GetProductById(ProductKey id, DataSource dataSource)
DataSource is an enumeration.
Alternative 2 (my solution):
Add the DataSource property to the key classes. this will be set by Entity Framework when the object is retrieved. Also, this will not be persisted into the db.
class ProductKey
{
public long ID { get; }
public DataSource Source { get; } //enum
}
The advantage is that the change will have minimal impact to the client.
However, people dont like this solution because
the DataSource doesn't add business value. (My response is that
the ID doesn't add business value either. Its a surrogate key. Its
purpose is for tracking the persistence)
The children in the object graph will also contain DataSource which is redundant
Which solution is more sound? Do you have other alternatives?
Note: these services are used everywhere.
What I would suggest is door number 3:
[||||||||||||||]
[|||||||||s! ]
[||||nerics! ]
[ Generics! ]
I use a "dynamic repository" (or at least that is what I have called it). It is setup to be able to connect to any datacontext or dbset while still being in the same using block (i.e. without re-instantiation).
Here is a snippet of how I use it:
using (var dr = new DynamicRepo())
{
dr.Add<House>(model.House);
foreach (var rs in model.Rooms)
{
rs.HouseId = model.House.HouseId;
dr.Add<Room>(rs);
}
}
This uses the "default" dbcontext that is defined. Each one must be defined in the repository, but not instantiated. Here is the constructor I use:
public DynamicRepo(bool Main = true, bool Archive = false)
{
if (Main)
{
this.context = new MainDbContext();
}
if (Archive)
{
this.context = new ArchiveDbContext();
}
}
This is a simplified version where there are only two contexts. A more in depth selection method can be implemented to choose which context to use.
And then once initialized, here would be how the Add works:
public void Add<T>(T te) where T : class
{
DbSet<T> dbSet = context.Set<T>();
dbSet.Add(te);
context.SaveChanges();
}
A nice advantage of this is that there is only one spot to maintain the code for interacting with the database. All the other logic can be abstracted away into different classes. It definitely saved me a lot of time to use a generic repository in this fashion - even if I spent some time modifying it at first.
I hope I didn't misunderstand what you were looking for, but if you are trying to have one repository for multiple data sources, I believe this is a good approach.

Categories

Resources