views:

131

answers:

1

I'm looking for some feedback on my ASP.NET MVC based CMS application architecture.

Domain Model - depends on nothing but the System classes to define types. For now, mostly anemic.

Repository Layer - abstracted data access, only called by the services layer

Services Layer - performs business logic on domain models. Exposes view models to the controllers.

ViewModelMapper - service that translates back and forth between view models and domain models

Controllers - super thin "traffic cop" style functionality that interacts with the service layer and only talks in terms of view models, never domain models

My domain model is mostly used as data transfer (DTO) objects and has minimal logic at the moment. I'm finding this is nice because it depends on nothing (not even classes in the services layer).

The services layer is a bit tricky... I only want the controllers to have access to viewmodels for ease of GUI programming. However, some of the services need to talk to each other. For example, I have an eventing service that notifies other listener services when content is tagged, when blog posts are created, etc. Currently, the methods that take domain models as inputs or return them are marked internal so they can't be used by the controllers.

Sounds like overkill? Not enough abstraction? I'm mainly doing this as a learning exercise in being strict about architecture, not for an actual product, so please no feedback along the lines of "right depends on what you want to do".

thanks!

+1  A: 

Overall, the design looks good to me.

There are a few more items I might do:

  • Validations - have a 2 step validation -
    Step 1 : the domain-level classes enforce their own validity (via attributes or any other mechanism).
    Step 2: The repository ensures that the object is valid in the context of the repository

  • Dependency Injection - use a DI framework to inject dependencies. It will be useful for unit testing. Also, If the service layer where you need to call across services, check if this article on Aggregate Service is useful: http://blog.ploeh.dk/2010/02/02/RefactoringToAggregateServices.aspx

    • ViewModels - might be tempting to re-use, but wait & watch before you finally decide

HTH.

Sunny
Good answer. In the old days we used to call Step 1 "Validation" and Step 2 "Verification".
pdr
Thanks Sunny. I'm actually using StructureMap for DI, so I'm good there. Currently, for validation, I have a validation service that validates the domain models. I like having the models prevent themselves from getting into an invalid state, and I think I prefer having the "valid state" type business rules embedded in the domain models. Where do you draw the line between rules that go in the domain model and elsewhere (validation service, repositories, etc.)?
Joe Future
To keep my domain model in a valid state I don't put any property setters on my model. Instead, all state changes must go through a method which verifies that the change is appropriate before applying it. The downside is that if you have a lot of potential changes this can become a fair amount of code. Creation and deletion operations still go on the repository layer.
Ryan
@Joe - usually, I put the valid datatype checks with the model itself. But, have the rules to the repository level. By this, the model will always have valid data, but can be persisted ONLY if the repository is also in valid state at the end of the operation. This way, I need not depend on the consumer to call a validation service.
Sunny
Sunny
I can see where both would be helpful. In the case of a missing required field, if the "setter" method never got called (and thus the value is missing), then you'd still want to validate this before saving to the repository. Thanks for all the tips!
Joe Future