Скажите, не спрашивайте принцип и срок действия пароля
Пытаясь придерживаться прагматических принципов программирования, я пытаюсь решить, как обрабатывать изменения пароля пользователя, основываясь на принципе "говори, не спрашивай".
У меня есть объект пользователя, пароль которого истекает каждые 30 дней. Я должен быть в состоянии показать пароль истек / изменить пароль, если срок действия пароля истек. Запрос объекта, если срок действия пароля истек (его состояние), а затем выбор вида для отображения, кажется нарушением принципа.
Каков наилучший способ справиться с этой ситуацией?
5 ответов
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()
Скажите, не спрашивайте, без исключений, и он подчиняется закону Деметры
Вы можете выдать исключение PasswordExpired из объекта пользователя, когда пароль аутентифицирован, или любую функцию, которую вы сначала вызываете для пользователя.
Вам следует подумать о том, чтобы пользовательский объект имел метод Validate(), который предоставляет логическое значение (как это делается в контракте с поставщиком членства), или подумал о том, чтобы метод Validate() возвращал какое-то перечисление, которое указывает результат проверки (ОК, INVALID_PASSWORD)., EXPIRED_PASSWORD и т. Д.).
Есть много вариантов - исключение не должно быть одним из них, если срок действия пароля истек. Это плохая форма, а также снижение производительности, так как среда выполнения должна разматывать стек.
Я лично не люблю программировать возвращаемые значения / 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();
Одним из способов решения этой проблемы является моделирование ОО, например, так:
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 для аутентификации, поскольку у него есть все необходимое для этого.