Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Architecture for MVC web project / usage of different types of model

I’m building a project that currently has 3 assemblies:

  • UI
  • Core (Services & Models, Utilities)
  • Repositories (Linq2SQL)

Dependencies are

  • UI -> Core
  • Core -> Repositories.

I’d like Services and Models to be in their own assemblies and end up with something that’s built around the Models i.e.:

  • UI ->Models, Services
  • Services -> Models, Repositories
  • Repositories -> Models
  • Models

The system I’m building is basically a website CMS so I’ll have a model for a web page (PageModel) which has a collection of child web pages. PageModel can call methods in a service (PageService) to populate its child pages but in the new design that can’t happen because the Models assembly necessarily knows nothing of the services assembly.

I’ve considered some of the ideas in the Onion Architecture (namely dependency injection) to solve this, but it seems that a more elegant /obvious solution might be available.

Do I need to introduce another layer of Model? View Models? I think what I’m calling Models are Domain Models... I may very well be wrong! Services would then be Domain Services?

So my solution would be:

  • UI -> Services, ViewModels, Models
  • ViewModels -> Services, Models
  • Services -> Repositories, Models
  • Repositories -> Models
  • Models

In this example I imagine my PageViewModel would extend PageModel and use the PageService to fetch it’s child pages..

Any suggestions appreciated. Also any pointers on what these layers of models are usually called? Am I talking about DTO Models rather than Domain Models here? And Domain Models rather than View Models? It seems like what I'm proposing to use the View Models for isn't really the job of a View Model..

Thanks

EDIT:

Something I hadn't mentioned originally is that my Domain Models aren't basic translations of single database entities like you tend to see in most tutorials. A domain model can contain data fields that come from several related database tables.

So would it be worth having a set of Models purely to encapsulate the the data in the Domain - without any methods/properties that fetched related objects or saved the object back to the DB etc? - Data Transfer Objects.

From looking at a couple of scribbled diagrams this would mean having a set of mappers in the domain layer (which seems wrong..) to translate DTO models to Domain Models and back. The project would become built around the DTO models rather than the domain models but given what's encapsulated by the DTOs I don't see that being a problem.

For anyone who's interested, the proposed dependency structure would be like so:

  • UI -> Services, Domain Models
  • Services -> Repositories, Domain Models, DTO Models
  • Domain Models -> Repositories, DTO Models
  • Mappers -> Domain Models, DTO Models
  • Repositories -> DTO Models
  • DTO Models (no dependencies)

It's a bit of a mess! And all just because I want my PageModel to be able to fetch its own child PageModels.. It's looking like having a go at dependency injection might not be such a bad plan.

Thanks to the guys who've replied. You've given me loads to think about.

like image 666
Giles Avatar asked Feb 28 '12 21:02

Giles


1 Answers

You can accomplish this just fine with the onion architecture. I'll have for example: UI, Domain, Data Access, Services

UI Services Data Access Domain (contains view models as well)

UI can access any one. Services, only data access and domain. Data access - only domain.

My repository interfaces are in the domain project, and they are implemented in the data access project. I also keep other interfaces in the domain project (IContext, IUnitOfWork, etc) so I have one central place and not spreading too many interfaces between projects.

DTOs would be used simply for transferring between layers, if you deem appropriate. There's no reason to me you can't pass a domain model from a data layer on up, some choose to only use DTOs here. I'll do the mapping in the UI layer (ex MVC controller) to a ViewModel since I can make use of AoP to do it for me ([AutoMap()] attribute )

Just remember that your models should not contain any persistence logic at all.

like image 62
Adam Tuliper Avatar answered Oct 18 '22 22:10

Adam Tuliper