I have the understanding that using data access routines directly from presentation code is considered evil. So I have a separate Repositories
project, as well as a Services
project. From what I can tell, typical use of a service layer is to insulate the data access from the presentation. All well and good.
I have a pretty simple domain, simply a Movie
class. A matching repository interface is:
public interface IMovieRepository
{
void AddMovie(Movie movie);
void UpdateMovie(Movie movie);
void RemoveMovie(Movie movie);
int GetMovieCount();
Movie GetMovieById(int id);
IEnumerable<Movie> GetAllMovies();
IEnumerable<Movie> GetMoviesByGenre(Genre genre);
IEnumerable<Movie> GetMoviesByYear(int year);
IEnumerable<Movie> GetMoviesByActor(string actor);
IEnumerable<Movie> GetMoviesByTitle(string title);
}
Now when I get to a service class to use the repository, I wind up defining an interface like this:
public interface IMovieService
{
Movie CreateMovie(string title, int year, Genre genre, int length, IEnumerable<string> actors);
void UpdateMovie(Movie movie);
void RemoveMovie(Movie movie);
int GetMovieCount();
Movie GetMovieById(int id);
IEnumerable<Movie> GetAllMovies();
IEnumerable<Movie> GetMoviesByGenre(Genre genre);
IEnumerable<Movie> GetMoviesByYear(int year);
IEnumerable<Movie> GetMoviesByActor(string actor);
IEnumerable<Movie> GetMoviesByTitle(string title);
}
The two interfaces are very similar, which strikes me as odd. I expect that an IMovieService
implementation would use an IMovieRepository
implementation internally, essentially being a thin wrapper on the latter. There could probably be some validation or caching or the like, but the former seems like it would simply pass through to the latter in most cases.
Am I going about this the right way, or is there something I'm missing?
I know it seems a bit overkill for such a simple domain, but I'm trying to nail down the pattern of layering and abstraction for use in future - and larger - projects.
EDIT: to be a bit clearer, I'm not talking about NHibernate or the repository pattern, but rather about the layering of concerns.
UPDATE: thanks folks. I believe I will keep the specific query methods on the service class, to be straightforward for the UI layer, and try to generalize the repository some by passing queries to a query function.
Repository layer is implemented to access the database and helps to extend the CRUD operations on the database. Whereas a service layer consists of the business logic of the application and may use the repository layer to implement certain logic involving the database.
The repository is where the data is stored. The service is what manipulates the data. In a real-world situation comparison, if your money is stored in a vault in a bank, the vault is the repository. The teller that deposits, withdraws, etc is the service.
The Repository-Service pattern breaks up the business layer of the app into two distinct layers. The lower layer is the Repositories. These classes handle getting data into and out of our data store, with the important caveat that each Repository only works against a single Model class.
Should your controller actions work with repositories or services? It depends! You can go with just services for all the things, but you're probably going to be writing a lot of trivial pass-through services. Alternately, you can choose to use the approach that best fits what a given endpoint method is doing.
I think you're right on track. The reason why your DataAccess API and ServiceAPI look so similar is you haven't given your service any real business logic yet. Here's a few brainstorms of things that might end up on your service API, but would involve some more complex operations than simple CRUD (Create, Read, Update, Delete) functionality. Obviously these are just quick and dirty examples, but I'm sure you get the idea:
I think the separation of ServiceLayer and DataLayer is an important and valuable one, and you shouldn't second-guess it, even though the two APIs are currently very similar. As the functionality of your service grows, the two APIs will continue to diverge, to meet the needs of their callers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With