我正在为网站创建密码重置功能。必须实现密码重置的第一步:
我有实现公共方法的服务类--RequestPasswordReset,这个方法非常程序化:
public void RequestPasswordReset(string email)
{
if(!IsValidEmail(email))
{
throw new ArgumentException("email");
}
var user = this.repository.FindByEmail(email);
if(user != null)
{
user.PasswordResetToken.Set(this.tokenGenerator.NewToken());
this.emailService.Send(this.from,
user.Email,
"Password reset",
"Your reset url: http://mysite.com/?t=" +
user.PasswordResetToken.Value);
}
else
{
this.emailService.Send(this.from,
user.Email,
"Requested password reset",
"Someone requested password reset at http://mysite.com");
}
}
此方法违反单一责任原则 - 它会检查用户是否存在,重置用户令牌,发送电子邮件。
这种解决方案的主要问题是,如果我需要添加额外的步骤,我必须为RequestPasswordReset方法和方法添加实现变得越来越复杂。 例如,其他步骤可能是检查用户是否已在另一个相关系统中注册,我可以建议他在我的系统中创建新帐户或为他创建用户帐户。
我正在查看Command模式 - 将服务类重构为单独的命令可能会很好,而RequestPasswordReset可能是这些命令之一。但它并没有解决RequestPasswordReset方法中的步骤的主要问题。
我也在关注责任链模式 - 按顺序处理步骤会很好,但我不知道它如何用于处理控制流程 - 应该实现的不同条件。此外,看起来每个处理程序应该执行类似的操作,并且不清楚整个控制流如何更改。
重构此类程序代码的最佳方法是什么?
答案 0 :(得分:6)
此方法违反了单一责任原则
其实我觉得不行。该服务的“单一责任”是重置用户的密码,并通过与其他对象(用户存储库和邮件服务)协调来做到这一点。如果重置密码的过程发生变化,那么这个课程就会改变,并且没有任何问题。
答案 1 :(得分:3)
我认为你的代码很好。如果你绝对想要重构一些东西,你可以将代码分解一点,以简化main方法的可读性;像这样的东西:
public void RequestPasswordReset(string email)
{
ValidateEmail(email); // May throw exception if invalid
var user = this.repository.FindByEmail(email);
if(user != null)
{
GenerateTokenAndSendPasswordResetEmail(user);
}
else
{
SendPasswordResetEmail(email);
}
}
除此之外,我会保持原样。你的问题非常简单,所以没有理由寻找复杂的解决方案! :)
答案 2 :(得分:2)
使用此代码最好的办法是确保对其进行全面测试。确保已测试所有代码路径。
然后,克服它!
认识到所有代码都必须遵守设计模式,单一责任原则和其他类似的东西。通过检查工作代码,发现了 。
你这里有代码。克服它并开始下一个任务。