I have a fairly clean ASP.NET MVC project structure. However, I'm struggling on how to organize the mass of classes which are DTOs (data transfer objects), e.g. just to encapsulate post data from forms (viewmodels) but don't represent full domain objects or anything near that yet; and then the many "result" objects I have which communicate complex result information from my service layer back to the controller. Where do you stuff these/how do you organize them? I have one folder with well over 60 classes now and it's getting cluttered. Appreciate suggestions!
Domain objects should live in a separate Domain Model library. Anything that supports the Domain Model in an framework-neutral way (e.g. no references to ASP.NET MVC, WCF, WPF etc.) belongs in the Domain Model.
Classes that perform translation between the Domain Model and the specific interface framework (ASP.NET MVC in your case) belongs in that particular project (your ASP.NET MVC project).
You can have your mappers etc. in a separate Mappers folder, but personally, I think it is much more valuable to structure code along features instead of infrastructure.
I use <CompanyName>.<ProjectName>.Core to store all project specific classes which are not strictly pertaining to the particular project interface that I am writing. So DTOs, DAOs, other project-specific classes are all in there.
I also use <CompanyName>.<DotNetLibraryNamespace> to store general purpose classes that could be reused across projects, and are not specific to this project domain. For example, string manipulation classes could go in the <CompanyName>.Text namespace. I always mirror the .net namespace structure names so that anyone that uses the .net class library has an easy time finding my stuff.
Related
In typical DDD architecture we have 3 layers:
Domain - no references
Application - it has reference to Domain layer
Infrastructure - it has reference to Domain layer
(+ Web / UI project)
Domain models live of course in Domain layer. But in which layer should live read models (projections) for read database, for example MongoDb?
Short answer, both Application Services (Application layer) and Repositories (Infrastructure layer) know about the READ models. The domain layer remains transparent to underlying persistence and loading mechanisms.
Long answer, the exact usage mechanism depends on how you use the read models. You could either be using them to construct objects used in your domain layer or more typically, only as responses to API queries.
First case: Use Read Models as objects in the domain layer
The Application service loads the READ model from the repository into the domain entity. It is the repository's responsibility to populate the READ model correctly into the domain entity. The repository is also responsible for transforming the domain entity into the WRITE model to persist in the primary database.
By the time you get to the Domain model, objects are already loaded into memory with the help of repositories. So the domain layer does not even know about the READ model and a WRITE model; it only deals with the domain entity.
Second case: Use Read Models for storing pre-built responses to API queries
This scenario is a more typical use of the READ models. Usually, there are more than one read models for the same Entity/Aggregate because they are custom-built for specific API requests.
In this case, we don't even touch the domain layer. The Application Service accepts the request, uses the READ model repository to load the object, and return a response to the application server.
There's no written law that dictates in which project a read model should live. In my personal opinion, I think having a separate read model project has its benefits. With command query responsibility segregation things tend to get pretty confusing if the command-part of the application can access the query-part of the application. I think the two should be clearly separated.
I've spent some time working on an example project that demonstrates how to set up your DDD/ports-and-adapters/CQRS application. I've dropped the code on GitHub: https://github.com/appie2go/steal-this-code
I've also spent some time to explain the choices I've made in detail in the following articles:
https://medium.com/#abstarreveld/implementing-dddomain-models-ports-adapters-and-cqrs-with-c-2b81403f09f7 and,
https://medium.com/#abstarreveld/dddomain-models-ports-adapters-and-cqrs-reference-architecture-c-504817df65ec
Hope it helps!
Cheers
To be honest, it doesn't really matter. There's no default structure for neither DDD-oriented implementation or event sourcing-oriented implementation.
You can perfectly have a single project if the system is small. If you want to keep your domain clean of external references - you can keep it in a separate project and take care of having zero references except for something you need to support the domain model basis, like entity base class and so on.
Read models and projections are completely orthogonal to the domain model and you usually need them for the query API or query services. You will benefit from keeping read models (documents in case of MongoDB) and projections in one place. You can either reference this project from your API project or keep the query API, query services, query models, read models and projections together.
Again, I would argue that such a thing as a "typical DDD architecture" doesn't exist, because DDD is not architecture to start with. Splitting projects is more a developer convenience and discipline concern and splitting the system is the architectural concern, which is not DDD-specific.
One thing that also comes to my mind is that if you really think DDD, you might first want to find out what is your context map, how many domain models you really need and maybe there you can find some ideas about separation, not based on technical concerns really.
I've been reading articles on StackOverflow and other sites all day about best architecture practices and there are just so many conflicting ideas and opinions.
I've finally settled on an approach, but I am having a really hard time deciding where to place the EF objects (DbContext, Fluent APIs, Seeding data, etc). Here is what I currently have:
ASP.NET MVC Project: The actual web project. Contains the standard views, controllers and View Models (inside a Models folder).
Domain Model Project: Contains all POCO classes that define the database (domain) objects. Currently, does not mention or reference any EF objects.
Service Layer Project: Contains service objects for each type of domain object (e.g., IProductService, IOrderService, etc). Each service references EF objects like DbSets and handles business rules - e.g., add a Product, fetch a Product, append a Product to an Order, etc.
So the question is, in this configuration, where do EF classes go? Initially I thought in the Service Layer, but that doesn't seem to make sense. I then thought to put them in the Domain Model Layer, but then it ties the Domain Models to EF, which is essentially a DAL / Repository. Finally, I thought about creating a separate DAL Project just for EF, but it seems like a huge waste considering it will likely have 3-4 files in it (DbContext and a few other small files).
Can anyone provide any guidance?
There is no need for Domain Model since it will be redundancy. EF classes directly can act as Domain Model and they are converted to View Models while sending it to View. EF can be separated into different class library. Most of them use repository pattern along with any ORM incase it would be easy if they go for replacement. But I've seen criticism over using repository pattern, check this out.
Here is what I do:
Data:
Has one class inheriting from DbContext.
It has all the db sets.
Overrides OnModelCreating.
Mapping primary keys and relationships.
Entities:
Has every POCO classes.
Each property is decorated with needed data annotations.
Services:
Each service has common methods (GetList(), Find(), Create(), etc.).
Business:
Called from clients, orchestrate using services to perform a specific task UserChangePassword (this will check if this can be performed, then perform the task, or return error/unauthorized statuses among many others to make the client shows the correct information regarding the task. This on my case is where I log.
Clients (Desktop/Web/Wpf/etc).
I'm not saying this is the best approach, I'm just sharing what's been working for me.
I'm going to develop a web-based system with MVC4 which will use web services (WCF, exactly) for getting data from data provider (I can't use direct connection to SQL)
So, I have a question about using the web services in this project. Is this correct to use directly web service models as MVC model or I should create separate models for my MVC project and then map web service models to the models in MVC with an object-mapper (such as EmitMapper)?
Note: Consider that the web services may changes a lot.
No, don't use your WCF serializable proxy classes as MVC Viewmodels - this will couple the SOA back end to your MVC front end unnecessarily.
The 2 classes have entirely different concerns - e.g. you may want to decorate your ViewModels with DataAnnotations like UIHint etc which aren't applicable to your WCF classes (and similarly, your WCF Proxy classes may have serialization attributes).
Also, as your screens evolve, you will typically find that you may need to diverge the 2 models significantly - e.g. your screens need properties which your Service doesn't need, and vice versa.
So yes, separate classes for WCF data serialization and for MVC ViewModels, and as you've suggested, if you keep to a standard naming convention, mappers like AutoMapper will do most of the work for you.
I can only tell you what I would do.
Keep the models separate. As you say, the web services may change a lot. Having a halfway house may shield you from a lot of the implementation churn.
Also worth pointing out that:-
Easier to move to a different solution ( use a different strategy to populate the model )
Easier to unit test ( don't necessarily need a net connection to test that your model works )
Solution setup:
DAL (class library)
BLL (class library)
Common (class library (some common functionality - enums, logging, exceptions,...))
Application1 (Windows Application)
Application2 (Windows Application)
WebApp (Web application)
...
Let's say I have a Customer entity, which is:
a table in SQL server
a CustomerDataTable in DAL
a Customer class in BLL
a BLL.Customer class in all the applications
What kind of objects should BLL and DAL use for communication - DataTable or List<Customer> (for example)? In first case, BLL logic should transform Customer object to DataTable and send it to DAL. In secod case, DAL layer should be aware of Customer class, which is in BLL layer. But originaly DLL references DAL and not opposite...
Should I put all classes into seperate assembly, which is referenced by all others (Common, BusinessObjects, ...)? In this case I could use Customer class in all my projects.
Should I even bother to seperate DAL and BLL when I know, that only one BLL will use my DAL. In this case I could merge them together into one project.
PS - I am reading about DataTables and a lot of people say that we shouldn't use them at all. What are better options? Maybe it is time for me to learn some ORM mapping tools :)
In my opinion you should have another Layer (seperate dll). Like "domain", where would you keep all entities like Customer.
Then simply include in all higher levels(DAL, BLL, UI and others) in hierarchy this assembly.
Sample architecture can look like this:
(Database) <-> DAL <-> BL <-> UI
and on all levels you will have access to "domain" layer.
DAL should return List not a DataTable. On some stage your development process you may want to use in DAL some OMR like NHibernate with would also return a List, probably.
it's hard to answer this general question without knowing the application domain well enough.
I would start with thinking about where future changes are most likely and try to figure out from that where flexibility is required.
my following thought are just a suggestion. feel free to consider them and change/ignore what you feel is irrelevant.
separating the DAL from the BLL is almost always a good idea. the data scheme is one thing that should be encapsulated and hidden from the rest of the application, so leave your DataTables, DataSets, ORMs or any other solution hidden in the DAL. the BLL (and layers above it) should use simple data types (meaning simple classes). I think it would be a good idea to put those classes in a Model class library that has no references and can be used everywhere.
it feels like you have a bit too much layering...do you really need a Customer class in the BLL and another one in the Application layer? could be, but I would make sure and think it twice over.
from my experience in one of my recent project (a weather web site with 200K unique visitors daily), we used link2sql for data access (mostly read only data), and simple data classes all over our ASP.Net MVC application (of course as part of models/view models). it worked quite smoothly, and we could easily change the data scheme without breaking down other layers.
as for your last question about DataTables, these objects, should you decide to use them (I would vote against), belong solely in your DAL. they should not be exposed to other layers as that would create coupling to that specific class. what if tomorrow MS invents a much better class? would you switch over now that you have a gazillion references all over your projects to the DataTables, its method and properties? would be nicer to just change your DAL to work with the NewAwsomeDataTable class and the rest of your app is blissfully ignorant.
hope that helped :)
I would use the following pattern as it allows you to upgrade to a different persistence strategy later.
UI/Consumer <--- (view models) --> BLL <--- Models ----> DAL/Persistence
Here the View models are consumed outside the BLL and models are communicated across the BLL/DAL layers.
In your case the model can be anything the DAL uses - DataTables for example or later perhaps ORM entities. The BLL is responsible to mapping between the model and view model.
As to keeping types in their own assemblies - yes for view models and in order to maintain a consistency, yes for the models as well.
Keeping the models and view models separate stops leakage of the persistence strategies outside of the BLL and thus permits future design changes to the persistence.
One advantage of this separation is that that different view model consumers can have differing view models for the same persistence model/entity. Some could be small and have few attributes and others large and rich in functionality. It also permits you to introduce offline/disconnectedness capability as the view models could be returned at differing times allowing you decide data merging strategies. This also allows you're persistence entities (e.g. tables to grow and change shape). Since this looks like a .net implementation things like AutoMapper will provide a lot of functionality out of the box
Of course this may be way overkill for your app - however I'd still maintain a BLL mapping that only talks view models to all BLL consumers. This should give you enough decoupling.
Pushing the domain entities into the dal is an option that would remove the crcular dependency, but may not match your intent. This isn't unheard of, though; for example LINQ-to-SQL gnerated entities would live in the DAL.
Other options:
put them into a common lower assembly (but that may leave your BL rather empty)
use IOC to remove / reverse the reference between BL/DAL
There are no single right answers here.
Re DataTable; personally I agree - I'm not a fan ;) However, they can be used successfully and reasonably. But if I had to use them, I'd be keeping them in the DAL as an implementation detail - and not exposing them above that.
So i am reorganizing a winforms C# solution to help decouple and make it cleaner and more organized. The solution tracks a small business orders,etc . .
I have broken out the projects so far into
App.View - all GUI Related Code
App.Data - just data structures and interfaces. No other implementation code
App.BusinessLogic - all business logic code that has no GUI references
I have some classes that i can't figure out where they belong. Please let me know your thoughts which project each class should go or if there is another project that should get created for this.
A Class that retrieves user preferences from a database
A Class that retrieves static data from our static data server and returns sets of data results.
A Class that brings down user entitlements
A model class that stores a hashtable of orders
A class that emails out messages on a user action
Actually, I think you have things a little off from a traditional layered architecture. Normally, the models of your data that your application works on would be kept in a business layer, along with the code to operate on them. Your data layer would have both the data models of your persistence framework and the code to interact with that framework. I think this might be the source of the confusion between the suggested locations of your classes and your reaction to it based on your comments.
From that perspective anything that retrieves or brings would necessarily be located in your data layer -- it's accessing data in persistent storage. What it retrieves are eventually converted into business layer objects that your business logic operates on. Things are are conceptual models -- like a table of orders -- or business actions belong in the business layer. I would agree with #Adron with, perhaps, the same confusion about where (3) goes depending on what it actually is.
More specifically:
User Preferences are business
objects, the thing that retrieves
them is a data layer object.
The static data maps on to a business
object (table or view or something),
the thing that accesses the external
server is a data layer object.
The user entitlement is a business object, the thing that retrieves it is data layer object.
A table of Orders is a business object
Emailing is a business activity, so the thing that mails people is a business object
[EDIT] My generalized 3-Tier Architecture for (simple) web apps
DataAccessLayer
This would include my TableAdapters and strongly typed DataTables and Factories that turn rows of my DataTables into business objects in pre-LINQ projects. Using LINQ this would include my DataContext and designer generated LINQ entities.
BusinessLayer
This would include any business logic, including validation and security. In pre-LINQ these would be my business objects and any other classes that implement the logic of the application. Using LINQ these are the partial class implementations of my LINQ entities to implement security and validation along with any other classes to implement business logic.
Presentation
These are my web forms -- basically the UI of the app. I do include some of the validation logic in the forms as an optimization, although these are also validated in the BL. This would also include any user controls.
Note: This is the logical structure. The project structure generally mirrors this, but there are some cases, like connections to web services, that may be directly included in the web project even though logically the components are really in the BL/DAL.
Note: I'll probably be moving to MVC over 3-Tier once ASP.NET MVC is in production. I've done some personal projects in Ruby/Rails and I really like the MVC paradigm for web apps.
You have specified that App.Data should contain only data structures and interfaces, no implementation code, which is fine if you want to do that, but that leaves you with nowhere to put your database access code except in your App.BusinessLogic assembly.
Perhaps you really need to rename App.Data to App.Model (or something similar), and have a new App.DataAccess assembly that talks to the database (perhaps implementing a Repository pattern). Having done that, I would split things up like this:
App.DataAccess
App.DataAccess
App.DataAccess
App.Model
App.BusinessLogic
I would probably go with
Data
Data
Data, although I'm not entirely sure what the class is doing
Data
BusinessLogic
-> App.Data
-> App.Data
-> App.BusinessLogic or App.Data - not sure exactly what this means.
-> App.BusinessLogic
-> App.BusinessLogic