Say don’t ask for password principle and expiration

Trying to adhere to the principles of pragmatic programming, I am trying to decide how to handle user password changes based on the principle of "Tell, Do not Ask".

I have a user object whose password expires every 30 days. I need to show that the password has expired / changed the password if the password has expired. Set the object if the password has expired (it is specified), and then choose which view to show, it seems to violate the principle.

What is the best way to deal with this situation?

+7
source share
5 answers
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() 

Say don't ask, no exceptions and he obeys Demeter’s law

+4
source

You can throw a PasswordExpired exception from the user object when the password is authenticated, or any function that you call first for the user.

+3
source

You must consider that the user object has a Validate () method that provides a boolean value (for example, a membership provider contract) or it is considered that the Validate () method returns some kind of enumeration that indicates the result of the check (OK, INVALID_PASSWORD, EXPIRED_PASSWORD, etc. .d.).

There are many options - throwing an exception should not be one of them if the password has expired. This is a bad form, as well as performance, since runtime should spin the stack.

+3
source

I personally don't like programming arround / Enum return values. The more return types you have, the more ways you should test / work with. Also, using exceptions for the control flow is bad practice (if you really cannot find any other option, but it is usually better).

The expired password is not exclusive to me. Its legal state in the end (otherwise you would do something against passwords to expire at all)

I am trying to keep it simple and either return a bool or something like Func<T> that could be called by the caller.

Maybe something like this:

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

From the side of the subscriber:

 user.Validate().Invoke(); 
+1
source

One way to solve this is OO modeling as follows:

 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) { ... } } 

Thus, you do not ask anything for other domain objects, but tell Login for authentication, since it has everything you need for this.

0
source

All Articles