7

为了遵循实用的编程原则,我试图根据“告诉,不要问”原则来决定如何处理用户密码更改。

我有一个用户对象,其密码每 30 天过期一次。如果密码过期,我需要能够显示密码过期/更改密码视图。询问对象密码是否过期(它的状态)然后选择显示哪个视图似乎违反了原则。

处理这种情况的最佳方法是什么?

4

5 回答 5

4
login
   model.validate();
   return model.show(self);

passwordExpired()
  return View("ChangePassword")

loginSuccess()
  return View("default")

class User
  show(aController)
      if passwordExpired
          return aContoller.passwordExpired()
     else return aContoller.loginSuccess()

告诉,不问,没有例外,它遵守得墨忒耳法则

于 2012-03-26T21:45:59.543 回答
3

当密码通过身份验证时,您可以从用户对象中抛出 PasswordExpired 异常,或者您首先在用户上调用的任何函数。

于 2012-03-26T19:49:48.690 回答
3

您应该考虑让用户对象有一个提供布尔值的 Validate() 方法(就像会员提供者合同一样),或者考虑让 Validate() 方法返回某种指示验证结果的枚举(OK,INVALID_PASSWORD , EXPIRED_PASSWORD 等)。

有很多选择——如果密码过期,抛出异常不应该是其中之一。这是一种糟糕的形式,并且由于运行时必须展开堆栈,因此也会影响性能。

于 2012-03-26T19:55:10.657 回答
1

我个人不喜欢编写 arround 返回值/Enum类型。您拥有的返回类型越多,您必须测试/使用的路径就越多。此外,使用异常来控制流程是一种不好的做法(除非您真的找不到任何其他选择 - 但通常有更好的选择)。

过期的密码对我来说并不是什么特别的事情。毕竟它是一个有效的状态(否则你会做一些反对密码过期的事情)

我尽量保持简单,并返回 abool或类似 a 的东西Func<T>,可以由调用者直接调用。

大概是这样的:

public class User
    {
        private DateTime _lastChangeDate;
        public Action Validate()
        {
            if (_lastChangeDate >= DateTime.Now.AddDays(-30))
            {
                return new Action(() => this.Login());
            }
            else
            {
                return new Action(() => this.ChangePassword());
            }
        }
        private void Login()
        {
            Console.WriteLine("Login");
        }
        private void ChangePassword()
        {
            Console.WriteLine("Change Password");
        }
    }

在调用方:

user.Validate().Invoke();
于 2012-03-26T20:54:21.980 回答
0

解决此问题的一种方法是像这样的 OO 建模:

public class Login {

private String userName;
private String password;
private Date expirationDate;    

public void authenticate(String password) {
    if (this.password.equals(password) {
        redirectoToMainOrEditPage();
    } else {
        redirectToFailPage();
    }
}

private void redirectToMainOrEditPage() {
    Date today = new Date();

    if (today.before(expirationDate)) {
        redirectToMainPage();
    } else {
        redirectToEditPage();
    }
}

private void redirectToMainPage() {
    ...
}

private void redirectToEditPage() {
    ...
}

private void redirectToFailPage() {
    ...
}

public void changePassword(String newPassword) {
    ...
}

public void changeExpirationDate(Date newDate) {
    ...
}
}

这样您就不会向其他域对象询问任何内容,而是告诉 Login 进行身份验证,因为它拥有执行此操作所需的一切。

于 2013-01-26T18:02:52.513 回答