Architecture Design
Looking for some suggestions for a new architecture that I am putting together.
Tools to use:
MVC 4 (If you have an example for MVC 3 it would suffice)
Entity Framework 4.1 (EF)
Repository Pattern
Unit of Work
POCO’s (T4 auto generated)
WCF (For CRUD functions. Retrieve data using concrete service classes)
Dependency Injection (Ninject)
Mocking (Moq)
Any other good tools let me know.
Firm on using EF for ORM with NHibernate being a second go to if EF proves unworthy.
What I have done so far
1) Presentation Project (MVC4, DI For services, Service Channel setup, View Models) -> references Domain Project (2)
2) Domain Project (POCO Entities, Domain Objects, Service Interface) -> References Business Project (3)
3) Business Project (WCF Service, Concrete Service Classes, Unit of Work) -> References Data Project(4)
4) Data Project (EF, Context + .edmx, Repositories and their interfaces) -> Looks at database
Question 1: Is this a good project breakdown?
Question 2: Is this a good place to put any of the mentioned items in the parentheses?
Question 3: Is there anything that should be somewhere that I have entirely left out?
A few side notes:
We have large record sets that we retrieve that easily exceed 100,000 records. Rather than going through a WCF service we are just calling a concrete service class that will increase performance. We topped out the max message size plus it took twice as long to retrieve records through WCF.
Question 4: Is there a better method to go about doing this? Performance is key. Reusability is not
Domain objects have a single attribute which is whatever POCO that it corresponds to. Example: I have a domain object called “Order”. It has a single attribute of “OrderPOCO” which holds all of the attributes. The domain object then has validation methods and references the necessary CRUD functions.
Question 5: Where should complex validation such as “does this record already exist” be placed? Can it just be done in the service itself?
Question 6: Are Domain object even necessary? Most other examples don’t have domain models if they are using POCO’s from what I can tell. Just a little confused on the idea.
Sorry this is very long. Any answer will be greatly appreciated but a comprehensive answer will be exponentially more helpful. We can pick tools to do different things but making them work together correctly is the hard part.
Criticism welcome!
Thank you all
Question 1, 2 and 3:
I've often seen architecture layouts containing only three layers. But if you want to keep your Domain Project layer and Business Project layer seperated and decoupled, so you can change one without affecting the other you should of course keep them in seperate assemblies. However POCO entities, unit of work and concrete service implementations are often very closely related to the domain and to the business rules of your application, so you could consider merging these two layers into one assembly.
I would move the reposiroty interfaces up in the businnes layer, remove the reference from busines layer to data layer, and have the UI layer reference the data layer instead. The UI layer then constructor injects the concrete repostiories into the domain/business layer. This keeps your domain/business layer clean of references to the technology dependent data assembly.
Question 4:
If performance is important, I would just call the concrete service classes.
Question 5:
I'm not sure what you mean by "complex validation".
Question 6:
EF can auto-generate the POCOs for you and place them in another assembly than the .edmx. See this article. This way your POCOs only depend on the T4 template and are not hard coupled to the EF.
Related
I'm aware that copying entity classes and properties into DTOs is considered anti-pattern, so by Exposed domain model pattern the same #Entity can be used as both database entity class, and DTO for service and MVC layer. (see here https://codereview.stackexchange.com/questions/93511/data-transfer-objects-vs-entities-in-java-rest-server-application)
But suppose we have microservice architecture where the same set of properties is used as entity in one project with persistence, and as DTO in another project which uses the first one as a service. What's the proposed pattern in such a situation?
Because the second project doesn't need #Entity related functionality, and if we put that class in shared library, it will be tied unnecessary to JPA specific APIs and libraries. And the alternative is to again use separate DTO classes anti-pattern.
When your requirements for a DTO model exactly match your entity model you are either in a very early stage of the project or very lucky that you just have a simple model. If your model is very simple, then DTOs won't give you many immediate benefits.
At some point, the requirements for the DTO model and the entity model will diverge though. Imagine you add some audit aspects, statistics or denormalization to your entity/persistence model. That kind of data is usually never exposed via DTOs directly, so you will need to split the models. It is also often the case that the main driver for DTOs is the fact that you don't need all the data all the time. If you display objects in e.g. a dropdown you only need a label and the object id, so why would you load the whole entity state for such a use case?
The fact that you have annotations on your DTO models shouldn't bother you that much, what is the alternative? An XML-like mapping? Manual object wiring?
If your model is used by third parties directly, you could use a subclassing i.e. keep the main model free of annotations and have annotated subclasses in your project that extend the main model.
Since implementing a DTO approach correctly, I created Blaze-Persistence Entity Views which will not only simplify the way you define DTOs, but it will also improve the performance of your queries.
If you are interested, I even have an example for an external model that uses entity view subclasses to keep the main model clean.
Thank you for the answers, but emphasize in the question is on microservice (MS) architecture and reusing defined entity POJOs from one MS in another as POJOs. From what I've read on microservices it's closely related to another question - should MSs share any common functionality and classes at all, or be completely independent? It seems there is no definite agreement on it, and also no definite answer, or widely accepted pattern, to this.
From my recent experience here is what I adopted, and it works well so far.
Have common functionality across MSs - yes, in form of a commons project added as dependency to all MSs, with its dependencies set as optional. Share entity classes (expose them in commons) - no.
The main reason is that entity classes are closely related to data store for particular MS. And as the established rule is that MSs shouldn't share data stores, then it makes sense not to share entity classes for those data stores. It helps MSs to be more independent, and freedom to manage their data store in their own way. It means some more typing to add additional DTO classes and conversion between them, but it's a trade-off worth taking to retain MS independence. Reasons Christian Beikov and Maksim Gumerov mentioned apply as well.
What we do share (put in commons) are some common functionality and helper classes (for cloud, discovery, error handling, rest and json configuration...), and pure DTOs, where T is transfer between MSs (rest entities or message payloads).
I am working on a Web Application using ASP.Net MVC 4 3-Tier Architecture and I am stuck at certain points. I know here exist similar threads but none were clear enough. I have already created the needed layers which are UI(MVC4 project), BLL- Business Logic Layer(library class), BOL- Business Object Layer(library class that contains ADO.net) and DAL- Data Access Layer (library class).
Layer dependencies are as follows:
UI depends on BOL and BLL
BLL depends on BOL and DAL
DAL depends on BOL
I want you to correct me if I am wrong in the following. The BOL is the master reference layer which exchanges raw dB records with DAL then sends them to BLL which is responsible for any logical computations then gets the updated records and sends them to the controller in the UI.
Knowing the above,
Where should we place the CRUD functions?
Where and why should we create a class for declaring (plus set and get) the useful database fields?
What exactly should we put in the ViewModel folder; in other words since we have already defined the variables in the previous step and in the Entity then does it add any value to keep the Model folder?
Thank you in advance.
Can't be unambiguously correct answers on these issues, so any answer should be evaluated simply as an opinion. Here are my answers:
Where should we place the CRUD functions? CRUD is a frequent pattern at different levels. Hi-level Repository provides similar methods, as a low-level Table Gateway.
Where and why should we create a class for declaring (plus set and get) the useful database fields? These classes are usually simple Data Transfer Objects (DTO) or slightly more complicated Active Records. In accordance with the Dependency Inversion Principle the interface for these classes should provide the Business Logic Layer, and implementation should provide the Data Access Layer. Since DTO is very simple classes, they can be provided "as is" without interface/implementation separation.
What exactly should we put in the ViewModel folder; in other words since we have already defined the variables in the previous step and in the Entity then does it add any value to keep the Model folder? In theory entities should be our models; but in practice it's often not the case. F.e. in ASP.NET MVC models should provide not only the value of drop-down field, but also all possible values; so it requires the separate model class.
The result may be that you have three or four very similar classes at different levels of the application. Of course, it's not very good, so Aspect Programming may be applied in this case.
I have started using Entity Framework Code First for the first time and am impressed by the way in which our greenfield application is being built around the domain rather than around the relational database tables (which is how I have worked for years).
So, we are building entities in C# that are being reflected in the database every time we do a new migration.
My question is this: should these same entities (i.e. designed with Entity Framework in mind) play the same role as entities in Domain Driven Design (i.e. representing the core of the domain)?
Object-Relational Mapping and Domain-Driven Design are two orthogonal concerns.
ORM
An ORM is just here to bridge the gap between the relational data model residing in your database and an object model, any object model.
An Entity as defined by EF concretely means any object that you wish to map some subpart of your relational model to (and from). It turns out that the EF creators wanted to give a business connotation to those by naming them Entities, but in the end nothing forces you that way. You could map to View Models for all it cares.
DDD
From a DDD perspective, there's no such thing as "an Entity designed with EF in mind". A DDD Entity should be persistence ignorant and bear no trace of any ORM. The domain layer has no interest in how, where, whether or when its objects are stored.
Where the two meet
The only point where the two orthogonal concepts intersect is when the object model targeted by your ORM mapping is precisely your domain model. This is possible with what EF calls "Code first" (but should really be named regular ORM), by pointing to your DDD Entities in separate EF mapping files living in a non-domain layer, and refraining from using EF artifacts such as data annotations directly in your Entity classes. This is not possible when using Database First, because the DDD "purity" part of the deal wouldn't be met.
In short, the terms collide, but they should really be conceptually considered as two different things. One is the domain object itself and the other is a pointer that can indicate the same bunch of code, but it could point to pretty much anything else.
They shouldn't be the same as they're designed for different purposes. An ORM entity is a facade for 1 or more tables, its purpose is to simulate OOP on top of relational tables. A Domain Entity is about defining a Domain concept. If your Domain Entity turns out to be just a data structure, then you can reuse it as an EF entity, but that's just one case.
A DDD app never knows about EF or ORM. It only knows about a Repository. Hence, your Domain Objects (DO) don't know either about EF. You can choose to consider them EF entities, as an implementation detail, BUT... you should do that ONLY after your DOs are defined and their use cases implemented. You should defer as much as possible the implementation of persistence (use in-memory repos (lists) for devel).
When you reach that point you'll know if you can reuse your DO for ORM purposes or if you'll need other ways (such as a memento).
Note that a design of a DO while driven by the Domain, it should take into consideration the persistence issue, but it shouldn't be influenced by it i.e don't design your DO according to the db schema. The persistence strategy can be different for each DO and it might involve or not an ORM.
If you're using Event Sourcing for a DO, ORM doesn't exist. Same for serialized objects. It matters a lot how an object will be used by the app (updating and querying), that's why I've said you should defer the persistence implementation. For a lot of DOs you won't need a rdbms (even if you're using it) so an ORM entity will look more like a KeyValuePair (Id => serialized data).
In conclusion, they are different things for different purposes, that might look identical for some cases (CRUD scenarios).
I would say, they can be the same.
Sometimes there is no need to support two models. When you follow code first approach, your entities model your domain, your infrastructure (ORM) separates domain and persistence layers.
It might be reasonable to maintain two models if you have legacy database and have to maintain it.
There are two other SO questions that can be helpful:
Repository pattern and mapping between domain models and Entity Framework
Advice on mapping of entities to domain objects
Well.That's The Approach i use.And I've seen a lot of others doing the same.Now am using The Onion Architecture/Pattern to Create my application and making Everything rely on the domain entities made my life easier.because whenever i want to change for example the Layer that deal with my database ,i can do that without changing the UI layer(ASP.NET MVC app,WPF app...etc)...I suggest doing the same.
let's wait for other posts
I agree with what MikeSW said (3rd Answer).When you design your domain entities,you should do that without caring about who will consume those entities (ORMs or any other technology serving whatever purpose).design them with one idea in mind : they will be reusable and they will not need to be changed in the future (hopefully)
I stumbled upon the following two articles First and Second in which the author states in summary that ORM Entities and Domain Entities shouldn't be mixed up.
I face exactly this problem at the moment as I code with EF 6.0 using the Code First approach. I use the POCO classes as entities in the EF as well as my domain/business objects. But I find myself frequently in the situation where I define a property as public or a navigation property as virtual only because the EF Framework forces me to do so.
I don't know what to take as the bottom line of the two articles? Should I really create for example a CustomerEF class for the entity framework and a CustomerD for my domain. Then create a repository which consumes CustomerD maps it to CustomerEF do some queries and than maps back the received CustomerEF to CustomerD. I thought EF is all about mapping my domain entities to the data.
So please give me some advice. Do I overlook an important thing the EF is able to provide me with? Or is this a problem which can not completely solved by the EF? In the latter case what is a good way to manage this problem?
I agree with the general idea of these posts. An ORM class model is part of a data access layer first and foremost (even if it consists of so-called POCOs). If any conflict of interests arises between persistence and business logic (or any other concern), decisions should always be made in favor of persistence.
However, as software developers we always have to balance between purism and pragmatism. Whether or not to use the persistence model as a domain model depends on a number of factors:
The size/coherence of the development team. When the whole team knows that properties can be public just because of ORM requirements, but should not be set all over the place, it may not be a big deal. If everybody knows (and obeys) that an ID property is not to be used in business logic, having IDs may not be a big deal. A scattered, unexperienced or undisciplined team may need more stringent segregation of code.
The overlap between business logic concerns and persistence concerns. Object oriented design thrives when a class model sticks to SOLID principles. But these principles are not necessarily at odds with persistence concerns. I mean that although the concerns are different, in the end their resultant requirements may be quite similar. For instance, both concerns may require valid object state and correct associations.
There can be use cases, however, in which objects temporarily need to be in a state that absolutely shouldn't be stored. This may be a reason to work with dedicated domain classes. Another reason may be that the entity model just can't fulfill the best segmentation of responsibilities. For instance, a business process "blacklisting customer" may require data that is scattered over so many entity objects that new domain classes must be designed that can encapsulate the data and the methods working on them. In other words: doing this by entities would violate the Tell Don't Ask principle.
The need for layering. For instance, if the data access layer targets different database vendors it may have to consist of interchangeable parts that are vendor-specific (e.g. to account for subtle differences in data types between Oracle and Sql Server or to exploit vendor-specific features). Using the persistence model as domain model would probably bleed vendor-specific implementations into the business logic. That would be really bad. There the data access layer should be precisely that, a layer.
(Very trivial) The amount of data. Creating objects takes time and resources. When "many" objects are involved in a business case it may just be too expensive to build both entity objects and domain objects.
And more, undoubtedly.
So I would always try to be a pragmatist. If entity classes do a decent job, go for it. If the mismatch is too large, create a business domain for appropriate parts of the business logic. I would not slavishly follow a (any) design pattern just because it is a good pattern. Contrary to what is said in the post, it requires a lot of maintenance to map an entity model onto a business model. When you find yourself creating myriads of business classes that are almost identical to entity classes it's time to rethink what you're doing.
I had a little discussion with a friend of mine about the use of Entity framework. I had a project where I made a 3 tier solution with the entity framework as my datalayer, and used Data Transfer Objects to move from the business tier to user interface. I really liked the loose coupling it gives, since I can change the entity framework with e.g. hibernate later on. My friend on the other hand, was arguing that the purpose of the Entity framework was to model it so it could be used on the user interface.
How do you couple the entity framework to your solution?
I see the idea that my friend is proposing with the interchangable layers being Hibernate and EF, but I think its a little drastic as these two frameworks already contain DL->BL capabilities. I think the reason for using frameworks like EF and Hibernate are these, in prioritized order:
1. Direct usage of entities in business logic
2. Database type independence
3. Automatic caching
4. SQL Abstraction
Expecting that a framework like this should ALSO be loosely coupled to the tiers would just require too much query parsing, object wrapping and unwrapping and various noise to make up for the interchangability that might never become a reality. As i see it, his proposal would result in the equivalent of: DL -> DL -> BL -> UL
Anyone agree on this?