为了保持实用的编程原则,我试图根据" Tell,Don&#t; Ask"来决定如何处理用户密码更改。原理
我有一个用户对象,其密码每30天到期一次。如果密码已过期,我需要能够显示密码已过期/更改密码视图。如果密码过期(它的状态),然后选择要显示的视图似乎违反了原则,则询问对象。
处理这种情况的最佳方法是什么?
答案 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进行身份验证,因为它拥有执行此操作所需的一切。