控制器逻辑与服务/业务层逻辑

时间:2017-03-16 17:23:47

标签: design-patterns model-view-controller dependency-injection controller

我正在开发一个应用程序,并且正在使用Repository-Service-Controller方法来实现REST API。

我发现自己在控制器逻辑与服务逻辑之间进行争论。服务逻辑处理业务逻辑,例如计算账面价格,控制器逻辑应处理演示细节。

  • 如果是业务逻辑的一部分怎么办? 应用程序是检查发布者是否订阅了 PremiumService确定图书是否可编辑?将 这是业务逻辑还是控制器逻辑?
  • 如果在控制器中,如果发布者未在PremiumService中订阅,我想隐藏正在呈现的图书怎么办? PremiumServicePublisherController依赖PremiumService检查该书的发布者是否已在class Publisher { public function getId(): int; public function getName(): string; public function getBooks(): Book[]; } class Book { public function getId(): int; public function getName(): string; public function getPublisher(): Publisher; public function getAuthors(): Author[]; } class Author { public function getId(): int; public function getName(): string; public function getBooks(): Book[]; } // Simple CRUD repository. class BookRepository { public function find($id); public function findAll($criteria); public function create($book); public function edit($book); public function remove($book); } class BookService { public function __construct( BookRepository $book_repository, AuthorService $author_service, PremiumService $subscription_service ); public function get($id); public function getAll($criteria); // Book is editable if the publisher of the book is subscribed to the PremiumService public function edit(Book $book); // Book is removable if the publisher of the book is subscribed to the PremiumService public function remove(Book $book); // Can only add an author if the publisher of the book is subscribed to the PremiumService. public function addAuthor(Author $author, Book $book); } class PublisherController { public function __construct(BookService $book_service); // Can only view a book if the publisher of the book is subscribed to the PremiumService public function getBook(Request $request); // Can only view books if the publisher of the book is subscribed to the PremiumService public function getBooks(Request $request); } 订阅?

我可以看到如何在BookService上创建太多依赖项可能会变成意大利面条代码。

这是一个带有伪代码的界面,可以帮助回答我的问题。

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{

optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS;Database=MYDB;Integrated     Security=True;MultipleActiveResultSets=True;");

}

如果服务依赖于其他服务的过多依赖,那么通常或推荐的方法是什么?该服务应该是愚蠢的,如存储库?

1 个答案:

答案 0 :(得分:5)

回答你的问题:

1)您通过说“如果应用程序的业务逻辑的一部分是......”会回答您自己的问题。因为它是业务逻辑,所以将它放在业务逻辑层(即服务)中。

2)如果发布者未订阅订阅服务,则隐藏图书听起来像是您的业务逻辑的一部分(您的业务规则是用户无法阅读书籍,如果他们不支付费用),那么会去服务。然后是的,该服务必须是您的控制器的依赖。

我经常发现自己处于与您类似的情况,其中单个业务规则需要依赖于许多业务服务才能完成其工作。避免在服务中拥有大量依赖关系,同时保持每项服务简单的一种好方法是,一旦开始获得服务的四个或五个依赖项,就使用 facade 服务。外观是一种更高级别的服务,处理协调下级服务。

例如,您可以拥有ContentManager服务,该服务接受BookServiceAuthorServicePremiumService的相关性。然后你的控制器只对ContentManager有一个依赖。当您的控制器想要显示书籍列表时,它会调用ContentManager.getBooks并传递一些用户详细信息,以便您可以确定该用户是否已订阅。然后ContentManager确定用户是否可以查看图书,获取图书的详细信息,获取图书的作者详细信息等等。

尽管ContentManager最终在其子服务中有很多东西,但它仍然是一个非常简单的类,因为它唯一的工作就是为给定的动作调用适当的子服务方法。

不可否认,你的情况不是很大,因为你没有大量的依赖关系,但是如果你发现自己处于需要控制器的情况,比如8个依赖关系,那么你可以把它们分解成外墙。如果其中五个服务用于一组高级业务规则(例如您的库/发布者管理),其中三个服务用于另一组高级业务规则(例如计费),那么您将有一个具有五个依赖关系的外观和另一个具有三个依赖关系的外观。