Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I used to deal with simple apps that have Service Layer containing all of the business logic. In Domain Driven Design it's common to keep business logic in a rich model.
Watched a tutorial by Pluralsight in which they mention Repositories and noticed that a repo normally contains basic CRUD operations (create, update, fetch & remove entity). Nothing much was explained with regard to Entity Framework.
Entity Framework 6 & Entity Framework Core already provide Repository/UoW out of the box. I'm wondering if we can omit creating Repository Layer in this case?
So, how I imagine the app without a separate Repository layer...
My understanding is:
For example we have Customer model as an Aggregate Root (rich domain model). And that model has one-to-many relation ICollection<Payment> Payments. Plus, according to DDD - we keep our logic inside the model - so we have MakePayment method.
The code will be as follows:
public class Customer
{
public virtual ICollection<Payment> Payments { get; set; }
// ... other properties/collections
public void MakePayment(decimal amount)
{
this.Payments.Add(new Payment() { Amount = amount });
}
}
With Entity Framework we can eagerly load the entire tree with the result Customer already has all their Payments mapped.
(say, we deal with an ASP.NET WebAPI app)
So, in order to make a payment, I imagine, we do the following:
in our controller / service we fetch a customer (for example by id)
then follows the code customer.MakePayment(10);
after that we call dbContext.SaveChanges() method
DbContext tracks the changes and stores the payment - Bingo!
Is my understanding correct?
Regarding Service Layer:
Would it be okay to have Service Layer with DDD in such a web app?
I still think keeping the code in controller isn't necessarily the right thing to do (even with DDD) as long as e.g. part of functionality MAY BE required in a WPF app - so we can use Service Layer with it.
Seems like the most optimal approach, doesn't it?
I'm wondering if we can omit creating Repository Layer in this case?
As explained in first paragraph here, consider using Generic Repository (DbSet) directly. Avoid creating additional layer of Repository.
Is my understanding correct?
IMO, your understanding is correct if you have correctly implemented Unit of Work (Session Per Request as you explained in question) pattern. That is how it should work.
Would it be okay to have Service Layer with DDD in such a web app?
With DDD, your domain model includes the related logic. But, there is always a logic that does not belong to any domain model. That logic generally consumed in Services. So yes, you may still need Services with DDD. Just that, it will not contain all of your logic as most of it will be in models.
With DDD, consider using CQRS. With CQRS, you separate reads and writes to your data store. Repository is optional in this case. As suggested above, you can use Generic Repository exposed by ORM.
I'm wondering if we can omit creating Repository Layer in this case?
In my opinion, you cannot omit the Repository Layer. Generally, Repository is responsible for Save and Rebuild the Aggregate Root, and your domain entity is not your database entity. EF entity is not your domain entity.
Would it be okay to have Service Layer with DDD in such a web app?
Of course you can keep your Service Layer, actually, you can call it Application Layer in DDD, but you need care what should be include in this layer.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
Can someone explain?
I'm trying to convert my wpf app mvvm into different layers (reading ddd). I have some small confusions
Presentation Layer (WPF, WEB, API) (ok.. this I know )
Entity Model (I know is the class that represent database table e.g
customer {id,name,surname,phone} from Entity Framework
but the following confuse me
Domain model (is the class that represent sql table columns? e.g
customer {Id,Name,Surname,phone} or the class that make sense for my
application e.g Customer {ID,FullName,Balance}
Where domain model lives? in which layer (seperate dll ?, in service
layer ? or in data repository dll)
DTO (Data Transfered object) is it the same as domain model?
Service Layer (is it a separate dll?)
Business Layer (many times i see the word business layer, some
refer it as service layer) what is it actually? is it the same? is it
a different class? a different dll (layer) that has it's own
responsibility apart from service layer?
Data Repository (question is, if service layer or business layer should be implement in the same layer that repository lives)
with all the above i have make sample application trying to understand where each one goes.
STEPS I FOLLOW
I have sucesfully understant the data repository. a simple interface
with CRUD and or complex queryies
I create a IService that implements and inherited from reposiroty
Now in wpf i have to reference the service dll, but wpf needs not only service dll but also repository dll because service layer is using it.
My Question on this is. Is It normal? shouldn't service be independent?
Should Service Layer used it's own models? and convert data repository models to service models? therefor wpf will not need reference to repository? ( but if so.. isn't duplicate work?)
Domain model
It depends on which pattern you want implement: rich domain model or anemic.
Some refs:
DDD vs Anemic domain models
Anemic domain model
Rich vs anemic domain model
In two words:
rich domain model - it's a model, when business logic incapsulated at your business object (model).
anemic domain model - it's a model, when business logic implemented at service layer.
If you talks about services, it's not pure DDD, it's anemic.
Fowler told that anemic is an anti-pattern, but it's used a quite often. The main problem of rich domain model, that you need a lot of experience to realise right way to implement it.
I think in your case you can use entities as domain objects.
Where domain model lives?
If you trying to implement domain model, it requires a organised structure of you solution.
Usually it contains next projects:
*.Domain - for domain objects
*.Application - for you business logic, if we talk about anemic model
*.Dto or *.Contract - for dto's or another objects that can be use at outer scope of your application (for services interactions, dto's, etc.)
*.Persistence - for data layer
Dto(Contract) is placed in another project in case reusing items implemented at them.
Where * is your project name.
DTO
Dto depends on your needs.
I recommend declare dto's for each purpose, but if you don't want, you still can return domain object (but some people can say, that it's bad practice).
As I told previously you can place dto's to *.Dto or *.Contract projects
Service Layer and Business Layer
Implement at your *.Application
Data Repository
Usually you prefer to declare Data Repository interfaces at *.Domain or *.Application and implementation at *.Persistence. It allows you use interfaces and don't care about realisation.
Is it normal? shouldn't service be independent?
Best practice it's when service depends just on your *.Domain assembly.
Should Service Layer used it's own models? and convert data repository models to service models? therefor wpf will not need reference to repository? ( but if so.. isn't duplicate work?)
You services should work with domain models, and return dto's when it needs. One of general ideas of ddd, that you have common model for all operations. So it's good if you can return your domain model from repository.
Setup
.NET, C#, WebAPI, Entity Framework using code-first migration
Summary
I am designing a .NET solution using the repository pattern. The repository sits at the bottom of my stack and currently contains my domain models. I have layers on top of the repository (e.g. BLL) and finally I have an API layer on the top of the stack which contains my RESTful API endpoints.
Here is a simplified pseudo-diagram of the current solution stack:
-API
-BLL
-REPOSITORY
Problem
In the API layer, I would like to use .NET's ModelState validation inside each of the controller's endpoints. Problem is, this requires that the API layer have a reference to (ergo knowledge of) the Repository layer. Wouldn't this be a leaky abstraction?
It seems like the use of Data Transfer Objects would be the solution, but this almost seems silly since they would be essentially identical to the Domain Models in the Repository. That doesn't allow for much abstraction.
An alternative?
I am kicking around the idea of adding a separate project to contain the Domain Models, and then allow the API, BLL, and Repository to all reference that project. Any reason this shouldn't be done?
The only downside I see here is that now three of the projects in my solution will need access to the database:
API (because I have set up OWIN authentication in the API)
Repository
DomainModels (because I am using code-first migration)
Any help is appreciated.
The repository sits at the bottom of my stack and currently contains my domain models
That's your problem, the repository uses domain entities, but it doesn't contain them. The repo is part of the persistence, your domain model should be part of the Domain layer. The repo interface is part of the Domain too.
ALso, you domain model should be different (as a concept) than you persistence model i.e the pocos you're using with EF to do CRUD stuff. The domain objects are modelled according to the business view, the persistence pocos are designed with db usage (store/easily queryable) in mind.
The domain layer should be at the core, persistence and application services should use it i.e depend on it. You can take a look at the onion architecture or business components/ vertical slices (which is a more advanced approach IMO)
I read many documentation about CRUD and I still don't understand what exactly should be CRUDable! It seems most of people are talking about CRUD entities but they architecture doesn't show any Create, Read, Update or Delete methods in their entities. They implements these CRUD operations in a separate class. I like to call these kind of classes CRUD controllers.
Is it correct to create POCO entites with CRUD controller? What should be CRUD?
My take is that you should have a repository which performs the CRUD operations.
Then a controller should call the appropriate CRUD method in the repository, possibly via an intermediate service layer.
Read more about the repository pattern here and here.
These classes are usually called repositories. A repository provides access to your entities with means of adding, updating, removing and retrieving one or more entities. So the repository Creates, Reads, Updates and Deletes (CRUD).
When using a database your POCO is normally an object your database entity is converted into, e.g. with AutoMapper in the repository.
In architectural terms, CRUD means that you have entities without business rules. This entities, have, at most, some simple validations. When you have this kind of entity you speak of CRUD because you can modify the data without worrying about anything else (but validations). This can be used for example for maintaining a list of contacts: name + phone no. + address: at most you can validate that the name is not empty, the phone no. is valid, and the address is valid. But there are no business rules in there.
If there are involved business rules, you should avoid using CRUD to make sure that the business rules are respected. For example you should not allow CRUD for an order detail, because there are business rules involved: perhaps you cannot change an order detail if the order is already paid or sent, or confirmed to the customer. Besides the total order amount depends on the order details. In this case you should use the order with its details as a whole, and read / write / update it all at once. (In DDD this is called "aggregate").
Speaking about CRUD is not a question of how you implement it (repository, ORM like DbContext or NHibernate, or wichever you want to use), but a more philosophical question.
Implementing CRUD is much faster than implementing any other architecture which involves business rules (for example DDD). If you can use CRUD for an entity, is advisable to use it, but not in the other cases.
As to your comment:
but they architecture doesn't show any Create, Read, Update or Delete methods in their entities
That's natural... you can do CRUD with EF for example, without explicitly declaring the CRUD methods. Create an entity in the context, or remove it or modify it and the CRUD operations will be implicitly executed on the SaveChanges.
This question already has answers here:
In separate data access & business logic layer, can I use Entity framework classes in business layer?
(3 answers)
Closed 9 years ago.
If EF model(s) are contained in a separate assembly and referenced/used by the Data Access Layer for all DB operations, is it acceptable to also reference that same assembly with EF model(s) from the Business Intelligence layer in order to simplify the data transfer from DAL to BI layer?
This would allow for elimination of DTO objects or in my case Tuples I use to transport the data from DAL to BI since the DAL could just return EF objects that BI would already "know" about. The question is if this would be frowned upon from the architecture stand point as something that is going against the separation of concerns or some other rule of good software design?
This is why I don't like EF. In order to hide the fact you're using a DB, you have to hide the fact that EF is generating all these nice lovely classes for you by making new ones.
Since EF classes have navigable relations, and those relations are only viable while the entities are attached to a context, you cannot, for example, shoot them across the wire to an API client.
Well, you could, but they would be annoyed whenever you fail to, for example, include related records for a Get call.
Personally, I'd leave the leaky abstraction behind. If not completely (cough dapper cough) then hide your shame in the DL.
I know there are a lot of threads here already on the repository pattern but somehow I feel my question is a little different. Maybe because yesterday was the first time I heard of the word POCO.
My question is this--usually, I have add and save methods in my business entities. Say I am writing a Q/A site, and I have the following entities: questions, answers, and comments. If I wanted to use the repository pattern, I basically need to keep only the properties in my business entities (example, Question), and move my operations to the repository class (example, QuestionRepository), right? If this is true, does POCO mean a business entity with just the properties?
I'm using Entity Framework 4.0, which created my entities in the edmx code behind. If I wanted to use the repository pattern with this, there is no need to write my own business entities (Question, Answer, etc) since they are already generated by EF, right? All I'd need is the Repository to do CRUD? And I'll be having three repositories for this example, one for each entity?
First an observation about Asp.net MVC project template
I must say that there is a tiny misunderstanding with Visual Studio's Asp.net MVC project template. And that is the Model folder. People not knowing MVC pattern would automatically relate this to data model and not MVC application/presentation model. This is fine for simple applications where we don't distinguish between the two but not for anything else.
Let's continue to my answer
When I write business level applications I separate my solution into 4 projects (at least):
presentation tier - Asp.net MVC application but I remove Model folder and have all my views as strong type views to avoid magic strings as much as possible
service tier - business logic processes
data tier - data model ie. EF4 and repositories that access this model
objects tier - this project actually has POCOs that are used for inter-layer communication and any interfaces used by various layers (think of IoC)
My request process usually looks very clean and works this way:
When a request is made my Asp.net MVC controller action validates data (POCO objects), does whatever is necessary for the presentation tier before calling into services.
Service is called that does whatever business process logic requires and normally calls repository to do something with data.
Repository manipulates data in the data model and then creates POCOs from results that will be returned to service layer.
Service layer receives POCOs does additional logic if needed and returns them back to presentation.
Presentation (controller) decides which view to display and provides model for that particular view and returns it. Of course instead of a view it can be any other result as well.
Advantage of using separate MVC model classes in Objects project (you couldn't put them in the Model folder because of circular project reference) is that I can have presentation optimised classes. Or better said: I have business process centric interface instead of data centric.
Let's explain this with an example: Take for instance user registration view. It can't be strong typed to data model's User entity. Why? Because it has two inputs for password. So I can have an application/presentation model class called UserRegistration even though there's nothing similar in data model. Its validation works completely differently compared to data model's User entity. If I'd have my user registration done without strong type I'd have to make my controller action with all parameters of every single field. These wouldn't be automatically validated which would mean that I can have a larger bug surface. Someone might hurry into writing code but forget about certain aspects of validation.
Strong type views returning strong types back at server are the safest way of getting rid of all kinds of obscure bugs that are usually discovered by users especially if you don't do any methodical testing on your project (which is somewhere between 75-90% chance).
I was in a very similar place as the OP sometime ago, so I'll expand on Roberts answer with some code of how I structured my asp.net mvc app after learning about the repository pattern.
So your project is QandA
You'll have a class library project called QandA.data, here is where you will create your edmx file and all your entity framework classes. Then you have a repository for each entity like this:
public interface IRepository<T>
{
T Save(T entity);
void Delete(T entity);
IQueryable<T> GetAll();
T GetById(int id);
}
You could then have either a factory or use Dependency Injection to get the actually repositories. So:
class QuestionRepo : IRepository<Question>
{
//call xxxEntites and get/save/delete yourentities here.
}
static class RepositoryFactory
{
public static IRepository<Question> GetQuestionRepo()
{
return new QuestionRepo();
}
}
Then down in your calling code (in your asp.net project) you have
IRepository<Question> qRepo = RepositoryFactory.GetQuestionRepo();
Question q = qRepo.GetById(1);
Now the advantage of doing the above is, your calling code has no idea how the entities are coming through, so you could create a mock repository to test your app out.
static class RepositoryFactory
{
public static IRepository<Question> GetQuestionRepo()
{
return new FakeQuestionRepo();
//create your own fake repo with some fixed fake data.
}
}
Now you're calling code does not change at all if you throw it a fake or real repository.
Also, what robert talks about in his question is a ViewModel. So you would not make a strongly typed page of type Question. So you have
class QuestionForm
{
public string Title
public string QuestionContent
}
You're page is going to be of type QuestionForm but in your create controller, you will take the data from the question form, fill it in your Question entity and then send it off via the repository.
[HttpPost]
public ActionResult Create(QuestionForm quesfrm)
{
IRepository<Question> qRepo = RepositoryFactory.GetQuestionRepo();
Question ques = new Question {
AskedDate = DateTime.Now,
Title = quesfrm.Title,
Content = QuestionContent
}
qRepo.Save(ques);
}
Robert mentions one of the reasons why you would do this, there are a few other reasons and you can read up more on view models on SO. Also check out the code for nerddinner
You may want to see these SO questions:
Should repositories implement IQueryable<T>?
Repository pattern: One repository class for each entity?
I hope it helped.
Your POCO objects would still have methods on them for operations, but those operations would pertain to the business concerns of the entity not the persistence concerns(CRUD). If there are no business operations on your entites, then yes they will be just properties.
You wouldn't need to write your pocos from scratch if you are generating them but you may want to extend them with partial classes for business operations and non-persistent or calculated properties.
You could have a single repository class or a repository for each entity.