Understanding rich domain models and dependencies - c#

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.

Related

Where to access persistance in DDD

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.

How to map to internal properties using Automapper?

we've been using Automapper for sometime and we think it is great utility, thanks for creating it!
However, we have a question:
Question
"How do you configure AutoMapper to map a source property to an internal destination property?"
Background
In our layered architecture, Dto objects never leave the Data Access layer, only Domain objects are allowed to pass in and out of the Data Access layer. Thus, from a domain POV, domain objects shouldn't contain any database knowledge. However, in reality database Ids are very useful to carry around - expect the 'business-layer' developer shouldn't know about them.
Solution: add the database Ids to the domain object but market them as internal so that they aren't exposed to the 'business-layer'. Next expose the Common layer (which owns the domain objects) internals to the Data Access layer. Problem solved. Expect we can't figure out how to get Automapper (> v3.3.0) to work with our internal properties.
In, version 3.3.0 BindingFlags were exposed, which use to solve the problem.
Example
Common.Dll
public class Person
{
public Parent Father { get; set; }
internal int FatherId {get; private set; }
}
DataAccess.dll
internal class PersonDto
{
public ParentDto Father { get; set; }
public int FatherId {get; private set; }
}
In our Profile class we have CreateMap<PersonDto, Person>();
Edit 1 - Fixed a typo in the return type of Father.
Edit 2 - Added more info..
In the Common.Dll, we have Services something like this:
public class ParentService
{
public Parent GetFather(Person person)
{
return repo.Parents.FirstOrDefault(parent => parent.Id = person.Father.Id);
}
}
And in the Business.Dll we have developer's using the Services something like this:
var father = parentService.GetFather(son);
// use father separately or assign it to the son. Like so:
// son.Father = father;
The whole point is, we don't want the business developer's to have access to son.FatherId from the Businssess.Dll nor do they have access to the Dto object that created the domain object.
Thus, all the 'database' knowledge is encapsulated within in the various Common.dll Services or in the DataAccess.dll.
Thanks.
This question is answered here.
I quote the answer for your convenience:
Just set the ShouldMapProperty property of your configuration object
in the initialize method.
Here is an example using the static API, however, you should be able
to achieve the same in a similar fashion by using the non-static API.
Mapper.Initialize(i =>
{
i.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
i.CreateMap<Source, Target>();
});

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.

Amalgamate unique methods from multiple classes on interface?

I have 2 classes that contain unique DB repositories. Both interact with different DBs. I would like to amalgamate these repositories onto a single interface. Is this possible or will it always be the case that neither class will be deemed to fully implement all of the interface members?
I would like something like this,
public class FooDatabase : IFooBarDatabases
{
public IFooRepository FooRepository { get; set; }
}
public class BarDatabase : IFooBarDatabases
{
public IBarRepository BarRepository { get; set; }
}
public interface IFooBarDatabases
{
IFooRepository FooRepository { get; }
IBarRepository BarRepository { get; }
}
Repositories should be "database independant"
A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes
Now the way how you will create yuor repository really depends by your domain rather then what database will be hit: a repository should not care about what database will be hit
http://martinfowler.com/eaaCatalog/repository.html

Categories

Resources