告诉,不要问原则和密码到期

时间:2012-03-26 19:47:04

标签: c# asp.net-mvc law-of-demeter tell-dont-ask

为了保持实用的编程原则,我试图根据" Tell,Don&#t; Ask"来决定如何处理用户密码更改。原理

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

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

5 个答案:

答案 0 :(得分: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()

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

答案 1 :(得分:3)

您可以在验证密码或用户首先调用的任何函数时从用户对象中抛出PasswordExpired异常。

答案 2 :(得分:3)

您应该考虑让用户对象具有提供布尔值的Validate()方法(如成员资格提供程序契约那样),或者考虑使用Validate()方法返回某种枚举,指示验证的结果( OK,INVALID_PASSWORD,EXPIRED_PASSWORD等。)。

有很多选项 - 如果密码过期,抛出异常不应该是其中之一。由于运行时必须展开堆栈,因此它的形式不好而且性能也受到了影响。

答案 3 :(得分:1)

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

过期的密码对我来说并不是特例。毕竟它是一个有效的状态(否则你会做一些反对密码到期的东西)

我尝试保持简单,并返回bool或类似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();

答案 4 :(得分: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进行身份验证,因为它拥有执行此操作所需的一切。