服务层应该只返回模型对象吗?网上有一些关于它的帖子(
here和
here是一些SO帖子)但没有一个很好的例子.
我所看到的都是这样的:
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.
我觉得我在这里遗漏了一些东西.
看看下面的例子……假设我想要返回所有电影的列表,但是,我需要一个布尔标志 – 类似于hasLike – 以显示我之前是否已经喜欢它.如何仅从服务层返回模型?
简而言之……如何按照这种方法从服务层返回元信息?那可能吗?
模型
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; } }
服务
public class MovieService : IMovieService { public Movie Get(int id) { } public Movie GetByName(string name) { } public IEnumerable<Movie> GetAll() { return unit.DbSet<Movie>(); } }
解决方法
您可以将服务拆分为查询和命令.
查询操作返回数据的扁平非规范化视图,易于客户使用.命令操作接受仅包含执行命令所需信息的命令.
这意味着从服务返回的查询模型与数据库中的查询模型不同.您可以根据需要添加属性,例如,由服务(或优选业务层)中执行的某些业务逻辑设置的HasLike属性.因此,如果客户端没有附加值,则不必返回喜欢列表;但是根据是否有喜欢将HasLikes设置为true或false.
基本上,您在示例中给出的模型类(Person,Movie,MovieLike)表示它们在您的域和/或数据库中的样子;但不是从您的服务返回的人.相反,你可以:
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 }
和…
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 }
以最佳方式设计服务合同以供客户使用,可以使您的生活更轻松.