2012-03-26 13 views
7

Próbując zachować pragmatyczne zasady programowania, staram się decydować o tym, jak radzić sobie ze zmianami hasła użytkownika w oparciu o zasadę "Powiedz, nie pytaj".Powiedz, nie pytaj o zasadę i wygaśnięcia hasła

Mam obiekt użytkownika, którego hasło wygasa co 30 dni. Muszę być w stanie wyświetlić hasło wygasło/zmienić widok hasła, jeśli hasło wygasło. Pytanie do obiektu, jeśli hasło wygasło (jego stan), a następnie wybranie widoku, który wydaje się być naruszeniem zasady.

Jaki jest najlepszy sposób na poradzenie sobie z taką sytuacją?

+1

Wygasłe hasła to głupia rzecz. Ludzie zwykle używają bzdurnych, ponieważ * po prostu * zdołali zapamiętać swój skomplikowany, kiedy muszą go zmienić. – ThiefMaster

+0

Zgodność z PCI nie zgadza się z tobą – Hupperware

+0

@Hupperware, które oznacza: -p – jnm2

Odpowiedz

3

Możesz rzucić wyjątek PasswordExpired od obiektu użytkownika po uwierzytelnieniu hasła lub jakiejkolwiek funkcji, którą wywołasz jako pierwszy użytkownik.

+0

Ale to łamie inną zasadę - nie kontroluj przepływu za pomocą wyjątków. Hasło wygasłe nie jest sytuacją wyjątkową. – NOtherDev

+0

Nie powinieneś używać wyjątków do sterowania przepływem - są one drogie –

+0

Dobre rzeczy, dziękuję. Jeśli jednak chcesz pozostać przy "Powiedz, nie pytaj", jak możesz sobie z tym poradzić bez wyjątków? Zwrócić stan z funkcji? – GavinCattell

3

Powinieneś rozważyć, czy obiekt użytkownika ma metodę Validate(), która zapewnia wartość logiczną (jak ma to miejsce w przypadku umowy dostawcy członkostwa), lub rozważ, czy metoda Validate() zwróci pewnego rodzaju wyliczenie wskazujące wynik sprawdzania poprawności (OK, INVALID_PASSWORD, EXPIRED_PASSWORD itd.).

Istnieje wiele opcji - wyrzucenie wyjątku nie powinno być jednym z nich, jeśli hasło wygasło. Jest to zła forma, a także trafienie wydajnościowe, ponieważ środowisko wykonawcze musi rozwijać stos.

+0

Nigdy nie rozumiałem tego argumentu ... stos jest całkiem niezły w rozwijaniu się. Właśnie to ma zrobić. – DanDan

+0

Wykonaj test. Napisz aplikację konsolową, która zgłasza wyjątek i wypisze dane wyjściowe do konsoli. Uruchom go w trybie debugowania. Zwróć uwagę, ile czasu zajmuje wyrzucenie i wyświetlenie wyjątku. Kiedy rzucasz wyjątek, dzieje się dużo - jest drogi. Rozumiem również, że debugowanie jest wolniejsze niż uruchamianie w trybie zwolnienia, ale nadal dzieje się dużo, gdy rzucisz wyjątek. –

+0

To dobrze ... Poradzę sobie z moim wyjątkowym obiektem, kiedy to nadejdzie, będę w najlepszym miejscu, aby poradzić sobie z problemem, ponieważ jest on pełen bogatych informacji. Naprawdę nie obchodzi mnie, czy skonstruowanie zajmuje kilka dodatkowych nanosekund. – DanDan

1

Osobiście nie lubię programować arround zwracanych wartości/Enum typów. Im więcej typów zwrotów masz, tym więcej ścieżek musisz przetestować/pracować. Poza tym używanie wyjątków do kontrolowania przepływu jest bardzo złą praktyką (chyba, że ​​naprawdę nie możesz znaleźć innej opcji - ale zwykle jest lepsza).

Wygasłe hasło nie jest dla mnie wyjątkowe. Jej prawidłowy stan po wszystkim (Albo chcesz zrobić coś przeciwko hasła wygaśnie w ogóle)

staram się zachować prosty i albo zwrócić bool lub coś jak Func<T> które mogą być bezpośrednio powoływane przez rozmówcę.

Prawdopodobnie coś takiego:

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"); 
     } 
    } 

Po stronie rozmówcy:

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

Tell, nie pytaj, nie ma wyjątków, i przestrzega prawa Demeter

0

Jednym ze sposobów rozwiązania tego problemu jest modelowanie typu 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) { 
    ... 
} 
} 

W ten sposób nie pytasz niczego o inne obiekty domeny, ale powiadamiasz Login o uwierzytelnieniu, ponieważ ma wszystko, co jest potrzebne, aby to zrobić.

Powiązane problemy