Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should a service class be more than a wrapper of a repository class?

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.

like image 252
Grant Palin Avatar asked Aug 18 '10 17:08

Grant Palin


People also ask

When should I use service and repository?

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.

Is a repository a service?

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.

What is service repository pattern?

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 controller talk to repository?

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.


1 Answers

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:

  • RecommendMovieToFriend(int movieID, string friendEmail);
  • RateMovie(int movieID, int numberOfStars);
  • AddMovieToMyWishList(int movieID, int userID);

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.

like image 79
mikemanne Avatar answered Sep 28 '22 04:09

mikemanne