一个身份验证业务逻辑类,它应该制定身份验证方案,它们是:登录用户、获取登录用户、注册用户、恢复用户密码。
您的身份验证业务逻辑类已经违反了单一职责原则。尽管您可能认为该类的唯一职责是“身份验证”,但这很难称为一项职责,因为您可以实现数百个处理身份验证的用例,这会导致一个丑陋的大屁股类。那个班级还会有一个责任吗?相反,每个类实现一个用例。在这种情况下,您的班级将承担非常明确和狭窄的职责。
HttpContext(用于用户状态)
您的业务逻辑不应该对所使用的技术一无所知(当然,除了它是 .NET,我们不能真正抽象出 .NET),因此它不应该依赖于HttpContext
. 依赖HttpContext
违反了依赖倒置原则(DIP) 和接口隔离原则(ISP)。
DIP 说“高级模块应该......依赖于抽象。”。您的业务层是“更高级别的模块”,但它不依赖于抽象,而是依赖于较低级别的模块(HttpContext)。这将业务层类与实际的 Web 逻辑紧密结合在一起。
此外,即使您改用System.Web.HttpContextBase
抽象,您仍将依赖于由较低级别模块定义的抽象,而根据 DIP,“抽象由上层/策略层拥有”。这背后的想法是您不希望您的代码对较低层有很强的依赖性,因为这会使较高层更加依赖于此,除此之外,较低层不能定义一个抽象,即适合您的应用程序。接下来表达这个问题。
ISP 声明“不应强迫任何客户端依赖它不使用的方法”。换句话说,抽象应该针对客户的特殊需求进行定制,并且应该是狭窄的。“这种缩小的接口也称为角色接口”。两者都HttpContext
违反HttpContextBase
了 ISP,因为它们非常广泛并且适用于一般用途。他们是一个糟糕的大州,一切都是一串串。这会导致您的代码使用非常广泛的 API,从而使该 API 更难使用。它还阻碍了可测试性,因为不可能伪造 aHttpContext
甚至是摘要HttpContextBase
造假是不愉快的。如果您应用 ISP,您的生产代码和测试代码都会变得更加简洁。它还阻碍了您的应用程序的可重用性,因为您可能希望稍后在后台进程中运行您的业务逻辑的某些部分,其中没有 Web 请求的概念。而且它阻碍了灵活性,因为有时您可能想要拦截或装饰您在其上执行的某些操作HttpContext
。例如,您可能希望在任何时候从 HttpContext 请求用户详细信息时记录。但是,当您的代码直接依赖于 HttpContext 时,这意味着您被迫在整个代码库中进行彻底的更改。必须在整个代码中进行彻底的更改表明您违反了开放/封闭原则。
相反,在 BL 中定义您自己的抽象并在您的 Web 应用程序中IUserContext
创建一个AspNetUserContext
实现(实现)。IUserContext
请注意,您不应该定义IHttpContext
抽象,因为这仍然会违反 SRP 和 ISP,并且基本上是泄漏抽象(并且泄漏抽象是违反 DIP),因为业务层不必知道存在网络请求。
我可以直接注入 SMTP 依赖
这样做时,您将再次违反Dependency Inversion Principle。您的业务层不依赖于抽象,而是依赖于较低级别的模块(您的 SMTP 类)。这将业务层类与实际的 SMTP 逻辑紧密结合。相反,您应该为此定义自己的抽象,例如IMailSender
.
这可能听起来很奇怪,您可能会觉得您永远不会改变发送消息的方式,因为电子邮件是这样做的唯一方式。但是即使电子邮件存在多年,您也可能希望改变处理电子邮件消息的方式,因为在您当前的实现中,电子邮件消息不会随业务事务自动发送。这意味着您可能已将消息推送到 SMTP 服务器(无法回滚的操作),但之后整个操作仍可能失败。当它失败时,意味着打开的数据库事务被回滚,但此时邮件仍然被发送。您无法将其回拨,并且稍后您将再次发送该邮件消息。
为了缓解这种情况,您必须将邮件消息写入事务队列(例如,包含应发送消息的数据库表)。此操作应在与业务逻辑运行相同的事务中运行。这意味着您可以在同一个事务中对多条消息进行排队,并且当操作失败时它们都会回滚。当操作成功时,所有消息都变得可用,并且一些其他(后台)进程可以提取它们并发送它们。
这只是一种可能的方式。未来邮件的发送方式可能会发生变化,但如果没有IMailSender
抽象,这将更难解决。
Logout等一些方法没有使用DB,明知道不需要使用,为什么还要启动db依赖。
一般来说,当依赖项并不总是被使用时,这不是问题,因为创建对象图(具有所有直接和间接依赖项的服务)应该非常快。但是在您的情况下,您所看到的是您的方法不是很有凝聚力。这表明单一责任违规。相反,您应该为Logout
操作提供自己的类。由于这个操作不需要db,所以这里不需要db依赖。
在我的控制器中,这个问题要大得多,因为我需要加载不止一个 BL,而且我所有的业务类都有相同的难闻气味。
您的控制者也可能违反了单一职责原则。一个 SRP 违规的一个很好的迹象是一个类具有的依赖项的数量。启发式是 4 或 5。超过 5 个依赖项,很可能您的类有太多责任。
当您关注 SOLID 时,您将获得许多小型且重点突出的课程。乍一看,这似乎需要大量的工作和代码,但实际上这会使系统更易于维护。如果您正在为如何创建业务逻辑而苦恼,请查看这篇文章。