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

11

我正在开发一个应用程序,使用Repository-Service-Controller模式设计REST API。

我在控制器逻辑与服务逻辑之间犹豫不决。服务逻辑处理业务逻辑,例如计算书籍价格,而控制器逻辑应处理展示细节。

  • 如果应用程序的一部分业务逻辑是检查出版商是否订阅了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[];
}
简单的 CRUD 存储库。
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个回答

16

回答你的问题:

1)你已经回答了自己的问题,因为你说“如果应用程序的一部分业务逻辑是……”,既然它是业务逻辑,那就放在业务逻辑层(即服务层)中。

2)如果没有订阅订阅服务的出版商不能阅读书籍听起来像是你的业务逻辑的一部分(你的业务规则是用户如果不支付费用就不能阅读书籍),所以这将在服务中实现。然后是,是的,该服务将成为控制器的依赖项。

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

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

即使ContentManager在其子服务中最终有很多东西在底层进行,但它仍然是一个相当简单的类,因为它的唯一任务是针对给定操作调用适当的子服务方法。

诚然,在你的情况下这不是一个巨大的改进,因为你没有太多的依赖项,但是如果你发现自己处于控制器需要八个依赖项的情况下,那么你可以将它们分解成facade。如果其中五个服务用于一组高级业务规则(例如你的图书馆/出版商管理),另外三个服务用于另一组高级业务规则(例如计费),那么你就会有一个带有五个依赖项的Facade和另一个带有三个依赖项的Facade。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接