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.
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.