What is your opinion on the following 'generic' code-first Onion-inspired ASP.NET MVC architecture:
The layers explained:
Core - contains the Domain model. e.g. that's the business objects and their relationship. I am using Entity Framework to visually design the entities and the relations between them. It lets me generate a script for a database. I am getting automatically generated POCO-like models, which I can freely refer to in the next layer (Persistence) since they are simple (i.e. they are not database-specific).
Persistence - Repository interface and implementations. CRUD operations on the Domain model.
BusinessServices - A business layer around the repository. All the business logic should be here (e.g. GetLargestTeam()
, etc). Uses CRUD operations to compose return objects or get/filter/store data. Should contain all business rules and validations.
Web (or any other UI) - In this particular case it's an MVC application, but the idea behind this project is to provide UI, driven by what the Business services offer. The UI project consumes the Business layer and has no direct access to the Repository. The MVC project has its own View models, which are specific to each View situation. I am not trying to force-feed it Domain Models.
So the references go like this: UI -> Business Services -> Repository -> Core objects
What I like about it:
- I can design my objects, rather than code them manually. I am getting code-generated Model objects.
- UI is driven/enforced by the Business layer. Different UI applications can be coded against the same Business model.
Mixed feelings about:
- Fine, we have a pluggable repository implementation, but how often do you have different implementations of the same persistence interface? The same goes for the UI - we have the technical ability to implement different UI apps against the same business rules, but why would we do that, when we can simply render different views (mobile, desktop, etc)?
- I am not sure if the UI should only communicate with the Business Layer via View models, or should I use Domain Models to transfer data, as I do now. For display, I am using view models, but for data transfer, I am using Domain models. Wrong?
What I don't like:
- The Core project is now referenced in every other project - because I want/have to access the Domain models. In classic Onion architecture, the core is referenced only by the next layer.
- The DbContext is implemented in the.Core project, because it is being generated by the Entity Framework, in the same place where the .edmx is. I actually want to use the.EDMX for the visual model design, but I feel like the DbContext belongs to the Persistence layer, somewhere within the database-specific repository implementation.
As a final question - what is a good architecture that is not over-engineered (such as a full-blown Onion, where we have injections, service locators, etc) but at the same time provides some reasonable flexibility, in places where you would realistically need it?
Thanks