控制器逻辑与服务/业务层逻辑
Posted
技术标签:
【中文标题】控制器逻辑与服务/业务层逻辑【英文标题】:Controller logic vs Service/Business layer logic 【发布时间】:2017-08-08 00:40:40 【问题描述】:我正在开发一个应用程序,并且正在为 REST API 使用 Repository-Service-Controller 方法。
我发现自己在控制器逻辑与服务逻辑之间争论不休。服务逻辑处理业务逻辑,例如计算图书价格,而控制器逻辑处理表示细节。
如果部分业务逻辑的 应用程序是检查发布者是否订阅了PremiumService
确定这本书是否可编辑?将
这是业务逻辑还是控制器逻辑?
如果在控制器中,如果出版商未在PremiumService
中订阅,我想隐藏正在呈现的书籍怎么办? PremiumService
是否会成为 PublisherController
的依赖项,以检查图书的出版商是否在 PremiumService
中订阅?
我可以看到在 BookService 上创建过多的依赖项会变成意大利面条式代码。
这是一个带有伪代码的界面,可以帮助回答我的问题。
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);
如果一个服务依赖于其他服务的太多依赖项,这里通常或推荐的方法是什么?服务应该像存储库一样愚蠢吗?
【问题讨论】:
【参考方案1】:回答您的问题:
1) 你回答了你自己的问题,说“如果应用程序的部分业务逻辑是......”既然是业务逻辑,就把它放在业务逻辑层(即服务)。
2) 如果出版商未订阅订阅服务,则隐藏书籍听起来像是您业务逻辑的一部分(您的业务规则是,如果用户不付费,他们就无法阅读书籍),因此会去服务。然后是的,该服务必须是您的控制器的依赖项。
我经常发现自己处于与您类似的情况,其中单个业务规则需要依赖于许多业务服务才能完成其工作。避免在您的服务中产生大量依赖项,同时保持每个服务简单的一个好方法是,一旦您开始获得一个服务的四个或五个依赖项,就使用 facade 服务。外观是一个更高级别的服务,负责协调较低级别的服务。
例如,您可以有一个 ContentManager
服务,它接受 BookService
、AuthorService
和 PremiumService
的依赖项。然后你的控制器只对ContentManager
有一个依赖。当您的控制器想要显示书籍列表时,它会调用 ContentManager.getBooks
并传入一些用户详细信息,以便您确定该用户是否已订阅。然后ContentManager
判断用户是否可以查看一本书,获取该书的详细信息,获取该书的作者详细信息,等等。
尽管 ContentManager
最终在其子服务中包含很多东西,但它仍然是一个非常简单的类,因为它的唯一工作是为给定操作调用适当的子服务方法。
诚然,这对您的情况来说并不是一个很大的改进,因为您没有大量的依赖项,但是如果您发现自己处于需要控制器的情况,比如八个依赖项,那么您可以将它们分解为外观。如果其中五项服务用于一组高级业务规则(例如您的图书馆/出版商管理),而其中三项服务用于另一组高级业务规则(例如计费),那么您会一个门面有五个依赖项,另一个门面有三个依赖项。
【讨论】:
以上是关于控制器逻辑与服务/业务层逻辑的主要内容,如果未能解决你的问题,请参考以下文章