Logging in and Exceptions

0 views
Skip to first unread message

Jupiter Moon

unread,
Jan 31, 2006, 8:45:52 AM1/31/06
to C# Design Patterns
OK, exceptions are a tricky subject. My thinking has always been to
only use exceptions when something exceptional happens - i.e. the
normal flow of a program (or component) cannot continue.

For example a FileLoader class with a LoadFile(fileName) method - if a
file asked to load does not exist then normal execution cannot
continue.

Also, a way to avoid an exception should, where possible, be provided.
In the above example the answer would be to add a
DoesFileExist(fileName) method to the FileLoader class. This allows
the user of the object to do:
if(FileLoader.DoesFileExist(fileName)
{
File file = FileLoader.LoadFile(fileName);
}
else
{
ShowMessage("File {0} could not be found", fileName);
}

So, how should a Login to an application be handled? If the wrong
details are provided should an exception be thrown or should an
LoginStatus object be returned providing details to the failure? Also,
DoesUserExist() does not nessasarily apply to a Login scenario -
especially seeing that logging in is a black or white situation. And,
does a failure to login prevent normal flow or is a login failure just
a branching of a normal flow?

Grateful for input.

Glenno

unread,
Feb 1, 2006, 7:45:10 AM2/1/06
to C# Design Patterns
I would design the system not to throw a exception but as another
branch in the normal flow for the login process. It would possibly be
better to return an enum that contains the possible login states from
the login function. e.g.

public enum LoginStatus
{
Authenticated,
BadUsername,
BadPassword,
UserNotFound,
AccountLocked
}

The authentication method that would return the result would be apart
of the business/application logic layer. Then in the presentation layer
you could decide what degree of info you would disclose to the user.
i.e. not much info = "bad username or password" or more info = "your
username doesn't exist"

As far as exceptions go in general, I would agree with your statement:


"only use exceptions when something exceptional happens - i.e. the
normal flow of a program (or component) cannot continue."

There is a good article on exceptions at:

din...@gmail.com

unread,
Feb 10, 2006, 9:49:58 AM2/10/06
to C# Design Patterns
There must be a process for this scenario. after user submited his/her
user ID, the system should check it. that's biz process logic, but not
an exception.

Bram

unread,
Feb 24, 2006, 6:21:01 PM2/24/06
to C# Design Patterns
Deciding where and when to use exceptions can be tricky. Some argue
that exceptions should only be used for critical errors. Throwing an
exception is not cheap in terms of cpu cycles because for each
exception a stack trace is built. When performance is critical, your
best bet might be to try to avoid exceptions as much as possible.

However, Exceptions can be very helpful when trying to write software
that works correctly. When done right, using exceptions liberally can
make an application more robust.

Microsoft has taken this path. Whenever something happens which is not
in line with the expected program flow, an Exception is thrown.
Although hardly a critical error, Int32.Parse("not an integer") throws
an Exception.

Partially it's a matter of taste. I use Exceptions a lot because I
prefer erring on the side of correctness to erring on the side of
performance. Also, I tend to perceive code using lots of exceptions as
being more readable.

For instance, for a login system, quite probably you'd create a User
class containing user information:

class User {
public string Username {}
public string PasswordHash {}
}

If this class would store all users, it would have to provide means to
access the invidual user objects:

public static User ByUserName(string username);

Basically, there would be two methods to handle an unknown username:
1) Throwing an exception
2) Returning null

I believe throwing an Exception is the better strategy. Strategy #2
requires ALL the code to check for null. If this check is omitted,
there is the risk of a NullPointerException, which does little to
explain what went wrong.

Therefore if I had to write login code it'd look kinda like this:

public Session Login(string username, string password) {
User user = User.ByUserName(username); // throws an exception if
user not found
if(user.HasPassword(password)) {
return new Session(user);
} else {
throw new InvalidPasswordException(username);
}
}

Hope it helps!
Cheers,
Bram

Michael Hamrah

unread,
Mar 8, 2006, 9:03:42 PM3/8/06
to C# Design Patterns
The framework design guidlines book by Brad Abrams and Krystof Cwalina
makes a strong case for using exceptions liberaly, in fact, they even
point out that returning error codes are in general a bad idea.
Personally, I disagree, and believe that exceptions should be used
conservatively. I guess the way they invisioned the login example
would be to come up with a series of exception classes
(BadPasswordException, BadUserNameException), and handle them
accordingly in various catch blocks. This will allow you to handle or
bubble the exception through the various tiers (you could log it one
tier, show it to a user in another, possibly redirect).

No matter what you do- error codes, enums, bools, you still have to
program against the error logic. Exceptions provide a more structured
approach at the cost of performance. Error codes can change
arbitrarily, enums are safer but handling error paths could slip
through the cracks. In general, users are probably not going to be
failing logins a lot, are they? I guess in the end what do you think
will be better:

try {
User.Login(username, password);
}
Catch(NoUserException ex)
{
ShowRegisterUser();
}
Catch(InvalidPasswordExcetion ex)
{
ShowBadPasswordMessage();
}
Catch(Exception ex)
{
ShowGenericError();
}
Finally
{
ShowHomePage();
}

Or
myLoginStatusEnum = User.Login(Username, Password);
switch(myLoginStatusEnum)
{
case Success:
ShowHomePage(); break;
case InvalidUser: SHowRegister(); break;
Default: Uh-oh, the enum values have changes, what do i do! Or do i
login? Is the user null? What to do then?

}

I guess exceptions are the safest bet in terms of structured control
flow under various scenarios.

Glenno

unread,
Mar 9, 2006, 7:50:36 PM3/9/06
to C# Design Patterns
Michael,

With your case statement, it should be used that unless the user is
explicitly authenticated (i.e. User.Login() returns LoginStatus.Sucess)
that the login attempt should fail. From there it is up to the
developer to how they handle the failure info given (BadUsername,
BadPassword, UserNotFound, AccountLocked ...Other) that means that the
default statement in a switch is an unknown/generic failure.

Reply all
Reply to author
Forward
0 new messages