views:

64

answers:

4

I'm using a repository pattern for my data access. So I basically have a repository per table/class. My UI currently uses service classes to actually get things done, and these service classes wrap, and therefore depend on repositories. In many cases my services are only dependent upon one or two repositories, so things aren't too crazy. Unfortunately, one of my forms in the UI expects the user to enter data that will span five different tables. For this form I made a single service class that depends upon five repositories. Then the methods within the service for saving and loading the data call the appropriate methods on all of the corresponding repositories.

As you can imagine, the save and load methods in this service are really big. Also, unit testing this service is getting really difficult because I have to setup so many fake repositories.

Would it have been a better choice to break this single service apart into a few smaller services? It would put more code at the UI layer, but would make the services smaller and more testable.

A: 

One possiblity would be to break up the service as you suggest, however it might be also reasonable to create a facade for working with those repositories and keep single service. This will allow you to separate business logic in the service and data manipulation and maybe flow in and between repositories.

Gabriel Ščerbák
A: 

I'd say that if you can abstract the saving to each repository and than call the abstraction from the service you then have a more testable and maintainable peace of code without putting any extra code in your UI.

I currently have a UI that calls more then one service to save the input in a single form (async) and it is a pain to get it to work properly. The biggest issue you have is handling validations and errors. The first bit might be correct, but then the second bit fails. You'd have to go back and delete the first bit, because it was already saved. Trust me, it's a pain.

Jonathan van de Veen
A: 

I think I would concentrate on the two sentences in the middle paragraph:

Firstly, why are the saving and loading methods in the service class "really big"? Could you break them up? Perhaps there are smaller units in there which can be tested separately. That would, perhaps, point to cutting the service up into a number of sub-components that your service delegates most of its work to. You could hopefully avoid adding any more code to the UI layer going down that route, because the UI would still be able to interact with just the one service, but you could test all the components separately.

Secondly, why is it so difficult to set up fake repositories in your test harness? Could you make that easier? I often use a builder to set up similar, but not identical, data structures for use by tests. You then end up with tests that read 'given the usual setup except for difference X, check that Y happens'.

One other idea is to notice that data access code is often very repetitive and it is frequently possible to generate much of it automatically based on your database schema. We generate much of our basic data access layer, including fake implementations of repository classes for testing against. Of course we have to hand-code the performance-critical bits but it takes a lot of the drudgery out of it and makes it easy to handle changes to the schema.

Dave Turner
+1  A: 

I would not have a repository class per table/class.

You should have one repository per 'module' or 'root-aggregate'. That is that a certain repository can cover much more than just one table. We have grouped related tables into one repository. Examples is that we have a RelationRepository on top of different tables like Person, Company and the OrderRepository on top of the tables Orders, OrderLines, FlightRepository on top of the tables to store all the data for Flights, etc. This is the repositorypattern as you should want to use it according to domain driven design anyway.

Hace