oop - 对 OOP 中单一职责的困惑
问题描述
让我们考虑以下示例:
class User
{
}
class FirstUseNotification
{
function show(User user)
{
// check if it was already shown, return if so
// show a notification
// mark it as shown in the db or whatever
}
}
class SomeController
{
function someMethod()
{
firstUseNotification->show(user);
}
}
show() 方法似乎通过做 3 件事来打破单一职责。所以我认为这可以重写为:
class User
{
}
class FirstUseNotification
{
function show(User user)
{
// show a notification
}
function shouldShow(User user)
{
// return true if not yet shown
}
function markAsShown(User user)
{
// flag notification as shown
}
}
class SomeController
{
function someMethod()
{
if (firstUseNotification->shouldShow(user))
{
firstUseNotification->show(user);
firstUseNotification->markAsShown(user);
}
}
}
所以这就是我感兴趣的:
- 我是否正确假设在第二个示例中通知类现在可以使用单一责任原则?
- show() 方法中发生的所有事情都消失了,但是......它们只是重新定位到控制器中的一个方法,所以这不应该意味着这个控制器方法现在破坏了单一职责吗?如果是这样,如何才能遵守?
解决方案
单一责任原则 (SRP) 经常以 Robert C. Martin 的名言形式表述:
一个类应该只有一个改变的理由。
在这种情况下,您的FirstUseNotification
课程的目的是向首次使用的用户显示通知。所以这个类需要改变的唯一原因是这个目的是否改变了;这是一个原因,所以 SRP 是满意的。
请注意,此定义适用于类,而不适用于方法。也就是说,将这个方法分成三个方法可能违反了 SRP,因为如果这个类的用户需要调用三个方法而不是一个,那么该用户类有责任检查是否显示通知,并将用户标记为显示,除了用户类自己的责任。FirstUseNotification
的职责是“向第一次使用的用户显示通知”,而不是提供允许其他类在不负责时执行此操作的 API。
实际上FirstUserNotification
,如果类如何显示通知或访问数据库的详细信息发生更改,则该类可能有其他更改原因。理想情况下,可以通过为通知和数据库类提供稳定的接口来防止这种情况,以便对这些类的更改不需要更改FirstUseNotification
显示通知和/或访问数据库的其他类。在实践中,这并不总是 100% 实现的,在这种情况下,FirstUseNotification
类可能有一些责任与显示通知或访问数据库的细节有关。但理论上,如果那些其他类处理好自己的职责,那么这个类只有一个改变的理由。
推荐阅读
- tensorflow - Keras 的 AUC(curve='PR') 和 Scikit-learn 的 average_precision_score 有什么区别?
- php - 如何在 Symfony 5 中集成 Ratchet websocket?
- php - 如何在 php 中禁用 $_GET 和 $_POST 中的数组?
- powerbi - OLE DB-eller ODBC-fel:[DataFormatError]外部表不是预期的格式
- java - 添加新数据后 Vaadin 14 LTS Grid 刷新不起作用
- ios - @Published 字符串变量不更新视图
- html - 使用 HTML 和 CSS 在除第一页和最后一页之外的所有打印页面上显示某些内容
- templates - Odoo 14:元素'
' 不能位于父视图中 - amazon-web-services - 文件从 Salesforce LWC 上传到 Amazon S3(无顶点)
- typescript - TS1005:“,”预期