Data Entities, Domain entities and the Repositories in DDD - c#

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)

Related

According to DDD do i need additional repository and model

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.

DTO vs. Domain Model, project organization

I have a project with a repository, a service layer, using EF6 and code-first POCOs. In the CustomerRepository, I am doing several projection queries that return objects.
I understand that the code-first POCO's are what would be considered "Domain Models", but if I were to do a projection query into a different model, what is that model considered? An example of this would be the CustomerOrderStats. Is that still a Domain Model, or should that be considered a DTO model?
Example
Object returned from Repository:
public class CustomerOrderStats
{
public string Name { get; set; }
public int Count { get; set; }
}
Query in the Repository
public CustomerOrderStats GetCustomerOrderStats(Guid customerGuid)
{
return customers
.Where(c => c.Guid == customerGuid)
.Select(new CustomerOrderStats
{
Name = c.Name,
Count = c.Orders.Count()
};
}
It could be either one, really. The definition of a model vs. a DTO isn't really a matter of how you organize any given framework, but rather what that object represents in the domain. If it has rich functionality or business logic or is an active part of the actual business process, it's probably a model. If, on the other hand, it's just a container of properties to move values from one place to another, it's probably a DTO.
The key here is whether the object is an active part of the business process. And a good rule of thumb here is often the name of the object.
Is it a name that non-technical business team members understand?
Is it a term they use to describe what the business does? (Even a very small part of the business)
Does it carry a meaning in the industry in general?
A DTO is generally something that exists for purely technical reasons. Component A needs to send data to Component B, but that operation is a technical one and not a business one. Data just needs to be, well, transferred. As a piece of the system, it's essentially built "from the bottom up" because it satisfies a low-level technical need.
A model describes a part of the business. It could be an element on a chart which defines the business process in non-technical terms, or an encapsulation of a business concept. As a piece of the system, it's essentially built "from the top down" because it is described generally by the business and then implemented specifically to meet that need.

Business logic layer needs its own models or not

I'm doing 3 tier application using asp.net mvc and I want to do everything as recommended.
So I've done MvcSample.Bll for business logic, MvcSample.Data for data and MvcSample.Web for website.
In Data I've my edmx file (I'm using database first approach) and my repositories. And in Bll I'm doing services which will called in web.
So my question is that:
Should I write other models in Bll or use that ones which are generated in edmx file?
It heavily depends on the type of problem that your application is trying to solve.
From my experience, it is very rare that the business logic returns model objects directly from Entity Framework. Also, accepting these as arguments may not be the best idea.
Entity Framework model represents your relational database. Because of that, its definition contains many things that your business logic should not expose, for example navigation properties, computed properties etc. When accepting your model object as an argument, you may notice that many properties are not used by the particular business logic method. In many cases it confuses the developer and is the source of bugs.
All in all, if your application is a quick prototype, proof of concept or a simple CRUD software than it might be sufficient to use EF model classes. However, from practical point of view consider bespoke business logic model/dto classes.
From my point of view you need another model for your Bll.
That would encapsulate your Bllcompletely.
I think there is no right or wrong answer for your question.
In my experience, I used both.
Let's see at below example:
I have an User table
public class User
{
public int Id{get;set;}
public string First_Name{get;set;}
public string Last_Name{get;set;}
public int Age{get;set;}
public string Password{get;set;} //let's use this for demonstration
}
I have a Method call DisplayAll() in Bll. This method should list down all users in my database by Full Names (FirstName + LastName) and their Ages.
I should not return User class because it will expose the Password, but rather, I create a new Class UserDto
public class UserDto
{
public string FullName{get;set;}
public int Age{get;set;}
}
So here is my DisplayAll():
public List<UserDto> DisplayAll()
{
List<UserDto> result = ctx.User //my DbContext
.Select(x => new UserDto()
{
FullName = x.First_Name + " " +Last_Name,
Age = x.Age
}
return result;
}
So as you can see, my method DisplayAll() uses both User and UserDto
My approach will be
MvcSample.Data
-- Model Classes
-- EDMX attach to model
MvcSample.Bll
-- Model Inheriting MvcSample.Data.Model
-- Business Logic Class - Using MvcSample.Bll.Model
MvcSample.Web
-- Controller using MvcSample.Bll.Model
It depends on your view about software design and how you want to take advantage of it. by separating BLL model, you will have your freedom to put story specific validation and calculation. By using only DLL model, it is sometimes tough as it is going to take effect in DB.
You can use 3 tier architecture in asp.net in this way
MvcSample.BLL - business logic layer
MvcSample.DAL - Data access layer
MvcSample.Domain - Domain layer
MvcSample.web - website
All your repository classes are including in .BLL layer.That means your logics are stored here.
Usually .DAL is used for storing .edmx classes. .Domain is using for recreate database objects that are useful for server side.That means if you are passing a json object from client to server,Then that object should be create on the server side.So those classes can be implement in the .domain

In what layer in DDD are classes declared as Aggregates roots?

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.

Where to keep business logics in MVC architecture?

In my company we have recently started developing MVC application. Our task is to write the business logic layer and in future it should be with less maintenance.
We have couple of web services to add/update/delete user information.
Now we have to add the business logics like:
If Field1 on the page is 'xxxx' then field2 should be in the range of 1000 to 2000
If field3 is some department then field4 should be only in some sub departments.
So we have to design the layer so that in future our admin(who don't have programming knowledge) can go in and change the logics so that it will work. Please give me some suggestions.
So far what i have got is: Write all these conditions in Model and validate them when user click save button.
Thanks in advance.
Business logic should kept inside the model. You should aim to have a big Model and a small controller.
You may find this interesting to read this.
Also check Where does the “business logic layer” fit in to an MVC application?
Keep it in a separate assembly which doesn't know about your ui layer. Your models can go here and enforce business rules. I personally like building the business layer on top of the Csla framework, which lets you build rich models with powerful rules. Its geared toward ntier development but I believe its also compatible with ddd.
When you are talking about layering, your Business layer should be separated from Presentation Layer. ASP.NET MVC is a presentation technology; so, your Business Layer would be in different assembly. Additionally, your Business Model wouldn't be used directly in your views; you can use ViewModel to validate user input and when everything was OK, transfer ViewModel data into Business Entity.
If you are interested to obtain more information about layering in enterprise level applications I recommend you Microsoft Spain - Domain Oriented N-Layered .NET 4.0 Sample App.
I like to use Entity Framework and Fluent Validation to create a domain layer that contains both models and validators. The set up looks like this:
public abstract class DomainEntity
{
private IValidator validator;
protected DomainEntity(IValidator validator)
{
this.validator = validator;
}
public bool IsValid
{
get { return validator.IsValid; }
}
public ValidationResult Validate()
{
return validator.Validate();
}
}
public class Person : DomainEntity
{
public int Id { get; set; }
public string Name { get; set; }
public Person() : base(new PersonValidator())
}
public class PersonValidator() : AbstractValidator<Person>
{
public PersonValidator()
{
... validation logic
}
}
Using this set up, my models and validators live in the same layer but I don't muddy up my model classes with busines logic.
Business Logic should be in Model layer, and I don't think that anyone without programming knowledge can change business logic, he must have basic programming knowledge at least
You can use DataAnnotations to do this - in fact data annotations enable more than just server side enforcing of model validity. They can also give hints to Entity Framework and client side scripts in order for database/client side validation, and add metadata to methods and properties that MVC can inspect
e.g. for a model:
class PersonDetailsModel
{
[Required("Please enter a name")] // Don't allow no value, show the message when the rule is broken (if client side validation is enabled it shows when you tab off the control)
[DisplayName("Full Name")] // Hint for MVC - show this when using the helper methods e.g. in MVC4 Razor syntax #Html.LabelFor(model => model.Name)
public string Name { get; set; }
}
And yes, keep as much business logic in the business layer (model). Cross-cutting concerns aside, your components should be as loosely coupled as possible. This way there is a central place to make changes, your code is more testable and maintainable and it also helps you to keep your programming consistent (which helps newbies to your project get up to speed quickly)
If you have more complex rules, you can write EF validators.
http://msdn.microsoft.com/en-gb/data/gg193959.aspx
If you aren't using Entity Framework then you might want to consider it - if you are using another ORM then obviously use the tools that support that. If you aren't using an ORM, then there are alternatives but you'll have to write some plumbing code

Categories