加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

.net – Real Life与SOLID开发合作

发布时间:2020-12-16 03:42:22 所属栏目:asp.Net 来源:网络整理
导读:最近我学习了SOLID开发,现在我遇到了一些挑战,当它是一个好的练习时,什么时候不是. 例如,我开发了一个包含成员的网站.我构建了一个Authentication Business Logic类,它可以解决身份验证方案,它们是: 登录用户 登录用户 注册用户 恢复用户密码 这个类有4个依
最近我学习了SOLID开发,现在我遇到了一些挑战,当它是一个好的练习时,什么时候不是.

例如,我开发了一个包含成员的网站.我构建了一个Authentication Business Logic类,它可以解决身份验证方案,它们是:

>登录用户
>登录用户
>注册用户
>恢复用户密码

这个类有4个依赖项:

>数据库/服务
> HttpContext(用户状态)
> ValidationRules(一些其他业务逻辑规则,以便登录用户)
> SMTP – 用于发送

现在感觉有些代码有难闻的气味,因为没有使用依赖注入.

我不确定的一些问题:

>我可以直接将SMTP依赖注入到Restore password&注册方法,因为所有其他方法都与它无关.我是不是该?
> Logout等一些方法没有使用DB,当我知道不需要使用它时,为什么要启动db依赖项.
>这是我的一些业务逻辑.在我的控制器中,这个问题要大得多,因为我需要加载多个BL并且我的所有业务类都有相同的难闻气味……

我觉得我做错了什么,请帮忙!

解决方法

an Authentication Business Logic class that should work out the
authentication scenarios,which are: Login user,Get logged in user,
Register user,Recover user password.

您的身份验证业务逻辑类已经违反了Single Responsibility Principle.虽然您可能认为该类的唯一责任是“身份验证”,但这很难被称为一种责任,因为您可以实现一百个处理身份验证的用例,这会导致一个丑陋的大屁股班.那个班级还有一个责任吗?相反,每个类实现一个用例.在这种情况下,你的课程将有一个非常明确和狭隘的责任.

HttpContext (for user state)

你的业务逻辑不应该对所使用的技术有任何了解(除了它当然是.NET,我们不能真正抽象.NET),因此它不应该依赖于HttpContext.取决于HttpContext违反Dependency Inversion Principle(DIP)和Interface Segregation Principle(ISP).

DIP说“高级模块应该……取决于抽象.”您的业??务层是“更高级别的模块”,但它不依赖于抽象,而是依赖于较低级别的模块(HttpContext).这将业务层类与实际的Web逻辑紧密结合在一起.

此外,即使您将使用System.Web.HttpContextBase抽象,您仍将依赖于由较低级别模块定义的抽象,而根据DIP“摘要由上层/策略层拥有” .这背后的想法是你不希望你的代码强烈依赖于较低层,因为这会使更高层的层更依赖于此,除此之外,较低层的层无法定义一个抽象.纠正你的申请.接下来将表达此问题.

ISP声明“不应该强迫任何客户端依赖它不使用的方法”.换句话说,抽象应该根据客户的特殊需求而定制,并且应该是狭窄的. “这种缩小的接口也称为角色接口”. HttpContext和HttpContextBase都违反了ISP,因为它们非常广泛并且适用于一般用途.他们是一个大的国家坏,一切都是一个字符串.这会导致您的代码使用非常广泛的API,这使得该API更难使用.它也阻碍了可测试性,因为它不可能伪造HttpContext,甚至抽象的HttpContextBase也不会令人讨厌.如果您应用ISP,您的生产代码和测试代码将变得更加清洁.它还会阻碍应用程序的可重用性,因为您可能希望稍后在后台进程中运行业务逻辑的某些部分,而不会出现Web请求的概念.它会阻碍灵活性,因为有时您可能想拦截或修饰在HttpContext上执行的某些操作.例如,您可能希望在从HttpContext请求用户详细信息时记录.但是,当您的代码直接依赖于HttpContext时,这意味着您必须在整个代码库中进行彻底的更改.必须在整个代码中进行彻底更改,这表明您违反了Open/Closed Principle.

相反,在BL中定义自己的IUserContext抽象,并在Web应用程序中创建一个AspNetUserContext实现(实现IUserContext).请注意,您不应该定义IHttpContext抽象,因为这仍然会违反SRP和ISP,并且基本上是漏洞抽象(漏洞抽象是DIP违规),因为业务层不应该知道是否存在网络请求.

I can inject SMTP dependency directly

执行此操作时,您将再次违反Dependency Inversion Principle.您的业务层不依赖于抽象,而是依赖于较低级别的模块(您的SMTP类).这将业务层类与实际的SMTP逻辑紧密结合在一起.相反,您应该为此定义自己的抽象,例如IMailSender.

这可能听起来很奇怪,您可能会觉得永远不会改变邮件的发送方式,因为电子邮件是唯一的方法.但即使电子邮件多年来一直存在,您也可能希望更改电子邮件的处理方式,因为在当前的实现中,电子邮件不会随业务事务原子发送.这意味着您可能已将消息推送到SMTP服务器(无法回滚的操作),但此后总操作仍可能失败.当它失败时,意味着回滚打开的数据库事务,但此时仍然发送邮件.您无法回拨,最后您将再次发送该邮件.这将使您的接收器烦恼,甚至可能导致您在回滚事务后发送不再存在的信息(如包含数据库ID的URL).

要缓解这种情况,您必须将邮件消息写入事务性队列(例如,包含应发送消息的数据库表).此操作应在与业务逻辑运行相同的事务中运行.这意味着您可以在同一事务中对多个消息进行排队,并且在操作失败时它们都会回滚.当操作成功时,所有消息都可用,而其他一些(后台)进程可以接收并发送它们.

这只是一种可能的方式.发送邮件的方式将来可能会发生变化,但如果没有IMailSender抽象,这将很难修复.

Some methods such as Logout are not using the DB,why should I
initiate db dependencies when I know that I will not need to use it.

一般情况下,当依赖关系并不总是被使用时,这不是一个问题,因为创建对象图(具有所有直接和间接依赖关系的服务)should be very fast.但在您的情况下,您目击的是您的方法不是’非常有凝聚力.这表明单一责任违规.相反,您应该为Logout操作提供自己的类.由于此操作不需要db,因此您不需要db依赖项.

In my controllers this issue is much bigger since I need to load more
then one BL and all my business classes have same bad smell..

您的控制器也可能违反单一责任原则. SRP违规的一个很好的指示是一个类具有的依赖数.启发式是4或5.有超过5个依赖项,你的班级很可能有太多的责任.

当您按照SOLID进行操作时,您将获得许多小型和专注的课程.这看起来好像很多工作和代码,但实际上这会导致系统更容易维护.如果您在如何创建业务逻辑方面苦苦挣扎,请查看this article.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读