4

我正在为网站创建密码重置功能。必须实施密码重置的第一步:

  1. 用户以密码重置形式输入他的电子邮件。
  2. 系统检查是否注册了具有电子邮件的用户。
  3. 如果找到用户,系统将发送带有密码重置 URL 和唯一令牌的电子邮件。
  4. 如果未找到用户,系统会发送电子邮件通知已为此电子邮件启动密码重置,但用户帐户不存在。

我有实现公共方法的服务类 - 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 方法添加实现,并且方法变得越来越复杂。例如,其他步骤可能是检查用户是否已经在另一个相关系统中注册,我可以建议他在我的系统中创建新帐户或为他创建用户帐户。

我正在查看命令模式 - 将服务类重构为单独的命令可能会很好,RequestPasswordReset 可能是这些命令之一。但它并没有解决 RequestPasswordReset 方法中的步骤的主要问题。

我也在研究责任链模式——按顺序处理步骤会很好,但我不知道如何使用它来处理控制流——应该实现不同的条件。此外,看起来每个处理程序都应该执行类似的操作,并且不清楚整个控制流如何变化。

重构此类程序代码的最佳方法是什么?

4

3 回答 3

6

这种方法违反了单一职责原则

其实我觉得不会。该服务的“单一职责”是重置用户的密码,它通过与其他对象(用户存储库和邮件服务)协调来很好地完成这项工作。如果重置密码的过程发生了变化,那么这个类也会发生变化,这并没有错。

于 2012-08-16T06:46:14.897 回答
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);
    }
}

除此之外,我会保持原样。你的问题真的很简单,所以没有理由去寻找一个复杂的解决方案!:)

于 2012-08-16T07:16:48.407 回答
2

使用此代码的最佳方法是确保对其进行彻底测试。确保所有代码路径都经过测试。

然后,克服它

克服所有代码都必须遵守设计模式、单一职责原则和其他类似东西的想法。这些模式是通过检查工作代码发现的。

你在这里有工作代码。克服它并开始下一个任务。

于 2012-08-16T06:51:41.767 回答