我正在开发一个应用程序,并且正在为 REST API 使用 Repository-Service-Controller 方法。
我发现自己在 Controller 逻辑与服务逻辑之间争论不休。服务逻辑处理业务逻辑,例如计算图书价格,而 Controller 逻辑应处理呈现细节。
应用程序是检查发布者是否订阅了
PremiumService
确定这本书是否可编辑?将这是业务逻辑还是 Controller 逻辑?
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)您通过说“如果应用程序的业务逻辑的一部分是……怎么办”来回答您自己的问题,因为它是业务逻辑,因此将其放在业务逻辑层(即服务)中。
2)如果出版商未订阅订阅服务,则隐藏书籍听起来像是您业务逻辑的一部分(您的业务规则是,如果用户不付费,则无法阅读书籍),这样就可以了一项服务。然后是的,该服务必须是您的 Controller 的依赖项。
我经常发现自己处于与您类似的情况,其中单个业务规则需要依赖于许多业务服务才能完成其工作。避免在您的服务中拥有大量依赖项同时保持每个服务简单的一个好方法是,一旦您开始获得服务的四个或五个依赖项,就使用外观服务。门面是一个更高级别的服务,它处理协调较低级别的服务。
例如,您可以有一个 ContentManager
依赖 BookService
的服务, AuthorService
, 和 PremiumService
.那么你的 Controller 只依赖于 ContentManager
.当您的 Controller 想要显示书籍列表时,它会调用 ContentManager.getBooks
并传入一些用户详细信息,以便您可以确定该用户是否已订阅。然后ContentManager
确定用户是否可以查看一本书、获取该书的详细信息、获取该书的作者详细信息等。
即使 ContentManager
最终在它的子服务中有很多东西在它下面进行,它仍然是一个非常简单的类,因为它的唯一工作是为给定的操作调用适当的子服务方法。
诚然,这对您的情况来说并不是一个很大的改进,因为您没有大量的依赖项,但是如果您发现自己处于需要 Controller 的情况,比如说八个依赖项,那么您可以将它们分解为外观。如果其中五个服务用于一组高级业务规则(例如您的图书馆/出版商管理),而其中三个服务用于另一组高级业务规则(例如计费),那么您将有一个具有五个依赖项的外观和另一个具有三个依赖项的外观。
关于design-patterns - Controller 逻辑与服务/业务层逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42840869/