This is the structure I've settled on for the time being:
- Data layer (eg, Linq to SQL)
- Data storage (eg, SQL database)
The View, Controller and Service communicate through DTOs (aka ViewModels); the View and Controller never see the (domain) Models. I'm not 100% decided about the Service - Repository interface: should the Model objects be the same as the Data Layer objects? For purity reasons I'd say no - it's a bad idea to return Linq to Sql objects to the Service because it will cause problems when trying to switch to (say) Entity Framework. However, I haven't yet worked on a project big enough that the benefits of this separation outweigh the drawback of creating 3 different classes for the same entity (Linq Order, Model Order, DTO Order). I'll have to see what happens when I actually do work on a larger project (with this architecture I mean, I work on huge projects but not with this structure).
The Service has two types of methods:
- Reads, where it asks the repository for a list of Models (eg Products).
- Writes, where it asks the repository for a Model and then asks the Model to do something.
This way I avoid the anemic domain anti-pattern - the Service layer can stay thin and let the Models provide (most of) the business logic - querying is not completely a business logic concern. (It is more of a reporting concern instead of a transaction concern.)
Speaking of that, I also need to come up with a way of saying "commit" when I'm doing transactions; each Service method must be a transaction, but I still haven't come up with a way of doing that. (Maybe the EntityService base class - all my Services inherit from it - should have a Commit method that in turns calls for example DataContext.SubmitChanges(). However, that would link the Service to a specific Data Layer, bypassing the repository/ies, which I'd rather not do. Hmm.
I already clarified the structure of the repository (if only to myself, since I haven't posted my last changes to the interfaces and Linq implementation ). In theory, it shouldn't be a big deal (a day or two) to write a Data Layer for, say, SQLite.
Well. Good place to save my current thinking on the subject. Hopefully I'm not too far off-mark.