I'm looking for some program design guidance.
I have a class library that handles data in a database. I have a winforms app that is the presentation layer for the user to input and manage data. Say for example the user inputs some data and attempts to save it. From the winforms app I do something like:
MyTool theTool = new MyTool();
MyTool.FirstName = this.Textbox1.Text;
MyTool.LastName = this.Textbox2.Text;
//etc...
int result = MyTool.SaveData(); //result is the ID of the inserted record.
MyTool is a type in my class library. Within this type I would have:
public int SaveData()
{
if (IsReadyForInput())
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else
{
throw new ArgumentException("One or more arguments prevented saving the data");
}
return theID
}
private bool IsReadyForInput()
{
if (this.FirstName.Length == 0)
{ return false; }
if (this.LastName.Length == 0)
{return false;}
return true;
}
Now, what I'm interested in is the best design on how exception handling should work. For example the above method is not specific at all so the user doesn't know what's wrong. So I could rewrite this to do something like:
public void SaveData()
{
string errMess = IsReadyForInput();
if (errMess.Length == 0)
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else {
throw new ArgumentException(errMess);
}
return theID
}
private string IsReadyForInput()
{
if (this.FirstName.Length == 0)
{ return "Specify a first name"; }
if (this.LastName.Length == 0)
{return "Specify a last name";}
return true;
}
However it just doesn't seem a very elegant (or fast) method to be comparing string lengths to find an error message. I had tried writing something like:
public void SaveData()
{
ValidateInput();
//..open a DB connection and save out the data
return theID
}
private void ValidateInput()
{
if (this.FirstName.Length == 0)
{ throw new ArgumentException("Specify a first name"; }
if (this.LastName.Length == 0)
{throw new ArgumentException("Specify a first name"; }
}
The problem with this is that the exception is actually thrown by ValidateInput when the front end is calling "SaveData", so when the exception reaches the top, to me, it would seem less clear (especially if there are multiple ways of calling "ValidateInput()" from within MyTool).
Additionally I am not sure what the best way to handle the exception on the front end would be because, if an error is thrown, the ID is never returned.
I guess I am just looking for some guidance on how to handle this situation and validation/error handling in general. Thanks for any help.
The first thing I wonder about is whether you need to throw an exception at all when ordinary control flow might be enough:
if (IsReadyForInput())
{
//..open a DB connection and save out the data
//..get the ID of the saved record
}
else
{
//..do whatever you need in case of invalid input
}
The obvious problem with this suggestion is that we are in a method somewhere in your class library, and some of the desired effects (displaying warnings to the user, etc.) happen in the WinForms layer. That, however, suggests a better solution; namely, to do the validation in the WinForms code:
if (IsReadyForInput())
{
int result = theTool.SaveData();
//...and whatever else should happen.
}
else
{
//..do whatever you need in case of invalid input
}
The above approach is simpler and makes the parts of your program less dependent on each other (as MyTool doesn't need to care about validation of user input) when compared to, e.g., throwing an exception or using special return values to signal failure.
Take a look at FluentValidation (http://fluentvalidation.codeplex.com/). I think it's what you're looking for.
With it you can define your validation rules and call its validation methods. It will return a full list of potential validation errors without causing exceptions to be thrown in your code.
Related
I have seen similar questions, but not exactly this:
I would like to know the right way of determining whether a method is executed correctly or not, returning a boolean, and if the method is not executed know the reason, even if an exception is thrown.
I do it in this way, but I think that return inside the catch is a bad practice, so which is the right way?:
if(!myObject.DoSomething('A', out result))
{
MessageBox.Show(myObject.ErrorMessage);
[...]
}else{
MessageBox.Show(result);
[...]
}
class myObject()
{
public string ErrorMessage;
bool DoSomething(char inputValue, out string result)
{
try
{
if(inputValue == 'A')
{
ErrorMessage = "Bad input value: " + inputValue;
return false;
}
[...]
return true;
}catch(Exception ex){
ErrorMessage = ex.Message;
return false;
}
}
I don't like trhow the exception inside the catch because I lose the control of the application (and I can't get the description), and the exception always finish in the form. And if I show the exception in the form, I don't need try catch in the rest of the classes.
I mean that try {} catch(Exception ex) { throw ex;} is the same as not putting try catch.
thanks a lot
My suggestion would be to create your own Exception type (possibly global), and pass it in as a reference.
Thereafter you can still get back your boolean indicating success or failure (and having only one return outside of the try..catch).
public class CustomException
{
private string _message;
private string _title;
public CustomException()
{
_title = "";
_message = "";
}
public CustomException(string title, string message)
{
_title = title;
_message = message;
}
}
Then call DoSomething passing in an instance of CustomException (ce in this case).
CustomException ce = new CustomException();
Be advised this is the best process to solve the problem of having to return a boolean indicating success or failure and know the message, for example; dumping it to a log file or logging to database (particularly for Service Calls - WCF)
However this is not a solution for bad logic in handling business process.
Return false inside a catch isn't by itself bad practice. It's useful when you handle a piece of code's exceptions and it must not fail.
For example, I'm working on a printer piloting DLL at the time, and this DLL must read a XML file containing multiple records to print. The method must not fail because one record fails to print, but it still can return exception if the XML file is not correctly formated.
public void Print(string xmlFile)
{
if (String.IsNullOrWhiteSpace(xmlFile))
throw new ArgumentNullException("No xml file has been passed to the Print method.");
// This line will most likely throw an exception if the XMl file is not well formated
XDocument dom = XDocument.Load(xmlFile);
foreach (XElement n in dom.XPathSelectElements("//RECORDS/RECORD"))
{
try
{
// send commands to the printer, if the printer fails to print, throw a PrinterRecordException
}
catch (PrinterRecordException e)
{
// log print failure, but keep on printing the rest
continue;
}
catch (Exception e)
{
// dunno what happened, but still have to print the rest
continue;
}
}
}
In this example, my function could return false instead of throwing exceptions to the main program, if this program doesn't care. In my case it does :p In my opinion, that's how you should think your method.
Exception handling methods and best practices are a some-what subjective matter. I cannot attest to the method I'm about to present because I have only just started to use it in my own project.
What I suggest is having a static ExceptionHandler class with which you can register any exception to be handled by Generic Parameter and its corresponding handler. This will decouple your business logic from your UI in case you wanted to display some kind of message box when a particular exception occurs.
Here's an example:
/// the real implementation uses lambda's and/or implementations of IExceptionHandler<TException>
ExceptionHandler.Register<InvalidPasswordException>(() => /*some handler logic*/);
// ... else where in the code ...
catch (InvalidPasswordException ex)
{
// do resource clean-up and raise exception for listeners such as the UI or logging infrastructure.
ExceptionHandler.Raise(ex);
}
So far this looks promising, especially when compared with my previous approaches. But only time will tell.
Update
The ExceptionHandler class itself need not be static, for example you might want to have different instances of ExceptionHandlers at different layers of your application if you are using a layered architecture.
I rewritten my question as I think it was too wordy and maybe what I am trying to achieve was lost.
I written this code in notepad so it may have mistakes and some stuff maybe not well thoughout but it is to illustrate what I see my options are.
// I wrap all code send back from service layer to controller in this class.
public class ResponseResult
{
public ResponseResult()
{
Errors = new Dictionary<string, string>();
Status = new ResponseBase();
}
public void AddError(string key, string errorMessage)
{
if (!Errors.ContainsKey(key))
{
Errors.Add(key, errorMessage);
}
}
public bool IsValid()
{
if (Errors.Count > 0)
{
return false;
}
return true;
}
public Dictionary<string, string> Errors { get; private set; }
public ResponseBase Status { get; set; }
}
public class ResponseResult<T> : ResponseResult
{
public T Response { get; set; }
}
public class ResponseBase
{
public HttpStatusCode Code { get; set; }
public string Message { get; set; }
}
Option 1 (what I am using now)
//controller
public HttpResponseMessage GetVenue(int venueId)
{
if (venueId == 0)
{
ModelState.AddModelError("badVenueId", "venue id must be greater than 0");
if (ModelState.IsValid)
{
var venue = venueService.FindVenue(venueId);
return Request.CreateResponse<ResponseResult<Venue>>(venue.Status.Code, venue);
}
// a wrapper that I made to extract the model state and try to make all my request have same layout.
var responseResult = new ResponseResultWrapper();
responseResult.Status.Code = HttpStatusCode.BadRequest;
responseResult.Status.Message = GenericErrors.InvalidRequest;
responseResult.ModelStateToResponseResult(ModelState);
return Request.CreateResponse<ResponseResult>(responseResult.Status.Code, responseResult);
}
// service layer
public ResponseResult<Venue> FindVenue(int venueId)
{
ResponseResult<Venue> responseResult = new ResponseResult<Venue>();
try
{
// I know this check was done in the controller but pretend this is some more advanced business logic validation.
if(venueId == 0)
{
// this is like Model State Error in MVC and mostly likely would with some sort of field.
responseResult.Errors.Add("badVenueId", "venue id must be greater than 0");
responseResult.Status.Code = HttpStatusCode.BadRequest;
}
var venue = context.Venues.Where(x => x.Id == venueId).FirstOrDefault();
if(venue == null)
{
var foundVenue = thirdPartyService.GetVenue(venueId);
if(foundVenue == null)
{
responseResult.Status.Code = HttpStatusCode.NotFound;
responseResult.Status.Message = "Oops could not find Venue";
return responseResult;
}
else
{
var city = cityService.FindCity(foundVenue.CityName);
if(city == null)
{
city = cityService.CreateCity(foundVenue.CityName);
if(city.Response == null)
{
responseResult.Status.Code = city.Status.Code;
responseResult.Status.Message = city.Status.Message;
return responseResult;
}
CreateVenue(VenueId, city.Response, foundVenue.Name);
responseResult.Status.Code = HttpStatusCode.Ok;
// I don't think I would return a success message here as the venue being displayed back to the user should be good enough.
responseResult.Status.Message = "";
reponseResult.Response = foundVenue;
}
}
return responseResult;
}
}
catch (SqlException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
// maybe roll back statement here depending on the method and what it is doing.
}
// should I catch this, I know it should be if you handle it but you don't want nasty messages going back to the user.
catch (InvalidOperationException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
}
// should I catch this, I know it should be if you handle it but you don't want nasty messages going back to the user.
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
}
return responseResult;
}
// another service layer.
// it is ResponseResult<City> and not city because I could have a controller method that directly calls this method.
// but I also have a case where my other method in another service needs this as well.
public ResponseResult<City> CreateCity(string CityName)
{
ResponseResult<City> responseResult = new ResponseResult<City>();
try
{
City newCity = new City { Name = "N" };
context.Cities.Add(newCity);
context.SaveChanges();
responseResult.Status.Code = HttpStatusCode.Ok;
responseResult.Status.Message = "City was succesfully added";
}
// same catch statmens like above
catch (SqlException ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
responseResult.Status.Code = HttpStatusCode.InternalServerError;
responseResult.Status.Message = GenericErrors.InternalError;
// maybe roll back statement here depending on the method and what it is doing.
}
return responseResult;
}
As you can see the methods are all wrapped in the status codes as they could be directly called by the controller being public. FindCity() and CreateVenue() could also have this wrapping.
Option 2
public HttpResponseMessage GetVenue(int venueId)
{
try
{
if (venueId == 0)
{
ModelState.AddModelError("badVenueId", "venue id must be greater than 0");
if (ModelState.IsValid)
{
var venue = venueService.FindVenue(venueId);
return Request.CreateResponse<ResponseResult<Venue>>(HttpSatusCode.Ok, venue);
}
// a wrapper that I made to extract the model state and try to make all my request have same layout.
var responseResult = new ResponseResultWrapper();
responseResult.Status.Code = HttpStatusCode.BadRequest;
responseResult.Status.Message = GenericErrors.InvalidRequest;
responseResult.ModelStateToResponseResult(ModelState);
return Request.CreateResponse<ResponseResult>(responseResult.Status.Code, responseResult);
}
catchcatch (SqlException ex)
{
// can't remember how write this and too tried to look up.
return Request.CreateResponse(HttpStatusCode.InternalServerError;, "something here");
}
}
public Venue FindVenue(int venueId)
{
try
{
// how to pass back business logic error now without my wrapper?
if(venueId == 0)
{
// what here?
}
var venue = context.Venues.Where(x => x.Id == venueId).FirstOrDefault();
if(venue == null)
{
var foundVenue = thirdPartyService.GetVenue(venueId);
if(foundVenue == null)
{
// what here?
}
else
{
var city = cityService.FindCity(foundVenue.CityName);
if(city == null)
{
city = cityService.CreateCity(foundVenue.CityName);
if(city == null)
{
// what here?
}
CreateVenue(VenueId, city.Response, foundVenue.Name);
}
}
return venue;
}
}
catch (SqlException ex)
{
// should there be a try catch here now?
// I am guessing I am going to need to have this here if I need to do a rollback and can't do it in the controller
// throw exception here. Maybe this won't exist if no rollback is needed.
}
return null;
}
public City CreateCity(string CityName)
{
// if it crashes something I guess will catch it. Don't think I need to rollback here as only one statement being sent to database.
City newCity = new City { Name = "N" };
context.Cities.Add(newCity);
context.SaveChanges();
return newCity;
}
As you see with option 2, I might still need to wrap it in try catches for rollbacks and I am not sure how to handle advanced business validation.
Also with catching everything in the controller and sending back vanilla objects(without my wrapper) I am unsure how to do fine grain HttpStatus codes(say like notFound,Create and such)
Sorry for the brief response, but here is my general rule - if an exception occurs which you expect might happen, deal with it - either by retrying or telling the user something went wrong and giving them options to fix it.
If an unexpected exception occurs, if it's something you can deal with (e.g a timeout which you can retry) try to deal with it, otherwise get out - just think what any MS app does - e.g. office - you get an apology that something went wrong and the app ends. It's better to end gracefully than to potentially corrupt data and leave things in a real mess.
This is an article with Java-specific concepts and examples, but the broad principles here are the way to go.
Distinguish between fault exceptions, which are catastrophic and unrecoverable, and contingency exceptions, which are very much recoverable. Let the faults "bubble" to the fault barrier, where you handle appropriately. For example, you might log the error, E-mail someone or send a message to a message queue, and present the user with a nice, informative error page.
Whatever you do, be sure to preserve all the exception information from the source.
Hope that helps.
Throw an exception wherever your code determines that something has gone wrong.
You always need to handle exceptions in methods which are called directly by the end-user. This is to cater for unexpected errors which your code doesn't have specific handling for. Your generic handling code would typically log the error and may or may not include letting the user know that an unexpected error has occurred.
But if there are errors which you can expect ahead of time, you'll often want to handle these lower down in the code, nearer to the point at which they occur, so that your application can "recover" from the error and continue.
I think exceptions are useful any time you need to return details of a failure from a method, whilst being able to use the ideal return type for the method you're calling.
You said in your question:
Now for me I try to return error messages back to the the controller
and try not to really catch anything in the controller.
If the service method is supposed to ideally return a Venue object, how do you return this potential error message back to the controller? an out parameter? change the return type to something which has an error message property on it?
If you're doing either of those options, I think you're reinventing the wheel... i.e. creating a way to return exception information when one already exists.
Finally, Exceptions are strongly typed representations of what went wrong. If you return an error message, then that is fine to send back to the user, but if you need to programatically do different things based on the details of the error, then you don't want to be switching on magic string.
For example, wouldn't it be handy to differentiate between authorization errors and not found errors so you can return the most appropriate http status code to the user?
Don't forget that the Exception class has a Message property you can simply return to the user if you want to use it that way
To make sure I understand the question, your are creating a web service and want to know when to handle and when to throw exceptions.
In this situation I would strongly recommend that you catch all exceptions. "Unhandled" exceptions are very bad form. On web sites they result in displays that range from meaningless to dangerous by exposing internal information that you do no want the public to see.
If this is a good sized program I suggest that you create your own MyException class which derives from System.Exception. The purpose of this is provide a place for you to add additional information specific to your application. Here are some typical things I like to add to my MyException classes:
An ID number that will help me find the location in the code where the problem occurred.
A "LogMessage" method that logs the exception, sometimes to the Windows Event Log. Whether or not you log and to which log you write depends on what you want recorded, and the severity of the situation.
An indicator that shows the exception has been logged so the above method will not log twice even if it gets called more than once.
Anything else that might be useful given the circumstance.
I also like to put the text of the messages in an external resource file, like an XML document, and key them to the error number that you assign. This allows you to change the error text to improve clarity without having to redeploy the application.
Catch all exceptions and create a new instance of your MyException type and put the original exception into inner exception property. Below the first level of my application, I always throw one of my MyException instances rather than the original exception.
At the top level (application level), NEVER let an exception go unhandled and never throw your own exception. A better way is to return an error code and message in your data contract. That way the client application will only get what you want them to see. The only exceptions they'll need to worry about are the ones outside your scope, i.e. configuration errors or communication failures. In other words if they are able to invoke your service and the network stays connected you should give them a response they can interpret.
Hope this helps.
PS I didn't include a sample exception as I am sure a little searching will find many. Post if you want me to put up a simple sample.
Use try catch at all levels and bubble it up. Optionally, log the error in a file or database. I use text file - tab delimited. Capture at each level
1. Module Name (Use C# supplied methods to get this)
2. Method Name
3. Code Being Executed (User created - "Connecting to database")
4. Error Number
5. Error Description
6. Code Being Executed (User created - "Accessing database")
7. Error Number for the end user
8. Error Description for the end user
Additionally, I also pass a unique identifier like - Session Id in case of Web, Logged in User Id, User Name (if available)
I always have the Exception catch block. In here I set the error number as -0 and the message from the exception object as the error description. If it is SQL Server related - I capture SQL Exception. This generates an error number - I use that.
I want to extend this some more though.
I read several articles regarding good practices in exception handling. Most of it tackled unexpected exceptions yet expected by the author. I just want to clarify and eliminate possible bad practices that I could be doing. Since I already expect these problems to happen already, I assume throwing an exception is a bit redundant.
Let's say I have this code :
string fileName = Path.Combine(Application.StartupPath, "sometextfile.txt");
// There's a possibility that the file doesn't exist <<<<<<<<<<<<<<<<<<<<<
if (!File.Exists(fileName))
{
// Do something here
return;
}
// Therefore, this will return an exception
using (StreamReader file =
new StreamReader(fileName))
{
// Some code here
}
Naturally, what I would do is to inform the user with a MessageBox saying "File not found". Is there an efficient or a better way of doing this?
Another idea that I have is to create an enum which contains expected error codes then create a method which will call a MessageBox showing the error message for that specific situation :
enum ErrorCodes {null, zero, ...}
public void showError(ErrorCodes error)
{
string message;
switch (error)
{
case ErrorCode.null:
{
message = "value cannot be null";
break;
}
case ErrorCode.zero:
{
message = "cannot divide by zero";
break;
}
}
MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
These things are never easy. By definition an exception is (like the Spanish Inquisition) never expected. In your first example the file might exist when you call File.Exist, but then not exist when you try to open it (file deleted, network failed, thumb drive pulled, etc.). As far as a best practice: protect yourself where you can, catch only the exceptions you know how to handle and hope for the best. Programs will fail and the very best thing you can do is make sure that unhandled failures are communicated as clearly as possible to the user of the code (the heart of your second example).
Communicating a failure depends greatly on the what the code does and who is using it. MessageBoxes are often used but generally not 'useful', because if the cause of the error isn't clear to the user about the only thing they can do is send you a jpg image (that's a best case :-D). Providing a way to log problems and/or a custom dialog that allows users to cut/paste information (like a stack trace) is much more useful. Think about the case where a user selects a file and there is a network hiccup. They tell you they got this error about the file not being found, but when you or they look it's there because the network is working correctly by that time. A simple "file not found" message does give you enough information and so you have to tell the user "I don't know, glad it works now" ... this does not inspire confidence. Best practice here is to leave yourself enough 'breadcrumbs' to at least have a rough idea about what has happened. Even something like having a full file path can give you the clues you need to figure out what went wrong.
If the code that is trying to access the file is on the front end, for example an event handler for an on-click, then it's OK to check for the error situation, display a message and return.
If I understand your question correctly you want to know whether you should do this:
public void button_Click() {
if(!File.Exists(textBox.Text)) {
MessageBox.Show("Could not find the file");
return;
}
ProcessFile(textBox.Text); // would have thrown an exception if the file didn't exist
}
That would be fine, except if ProcessFile throws any other kind of Exception it won't be handled.
You could do this:
public void button_Click() {
try {
ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
} catch(Exception ex) {
MessageBox.Show(GetUserMessage(ex));
return;
}
}
In my opinion it's better to do both:
public void button_Click() {
try {
if(!File.Exists(textBox.Text)) {
MessageBox.Show("Could not find the file");
return;
}
ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
} catch(Exception ex) {
MessageBox.Show(GetUserMessage(ex));
return;
}
}
This way you can provide the most specific message to the user relevant to what he was doing at this point. For example if he was trying to open an Excel file you could say "Could not find the Excel file you wanted to import".
This also works in case the file was deleted or renamed between the point you checked and the point you tried to process the file.
Alternatively you could accomplish something similar with this:
public void button_Click() {
try {
if(!File.Exists(textBox.Text)) {
throw new UserException("Could not find the file");
}
ProcessFile(textBox.Text); // throwns an exception if the file didn't exist
} catch(Exception ex) {
MessageBox.Show(GetUserMessage(ex));
return;
}
}
In this case you would create your own Exception class UserException and just pass that message along without translating it. This would allow you to reuse the same code you use to display a message.
Exceptions in Classes
If the error occurs in some class library then you should throw an exception. The purpose of an exception is that an error can't go unnoticed.
For example you shouldn't want this:
class MyFileHandler {
public void OpenFile(string fileName) {
if(!File.Exists(fileName)) return;
// do stuff
}
public void DoStuff() {
// do stuff
}
}
Now if a developer called myFileHandlerInstance.OpenFile("note.txt") he would assumed it worked. You could return a boolean, like so:
class MyFileHandler {
public bool OpenFile(string fileName) {
if(!File.Exists(fileName)) return false;
// do stuff
return true;
}
public void DoStuff() {
// do stuff
}
}
But now you are relying on the developer checking that value, this used to be a common method but errors got ignored and overlooked which is why Exceptions became better practice.
As far as what to display to the user, you really shouldn't display the Exception message directly, those messages are intended for developers not users. I suggest a method that takes an exception object and returns the best message, like so:
public string GetUserErrorMessage(Exception ex) {
if(ex is FileLoadException) {
var fileLoadException = (FileLoadException)ex;
return "Sorry but we failed to load the file: " + fileLoadException.FileName;
}
}
You can inspect the Exception properties for details including error codes if you like. Also I suggest capturing the actual exception details somewhere for your own debugging purposes, somewhere where it's not visible to the user.
I'm a IT student, second year. We just learned to program with 3 layers, one for getting data with a class, one for manipulating stuff with requests (all of the methods go in here) and one for the working of the program itself. Seeing as the first two go into classes instead of a form I dont know how to show errors.
Example:
We need to make a login system with a webbrowser and some other stuff behind it. So I make the login in a class, but how to check back for errors? I don't think it's normal or even possible to do MessageBox.Show(error); from a class, I can only return stuff, but I want the username/id to be returned if possible.
So in short, what is the best/most accepted way to report errors that are caused by data, so from a class?
Your framework level API's (eg. your layers) should use Exceptions for real errors, and return values to report non-critical errors.
public class Login
{
public bool AccountExists(string name) {
bool exists;
// do checking
return exists;
}
public LoginResult Login(string name, string password) {
// Try login
// If successful
return LoginResult.Success;
// What if the user does not exist?
return LoginResult.AccountNotFound;
// What about an error?
return LoginResult.Error;
}
}
public enum LoginResult
{
None,
AccountNotFound,
Error,
Success
}
In the example above, you can report the status of operations through return values. For LoginResult this could even be a value type (struct) that contains more information about the result (eg. a string message or something). Because these types of operations on non-critical, there is no necessity for exceptions here. Exceptions are costly and not always necessary to report errors.
Now let's talk about a different type of error. Logical developer errors. These should be handled by throwing exceptions. Take this example (assume we have some type Account that has a Role property).
public class Foo
{
public bool IsAdmin(Account account) {
if (account == null) {
throw new System.ArgumentNullException("You cannot pass a null account!");
}
return account.Role == "Admin";
}
}
We know as a developer that the account should not be null, so we should check for it and throw an exception if it is. If this exception is ever thrown, its a bug in the calling code and should be fixed not to pass in a null value.
Now that I've given two rough scenarios, how does this apply to your question? These are API's. Whatever your UI layer is, whether it be a WinForm, WPF Window, WebForm, or some other UI, the UI only has to use the API. The API is responsible for reporting information that can be usable by the UI, and the UI is responsible for displaying info in whatever way is best suited for that UI.
The framework API layers should never be responsible for reporting an error to the user with a UI. They should only be responsible for reporting errors to the developer who can take the result, and wire it up to the UI layer in some fashion. You would never display a message box or write to a console from a framework API for example. You would return some result that the UI can use to display its own message.
I highly recommend that you read Framework Design Guidelines. It covers a lot of this material and is an extremely great read.
You should have a class which validates the data object and returns error information. Then your front-end code can ask this class to validate the data and show any error messages that get returned.
var username = GetUserName();
var password = GetPassword();
var validationResult = new Validator().ValidateLogin(username, password);
if(validationResult.ErrorMessage != null) {
MessageBox.Show(validationResult.ErrorMessage);
} else {
// Do what you would have done.
}
If any errors occur that are outside of the expected logic flow, they should throw an exception.
Well you can use Exceptions. You Just throw the exception, it is up to the caller on what to do with the exception.
class Login
{
public Login()
{
}
public bool CheckLogin(string userName, string password)
{
// Do your validation here.
If every thing goes fine
return True.
else
throw Exception("custom message.");
}
}
class Input //class which takes input.
{
Login login = new Login();
public void TakeInput(string username, string password)
{
try
{
login.CheckLogin(username, password);
}
catch(Exception ex)
{
MessageBox.show(ex.message);
}
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
What would a piece of code which "uses exceptions to control flow" look like? I've tried to find a direct C# example, but cannot. Why is it bad?
Thanks
By definition, an exception is an occurrence which happens outside the normal flow of your software. A quick example off the top of my head is using a FileNotFoundException to see if a file exists or not.
try
{
File.Open(#"c:\some nonexistent file.not here");
}
catch(FileNotFoundException)
{
// do whatever logic is needed to create the file.
...
}
// proceed with the rest of your program.
In this case, you haven't used the File.Exists() method which achieves the same result but without the overhead of the exception.
Aside from the bad usage, there is overhead associated with an exception, populating the properties, creating the stack trace, etc.
It's roughly equivalent to a goto, except worse in terms of the word Exception, and with more overhead. You're telling the code to jump to the catch block:
bool worked;
try
{
foreach (Item someItem in SomeItems)
{
if (someItem.SomeTestFailed()) throw new TestFailedException();
}
worked = true;
}
catch(TestFailedException testFailedEx)
{
worked = false;
}
if (worked) // ... logic continues
As you can see, it's running some (made-up) tests; if they fail, an exception is thrown, and worked will be set to false.
Much easier to just update the bool worked directly, of course!
Hope that helps!
Bad
The below code catches an exception that could easily be avoided altogether. This makes the code more difficult to follow and typically incurs a performance cost as well.
int input1 = GetInput1();
int input2 = GetInput2();
try
{
int result = input1 / input2;
Output("{0} / {1} = {2}", input1, input2, result);
}
catch (OverflowException)
{
Output("There was an overflow exception. Make sure input2 is not zero.");
}
Better
This code checks for a condition that would throw an exception, and corrects the situation before the error occurs. This way there is no exception at all. The code is more readable, and the performance is very likely to be better.
int input1 = GetInput1();
int input2 = GetInput2();
while (input2 == 0)
{
Output("input2 must not be zero. Enter a new value.");
input2 = GetInput2();
}
int result = input1 / input2;
Output("{0} / {1} = {2}", input1, input2, result);
Here's a common one:
public bool TryParseEnum<T>(string value, out T result)
{
result = default(T);
try
{
result = (T)Enum.Parse(typeof(T), value, true);
return true;
}
catch
{
return false;
}
}
Probably the grossest violation I've ever seen:
// I haz an array...
public int ArrayCount(object[] array)
{
int count = 0;
try
{
while (true)
{
var temp = array[count];
count++;
}
}
catch (IndexOutOfRangeException)
{
return count;
}
}
I'm currently working with a 3rd party program that does this. They have a "cursor" interface (basically an IEnumerable alternative), where the only way to tell the program you're finished is to raise an exception. The code basically looks like:
// Just showing the relevant section
bool finished = false;
public bool IsFinished()
{
return finished;
}
// Using something like:
// int index = 0;
// int count = 42;
public void NextRecord()
{
if (finished)
return;
if (index >= count)
throw new APIProgramSpecificException("End of cursor", WEIRD_CONSTANT);
else
++index;
}
// Other methods to retrieve the current value
Needless to say, I hate the API - but its a good example of exceptions for flow control (and an insane way of working).
I'm not fond of C# but you can see some similarities between try-catch-finally statements and normal control flow statements if-then-else.
Think about that whenever you throw an exception you force your control to be passed to the catch clause. So if you have
if (doSomething() == BAD)
{
//recover or whatever
}
You can easily think of it in terms of try-catch:
try
{
doSomething();
}
catch (Exception e)
{
//recover or do whatever
}
The powerful thing about exception is that you don't have to be in the same body to alter the flow of the program, you can throw an exception whenever you want with the guarantee that control flow will suddently diverge and reach the catch clause. This is powerful but dangerous at the same time since you could have done actions that need some backup at the end, that's why the finally statement exists.
In addition you can model also a while statement without effectively using the condition of it:
while (!finished)
{
//do whatever
}
can become
try
{
while (true)
{
doSomethingThatEventuallyWillThrowAnException();
}
}
catch (Exception e)
{
//loop finished
}
A module developed by a partner caused our application to take a very long time to load. On closer examination, the module was looking for a config file at app startup. This by itself was not too objectionable, but the way in which it was doing it was outrageously bad:
For every file in the app directory, it opened the file and tried to parse it as XML. If a file threw an exception (because it wasn't XML), it caught the exception, squelched it, and tried the next file!
When the partner tested this module, they only had 3 files in the app directory. The bonehead config file search didn't have a noticeable effect on the test app startup. When we added it to our application, there were 100's of files in the app directory, and the app froze for nearly a minute at startup.
To add salt to the wound, the name of the config file the module was searching for was predetermined and constant. There was no need for a file search of any kind.
Genius has its limits. Stupidity is unbounded.
One example would be using exceptions to return a result from a recursive method:
public void Search(Node node, object data)
{
if(node.Data.Equals(data))
{
throw new ResultException(node);
}
else
{
Search(node.LeftChild, data);
Search(node.RightChild, data);
}
}
Doing something like this is a problem for several reasons.
It's completely counter-intuitive. Exceptions are designed for exceptional cases. Something working as intended should (we hope) never be an exceptional scenario.
You can't always rely on an exception being thrown and propagated to you. For example, if the exception-throwing code runs in a separate thread, you'll need some extra code to capture it.
It is a potential performance problem. There is an overhead associated with exceptions and if you throw a lot of them, you might see a performance drop in your application.
There are a few more examples and some interesting discussion on this subject here.
Disclaimer: The code above is adapted from the first sample on that wiki page to turn it into C#.