We got in argument with co-worker about the patterns of flow control and general code design. Need your opinion – which is the better/cleaner/preferred way of writing the code ?
This is for MVC 3, but that doesn’t really matter.
Version 1:
public ActionResult Login(LoginData loginData)
{
if (!ModelState.IsValid)
{
ShowGlobalError("Invalid credentials.");
return View(loginData);
}
UserProfile profile = null;
try
{
// see if we have profile with those credentials
profile = this.RetrieveUserProfile(loginData.Email.Trim(), loginData.Password.Trim()); // this just goes to db and tries to get user profile. Returns null if profile isn't found
}
catch (Exception ex)
{
ShowGlobalError("DB is down");
LogError(...);
return View(loginData);
}
if (profile == null)
{
// nope, we don't.. ask again
ShowGlobalError("Invalid credentials.");
return View(loginData);
}
// ok, we're good
Session["Profile"] = profile;
FormsAuthentication.SetAuthCookie(profile.Email, false);
FormsAuthentication.RedirectFromLoginPage(profile.Email, loginData.EnablePermanentCookie);
return View(loginData);
}
Version 2:
public ActionResult Login(Credentials credentials){
try{
PersonalProfile profile = AuthenticateUser(credentials);
SetProfileSessionstate(profile); // this does 'Session["Profile"] = profile;'
SetFormsAuthenticationAndRedirect(profile);
}
catch(Exception ex){
ShowGlobalError("invalid login, please try again.");
}
return View(credentials);
}
public void SetFormsAuthenticationAndRedirect(PersonalProfile profile){
FormsAuthentication.SetAuthCookie(profile.Email, loginData.EnablePermanentCookie);
FormsAuthentication.RedirectFromLoginPage(profile.Email, loginData.EnablePermanentCookie);
}
Version 1 is littered with return statements, version 2 is using try/catch for flow control.
So, which is the better way, or are we both doing it wrong, and there’s a better way you can share ?
Thanks !
I like #1 much better than #2
no.2 is lazy coding
no.1 explicitly capture errors
it is not a good idea to rely on exceptions to catch logic mistakes or errors
in #2, if profile is null, you do not check that and rely on throwing exception to catch that exceptions are expensive operations in general
and should only be relied on for unforseen logic outcomes (Exceptions!)