I’m porting our old Active-Record based API over to a new structure to make unit testing easier etc. We are using the repository pattern for our data access and StructureMap for dependency injection.
I’m struggling a little now with how to structure everything. Using our ‘Product’ class as an example, we previously had our model, repository and factory parts all built into the product object, for example to load, edit and save a product we could something like (simplified):-
Dim p As New Product If(p.Load(1)) p.Name = 'New Name' p.Save() End If
And to get a collection of objects we had a Shared(static) method on the object which acted as a basic factory
Dim arrProds = Product.GetProducts()
After looking at a few examples, in our new structure we now have an IProductRepository, IProductService (which is the factory) and Product model class. So, something like this
Dim prodSvc = ObjectFactory.GetInstance(Of IProductService) Dim prod = prodSvc.GetProduct(1) //Prod is an Instance of 'Product' prod.Name = 'New Name' prodSvc.Save(prod)
However, the Product class has the ability to load related data, for example
Dim arrRelatedProds = prod.RelatedProducts
Which inside the Product class looks like this
Class Product Function RelatedProducts() As IList(Of Product) // prodSvc is an instance of IProductService which is passed into the // Product class in the constructor (or via Dependency Injection) Return Me.prodSvc.GetRelatedProducts(Me.ProductID) End Function End Class
I don’t like this because it’s difficult to test and because I don’t like the fact that my ‘Model’ class (Product) calls the IProductService class directly.
Does anyone have any suggestions about a better way to structure all this?
Cheers
James
EDIT Probably the wrong time of year to ask this! Is there any clarification I can add to make this question answerable??
When using the repository pattern instead of active record, don’t reference to the repository in the domain object (product). It’s not impossible, but you save yourself a lot of trouble when you don’t. The best thing you can do is using an ORM that supports lazy loading. Personally I use NHibernate for that. Make your repository dependent on your domain objects, but the domain objects independent of the repository. The best thing to do is not to inject anything at all in your domain objects.