We have a large application that we are starting to develop using DDD.
We understand the concept of Aggregates (roots) and bounded contexts and repositories, where repositories accept only aggregate roots to be persisted.
What I am not clear about is this. We have auto generated entity classes for each bounded context in the persistence layer, and have a few domain models sitting in the domain layer. We do this to simplify a very complex database structure (700+ tables), which is why, for instance, we have a Customer entity class and related entities that map to a CustomerModel complex type as a domain model.
The IRepository<IAggregateRoot> has Get, Save, Delete, Update CRUD methods.
Given the example above with Customer and CustomerModel, the dbo.Customer table has about 15 other tables that belong to the same aggreagte. But what classes are actually supposed to implement the IAggreagteRoot?
The aggreagte is a logical grouping, but is it done in the domain:
public class CustomerModel : IAggreagteRoot {}
or is it done in the entity class:
public class Customer : IAggreagteRoot {}
To me it makes more sense to define the domain model classes as aggreagtes, because those are visible to the application(s) "sitting" on top of the domain. The entities are for persistance.
Thank you.
I think that you have mixed two concepts here. Everything in domain layer is Your model (domain model): aggregates, entities, value objects etc.
What you named CustomerModel is probably just a DB model (if I understood correctly), and DB models are part of infrastructure level. Domain layer has no knowledge about that.
To answer Your question: Customer should implement AggregateRoot interface.
Example:
infrastructure.ui.show_the_oldest_user:
oldest_user_dto = user_service.get_the_oldest_user()
oldest_user_dto is just a raw data
application.service.get_the_oldest_user:
user = user_repository.get_oldest()
return user
user is an aggregate root
infrastructure.persistence.repository.user.get_oldest:
orm_user = user_orm_model.order('age').desc().one()
user = this.reconstitute(orm_user)
return user
orm_user is an instance of user model from DB, which we have to map to our aggregate root (reconstitute).
This way we have no orm instance flying across all layers which is a really bad coupling. I also map aggregate to dto when I return it from application service, so UI is not coupled to domain model, but it's not a must.
AggregateRoots are Entities, the difference being that they can be accessed from services, views, etc.
Customer, in your example, is an aggregate root.
CustomerAddress is not - so you would make sure that calls to update a customer address went through Customer
customer.UpdateAddress(addressValueObject);
rather than having any way you can deal with a customer's address outside the context of that customer. In other words, you shouldn't have anything like
address.Update(newValue)
outside of the Customer entity.
Related
According to DDD for each aggregate i have repository. Let's take an example:
Client (model aggregate) > ClientRepository
Visit (model aggregate) > VisitRepository
Now phisicly i have association table in database which connects Client and Visit because clients could have many visists.
The question is: Should i create separated model like: ClientVisit which also would be an aggregate:
public class ClientVisit
{
int clientId;
int visitId;
}
Also s repository like ClientVisitRepository which could reference/use ClientRepository and VisitRepository.
Or is it enough to stick with e.g CLientRepository and get data from there without additionality model and repository
Modification to the post:
Instead of Visit (wrong example) - let's replace by Car therefore each client can have many cars. We would have also unique transactionNumber so:
Client (model aggregate) > ClientRepository
Car (model aggregate) > CarRepository
Should then i then create aggregate such as:
public class ClientCar
{
int clientId;
int visitId;
int transactionNumber;
}
and ClientCarRepository?
No, don't use a different repository for each entity or aggregate. You are not applying DDD completely in your modelling. You have to focus on the Ubiquitous language. Let me explain.
Repositories are meant to be nothing more than serializers and de-serializers for your entities and aggregates. There shouldn't be an intentional 1-to-1 between them. In fact, most of the time you won't have the 1-to-1. In my code, I tend to scope repositories to the bounded context or to a subcontext.
Take a trivial example: A blogging application. I might have a repository that can persist a comment. Persisting the comment means saving the comment itself and updating User's comment count. The Save(Comment comment, Usr usr) method will make two calls to my persistence mechanism to update the individual Entities or Aggregates.
Repository, in the sense of domain driven design, is a life cycle management pattern. See chapter 6 of the "blue book".
It's purpose is to isolate from our application code the strategy we are using to store and retrieve aggregate roots. That's important, because the aggregate roots are the only parts of the domain code that our application code talks to directly.
From this, it follows that you don't need a repository for the client car relation unless it is the root of its own aggregate.
Figuring out whether this relation should be in its own aggregate or not is a matter of domain analysis -- you're going to have to dig into your specific domain to figure out the answer. For something like a car rental domain, I would guess that you'll want this relation, and the information associated with its life cycle, to be in a separate aggregate from the car or the customer. But I wouldn't feel confident in that guess until I had worked through a few edge cases with the domain experts.
Whether you treat an entity as aggregate root, thereby introduce a corresponding repository, depends on your domain or its ubiquitous language. One of the key indicators of aggregates is that they encapsulate important domain operations.
Hard to be precise without knowing your domain, however, in your example, Client seems to be a more natural candidate for an aggregate: a client may own new cars, get rid of a few, etc; the corresponding operations (i.e. adding cars or removing cars) fit naturally into client.
ClientCar (or ClientVisit), on the other hand, doesn't seem to have any purpose other than retrieving cars owned by a client. For this purpose, navigating the entity should suffice, no aggregate is necessary. Your Client repository may introduce a method for this purpose like the following:
public interface ClientRepository
{
Client findById(String clientId);
void store(Client client);
IList<Cars> carsOwnedBy(String clientId);
}
Then carsOwnedBy method implementation retrieves a Client and returns only the Cars associated with it.
I'm trying to get my head around DDD but I'm stuck.
This is how I setup my project:
Data Access Layer
-Entity models that map to the db
-Db connection stuff
-Repositories implementations
Domain Layer
-Models that represent the DAL entity models
-Repositories interfaces
Application Layer
-MVC application that uses Domain models
The first problem I see here is that the Domain models are exactly the same as the Entity models, and I have a serious problem with this: the entity models obviously have validation configured into them, things like "max length", "nullable", "required", etc. Now, to conform to what I understand is DDD, I can't directly use these models anywhere, except the DAL, so I created my domain layer. In the domain layer, I have all these validation rules duplicated for UI validation, and what's even worse, is that if I need to change a rule, I will have to change it in two places: the DAL and the Domain.
Example:
User Entity in DAL
Name (required)
Last name (required)
Email (required, maxlen 120)
Username (required, maxlen 120)
User Domain Model
Name (required)
Last name (required)
Email (required, maxlen 120)
Username (required, maxlen 120)
Another thing that I find very weird is that the repositories organization in this architecture.
Following what I read, I created a GenericRepository interface, and a UserRepository interface, which inherits the GenericRepository, all in the Domain layer.
I implemented the GenericRepository in the DAL, and the implementation creates a DAO for the type of the entity used to create the repository. So far, so good.
Then, I proceeded to implement the UserRepository, and here I have another problem: the UserRepository interface expects the Domain User model, and when I try to implement the interface in the DAL, I need to implement it using the Domain User model, which causes the DAO to be created for a Domain model, not a DAL model, and this doesn't make any sense. The only to fix it would be to reference the DAL in the Domain layer, which is wrong.
Domain Layer:
public interface IGenericRepository<TEntity>
{
TEntity FindById(TKey id);
}
public interface IUserRepository : IGenericRepository<Domain.User>
{
Task<User> FindByUserNameAsync(string userName);
}
DAL:
public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
{
protected DbContext ctx;
protected DbSet<Entity> dbSet;
public GenericRepository(DbContext context)
{
ctx = context;
dbSet = ctx.Set<TEntity>();
}
public virtual TEntity FindById(TKey id)
{
return dbSet.Find(id);
}
}
public class UserRepository : GenericRepository<Domain.Models.User>, IUserRepository
{
public UserRepository(DbContext context)
: base(context)
{
// THIS WILL CREATE A DAO FOR A DOMAIN MODEL
}
// rest of code...
}
Can anybody shed a light on what I'm missing from DDD?
Your question and your doubt against DDD makes sense, because you are approaching the subject from the code-point-of-view.
You seem to stuck at your "code duplication" and you are about to miss the bigger picture.
From wikipedia definition:
Domain-driven design (DDD) is an approach to software development for complex needs by connecting the implementation to an evolving model. The premise of domain-driven design is the following:
- placing the project's primary focus on the core domain and domain logic-
basing complex designs on a model of the domain-
initiating a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses particular domain problems.
If the only business logic that your model needs, is the validation of string fields then you might need another approach,other than DDD, to develop your application.
How to think about DDD:
DDD is a development philosophy (defined by Eric Evans) and has focus on development teams writing software for complex domains. These teams need clear boundaries because a change, that is to come in one model, should not affect the other's team model, progress etc (therefore you have your code duplication).
How not to think about DDD:
It is not a framework with predefined code applicable patterns.
Common problems for teams starting DDD:
Overemphasizing the importance of tactical patterns:
instead of solving your real business problem, focus on aggregate roots, value objects etc..
Focusing on code rather than the principles of DDD: the code should be the last iteration of the DDD process. The real work is understanding the business problem and try to find a solution that is simple to understand (take away the complexity of a problem).
More pitfalls as well as advice how to learn to apply DDD you can find in Patterns, Principles, and Practices of Domain-Driven Design
(example of pitfalls are taken from chapter 9 of this book)
I wonder how could I solve the following case : there are a form on website where manager input very big amount of data to Viewmodel and pass to server-side.
class CitizenRegistrationViewModel {
public string NationalPassportId { get;set; }
public string Name { get;set; }
public List<string> PreviousRegisteredOfficeCodes {get;set;}
// about 30 fields like strings, Booleans, HttpBasedFiles (pdf,jpg).
}
And the problem that in domain this data need to be logically separated and stored in different tables (classes in EF) like CitizensNationalPassportsTable, CitizensWorkingPlaceRecordsTable, etc. There are no complex class Citizen with properties like :
public class Citizen {
public ICollection<CitizensWorkingPlaceRecords> workingPlaces
// etc...
}
but this properties are separately stored in different tables with no one-to-one or one-to-many relations (no FK here) . The only NationalPassportId property could be used as navigation key (unique per user and all records related to user in different tables contains this key).
Should I write big amount of code to parse Viewmodel to domains models like :
public void CitizenRegistrationViewModelToDomainModel(CitizenRegistrationViewModel model){
CitizenNationalPassport passport = new CitizenNationalPassport(model.NationalPassportId);
CitizensWorkingPlaceRecord workplace = new CitizensWorkingPlaceRecord(model.PreviousRegisteredOfficeCodes, model.NationalPassportId);
// 12 extra objects need to create...
db.CitizenNationalPassports.Add(passport);
}
Or is there any more correct approach to handle this problem? I wanted to use AutoMapper, but is it the best solution?
I can't change business models' logic, as it is a legacy project.
You should have a set of classes that represents the data that the browser is exchanging with ASP.NET MVC. Let's name them for example, Input Models. In this classes you have metadata attributes, custom properties and many things that are relates with the exchange between browser and web server.
You should have another set of classes that represent your database structure, those are your Entity Framework POCO classes. Let's name them DB Models. It does not matter how POCO and fancy they are, they always map to tables and columns, so they are always tight to the DB structure.
You should have another set of classes that are your domain classes, the classes you use when operating objects in your business layer.These are binding/persistence/representation agnostic.
You should have a repository that knows how to persist a domain entity. In your case it will be a class that knows how to operate the DB models and the DbContext.
Then, when you get input from your browser, you bind that data to the input models and those are passed to the controller (this is done automatically by the DefaultModelBinder or you can use your own IModelBinder).
When you get an input model, you have to create a new domain entity using that data (in case that is an actual new entity). Once you have your domain object ready, you pass it to the repository to be saved.
The repository is responsible of knowing how to save the domain entity in the database, using the DB models.
In essence, the Controller or the business service instance you operate in the Controller's action context should be responsible of articulate the interaction between these elements without them knowing each others.
AutoMapper or an alternative could be used to automate the mapping from View model to Domain models, but this only makes sense if properties are named identical in View and Domain models. If this is not the case you'll end up writing mapping rules which doesn't help you. It just moves code from your current mapping classes to the AutoMapper configuration. So, if you're in a position to modify your viewmodels I'd go for AutoMapper or anything similar, if not I'd use what you currently have.
I am little bit confused about the problem. I have an entity Product that is represented in the database. It looks like POCO. Here is example (I use attributes instead of fluent api for simplicity).
public class Product
{
[Key]
public int Id { get; set; }
//other properties that have mapping to db
}
But now I want to avoid AnemicDomainModel anti-pattern
So I am going to fill the Product model with methods and properties, that do not have mapping to db, so I should use [Ignore].
public class Product
{
[Key]
public int Id { get; set; }
[Ignore]
public object FooProperty { get; set; }
//other properties that have mapping to db
//other properties and methods that do not have mapping to db
}
I think such a way spoils my model. In this article I've found acceptable workaround. Its idea is to separate Product (domain model) and ProductState (state of product that is stored in the database). So Product is wrapper for ProductState.
I really want to know the views of other developers. Thanks a lot for your answers.
I understood that my real question sounds something like that: "Should I separate Data model and domain model? Can I change EF entities from Anemic to Rich?"
To ensure persistence ignorance of your entities, I've found EF Fluent Mapping to be better than Data Annotations. The mappings are declared in an external file, thus normally your entity doesn't have to change if something in the persistence layer changes. However, there are still some things you can't map with EF.
Vaughn's "backing state object" solution you linked to is nice, but it is an extra layer of indirection which adds a fair amount of complexity to your application. It's a matter of personal taste, but I would use it only in cases when you absolutely need stuff in your entities that cannot be mapped directly because of EF shortcomings. It also plays well with an Event Sourcing approach.
The beauty of the Entity Framework is that it allows you to map your database tables to your domain model using mappings which can be defined using the Fluent API, therefore there is no need to have separate data entities. This is in comparison to its predecessor Linq To SQL where you'd map each table to an individual data entity.
Take the following example, for the paradigm of a Student and Course - a student can take many courses, and a course can have many students, therefore a many-to-many relationship in your database design. This would consist of three tables: Student, Course, StudentToCourse.
The EF will allow you to use Fluent API mappings to create the many collections on either side of the relationship without having the intermediate table (StudentToCourse) defined in your model (StudentToCourse has no existence in a DOMAIN MODEL), you would only need two classes in your domain, Student and Course. Whereas in LinqToSQL you'd have to define all three in your model as data entities and then create mappings between your data entities and domain model resulting in lots of plumbing work open to bugs.
The argument of the anaemic vs rich domain model should have little effect on your mapping between your model and database tables, but focuses on where you place the behaviour - in either the domain model or the service layer.
I was under the impression they are all basically the same. Are model objects also the same?
Right now, in my architecture, I have:
class Person
{
public string PersonId;
public string Name;
public string Email;
public static bool IsValidName() { /* logic here */ }
public static bool IsValidEmail() { /* logic here */ }
}
class PersonService
{
private PersonRepository pRepository;
PersonService()
{
pRepository = new PersonRepository();
}
public bool IsExistingEmail(string email)
{
//calls repo method to see if email is in db
}
public Person GetPerson(email)
{
return pRepository.Get(email);
}
public void SavePerson(Person p)
{
if (Person.IsValidEmail(p.Email) && !IsExistingEmail(p.Email)
{
pRepository.Save(p);
}
}
}
class PersonRepository
{
public void Save(Person p)
{
//save to db
}
public Person Get(string email)
{
//get from db
}
public bool IsExistingEmail(string email)
{
//see if email in db
}
}
So which of the above classes are POCO, Domain Object, Model object, entity?
My (non-standard) Layman definitions
POCO - Plain Old %Insert_Your_Language% Object. A type with no logic in it. It just stores data in memory. You'd usually see just auto properties in it, sometimes fields and constructors.
Domain object an instance of a class that is related to your domain. I would probably exclude any satellite or utility objects from domain object, e.g. in most cases, domain objects do not include things like logging, formatting, serialisation, encryption etc - unless you are specifically building a product to log, serialise, format or encrypt respectively.
Model object I think is the same as Domain object. Folks tend to use this interchangeably (I can be wrong)
Entity a class that has id
Repository a class that speaks to a data storage from one side (e.g. a database, a data service or ORM) and to the service, UI, business layer or any other requesting body. It usually hides away all the data-related stuff (like replication, connection pooling, key constraints, transactions etc) and makes it simple to just work with data
Service software that provides some functionality usually via public API. Depending on the layer, it can be for example a RESTful self-contained container, or class that allows you to find a particular instance of needed type.
Original answer
These are terms that are largely used in (Distributed) Domain Driven Design. They are not the same. The term model Object can be used as a synonym to the domain object.
Domain Objects. Objects from the business specific area that represent something meaningful to the domain expert. Domain objects are mostly represented by entities and value objects. Generaly speaking, most objects that live in domain layer contribute to the model and are domain objects.
Entity. An object fundamentally defined not by its attributes, but by a thread of continuity and identity. (Meaning it must have Id)
POCO. A simple object without complicated logic, usually it has just a few properties and is used with ORM or as a Data Transfer Object
class Person - Entity and POCO, instance of this class is Domain Object
class PersonService - Service
class PersonRepository - Repository
basically it comes down to internal logic
Domain objects have internal domain logic for things like validation, etc.
Model is basically a light Domain object, they know about the data they hold but nothing really about how it's going to be used
Entities hold data and have some internal knowledge of where it came from, and where it's going to be saved, updated, etc
POCO holds data and may have some internal knowledge about it's self, things like what is the total value of all the items in a property collection
DTO is the simplest item of all, it just holds data and has no logic
They are all basically used for the same thing, it's just how smart you want them to be
according to your code sample
The Person class would be a domain object or a model, the other 2 are a service and a repository. Domain objects, Pocos, models, dtos, etc. are used like messages, passed from one layer to the next, a service class like PersonService is a layer in the application and the same with the Repository class like PersonRepository. for a good over view take look at http://bob-the-janitor.blogspot.com/2009/07/n-tier-design-revisit-part-1-over-view.html in this case it's talking about using a data entity which is basically a dto
It's more of a connotation of function; a domain object is something that is specific to your logic implementation and might be more complex than a simple POCO; an entity has a connotation to represent something (usually in reference to a persistence medium), and a POCO is just a quick identifier for a class. A model is just a term used to represent an object (usually containing state and usually dealing with the UI or DB).
It's not that there is any functional difference, they're just different terms to more closely describe something. Like the difference between race car, truck, and family sedan. All are automobiles, but each term is more descriptive.
There are already good explainations of Domain and Model in the answers above.
In a Database-Context Entity means Item in a Entity Relationship Model ERD. (i.e. a Row in a Table)
In the Microsoft-Dotnet-EntityFramework-World Entity means an Object that can be loaded from and saved to a database using a Data(Base)Context. Usually an Entity cannot exist without its Data(Base)Context. (Unit-) Testing the business functionality of these classes is difficuilt.
Pocos (Plain Old CommonRuntime Objects) can exist without the PersistenceFramework (EntityFramework or NHibernate) thus they are much easier to test.
The word poco is the adaptaion of pojo (plain old java object) that were created in the java world for the same reason.
A domain object is an entity in the domain layer of your application, eg. an Address class. "Model" means the same thing - an entity in the "Domain Model".
A POCO (plain old CLR object) is an object that has no behaviour (methods) defined, and only contains data (properties). POCO's are generally used as DTOs (data transport objects) to carry data between layers, and the data is then commonly used to populate a domain object/entity.