4

Should service layer return only model objects? There are some posts about it on the web (here and here are some SO posts) but none with a good example.

All I see is something like this:

Services should care only about the problem domain, not the view that renders results. Return values should be expressed in terms of domain objects, not views.

I'm feeling that I am missing something here.

Looking at the example below ... Suppose I want to return a list of all movies, but, I need a boolean flag - something like hasLike - to show if I already liked it before. How is it possible returning only models from service layer?

In short ... how do I return meta information from service layer following this approach? Is that possible?

Model

public class Person
{
    public int                     PersonID        { get; set; }
    public string                  Name            { get; set; }
    public ICollection<Movie>      FavoriteMovies  { get; set; }
    public ICollection<MovieLikes> Likes           { get; set; }
}

public class Movie
{
    public int      MovieID     { get; set; }
    public string   Name        { get; set; }
    public string   Description { get; set; }
}

public class MovieLike
{
    public int              MovieLikeID      { get; set; }
    public int              PersonID         { get; set; }
    public int              MovieID          { get; set; }
    public DateTimeOffset   Date             { get; set; }
}

Service

public class MovieService : IMovieService
{
    public Movie Get(int id)
    {

    }

    public Movie GetByName(string name)
    {

    }

    public IEnumerable<Movie> GetAll()
    {
        return unit.DbSet<Movie>();
    }
}
Community
  • 1
  • 1
Felipe Miosso
  • 7,309
  • 6
  • 44
  • 55
  • Hmmm ... but if I do that, I'm going to pass unnecessary data to the controller, right? – Felipe Miosso Apr 01 '14 at 20:12
  • Here is a possible answer to your question : http://stackoverflow.com/questions/21554977/should-services-always-return-dtos-or-can-they-also-return-domain-models – Hasteq Apr 01 '14 at 20:37

1 Answers1

2

You can split your service into queries and commands.

The query operations return flattened denormalized view of your data, easy consumable by your clients. The command operations accept commands that contain only information needed to execute the command.

This means that the query models that you return from your service are different than what is in your database. You can add properties as you like, for example, a HasLike property that is set by some business logic executed in your service (or preferably business layer). So you don't have to return a list of likes if that has no added value for the client; but set the HasLikes to true or false based on whether there are likes or not.

So basically, the model classes that you gave in your example (Person, Movie, MovieLike) are representations of how they look like in your domain and/or in the database; but not the ones to return from your service. Instead, you could have:

 public IEnumerable<MovieSummary> GetAll()
 {
     return unit.DbSet<Movie>();
 }

 // All properties needed in summarized representation
 public class MovieSummary
 {
     public int MovieID { get; set; }
     public string   Name { get; set; }
     public string   Description { get; set; }
     public bool HasLike { get; set; }
     // Other calculated properties
 }

And...

 public MovieDetails Get(int id)
 {

 }

 // All properties needed in detailled representation
 public class MovieDetails
 {
     public int MovieID { get; set; }
     public string   Name { get; set; }
     public string   Description { get; set; }
     public ICollection<MovieLikes> Likes { get; set; }
     // more
 } 

Designing your service contracts in the most optimal way to be used by your clients makes your life a lot easier.

L-Four
  • 13,345
  • 9
  • 65
  • 109
  • So, if I got this right ... instead of returning only Models you are saying to return only ViewModels? – Felipe Miosso Apr 02 '14 at 16:35
  • I would not really return view models, as these target specific views only; a service operation can return a model that can be used my multiple clients/view. But make it a flattened view instead of a hierarchy of data, return only what's needed, and add concepts like HasLikes if you need them. – L-Four Apr 03 '14 at 07:02