2012-03-26 7 views
7

Пытаясь сохранить принципы прагматического программирования, я пытаюсь решить, как обрабатывать изменения пароля пользователя на основе принципа «Сообщить, не спрашивать».Сообщите, не спрашивайте принцип и срок действия пароля

У меня есть объект пользователя, пароль которого истекает каждые 30 дней. Мне нужно показать, что пароль истек/изменил пароль, если пароль истек. Задавать объект, если срок действия пароля истек (состояние), а затем выбрать, какое представление показывать, похоже на нарушение принципа.

Каков наилучший способ справиться с этой ситуацией?

+1

Истечение паролей - глупая вещь. Люди просто склонны использовать дерьмовые, так как им просто удалось запомнить их сложную, когда они должны снова изменить ее. – ThiefMaster

+0

Соответствие PCI не согласуется с вами – Hupperware

+0

@Hupperware, который фигурирует :-p – jnm2

ответ

3

Вы можете передать исключение PasswordExpired из объекта пользователя, когда пароль аутентифицирован, или любую функцию, которую вы вызываете первым для пользователя.

+0

Но это нарушает другой принцип - не контролируйте поток с использованием исключений. Истекший пароль не является исключительной ситуацией. – NOtherDev

+0

Вы не должны использовать исключения для потока управления - они дороги –

+0

Хорошие моменты, спасибо. Однако, если вы хотите придерживаться «Tell, Do not Ask», как вы могли бы справиться с этим без исключений? Возвратить состояние из функции? – GavinCattell

3

Вы должны рассмотреть вопрос о том, имеет ли пользовательский объект метод Validate(), который предоставляет логическое значение (например, контракт поставщика членства) или считает, что метод Validate() возвращает некоторый вид перечисления, который указывает на результат проверки (OK, INVALID_PASSWORD, EXPIRED_PASSWORD и т. Д.).

Существует множество вариантов - бросание исключения не должно быть одним из них, если срок действия пароля истек. Это плохая форма, а также производительность, так как время выполнения должно разматывать стек.

+0

Я никогда не понимал этого аргумента ... стек хорош в том, чтобы раскручивать себя. Это то, что он должен делать. – DanDan

+0

Проведите тест. Напишите консольное приложение, которое выдает исключение и записывает вывод на консоль. Запустите его в режиме отладки. Обратите внимание, сколько времени потребуется для того, чтобы ваше исключение было выбрано и отображено. Там много чего происходит, когда вы бросаете исключение - это дорого. Я также понимаю, что отладка также медленнее, чем запуск в режиме деблокирования, но все еще происходит много, когда вы бросаете исключение. –

+0

Все в порядке ... Я обработаю свой объект исключения, когда он появится, я буду в лучшем месте, чтобы разобраться с проблемой, потому что она полна богатой информации. Мне все равно, нужно ли создавать несколько дополнительных наносекунд. – DanDan

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
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() 

Скажите, Не спрашивай, никаких исключений, и она подчиняется закону Деметры

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 для аутентификации, поскольку у него есть все необходимое для этого.