Methods that return meaningful return values - c#

I work in C#, so I've posted this under C# although this may be a question that can be answered in any programming language.
Sometimes I will create a method that will do something such as log a user into a website. Often times I return a boolean from the method, but this often causes problems because a boolean return value doesn't convey any context. If an error occurs whilst logging the user in I have no way of knowing what caused the error.
Here is an example of a method that I currently use, but would like to change so that it returns more than just 0 or 1.
public bool LoginToTwitter(String username, String password)
{
// Some code to log the user in
}
The above method can only return True or False. This works well because I can just call the following:
if(http.LoginToTwitter(username, password))
{
// Logged in
} else {
// Not Logged in
}
But the problem is I have no way of knowing why the user wasn't logged in. A number of reasons could exist such as: wrong username/password combination, suspended account, account requires users attention etc. But using the following method, and logic, it isn't possible to know this.
What alternative approaches do I have?

You could create and return an enum with expected LoginResults.
public enum LoginResult
{
Success,
AccountSuspended,
WrongUsername,
WrongPassword,
}
Then return using the enum type in your method:
public LoginResult LoginToTwitter(String username, String password)
{
// Some code to log the user in
}

You could choose to either throw an exception with a relevant message attached (and have the calling method deal with the exception), or have the function return an enum with different states (such as LoginState.Success, LoginState.IncorrectPassword, etc.).
If you are using exceptions, it's probably best to have your function return nothing (public void LoginToTwitter), but if you're using an enum, make sure the set the return type to the name of your enum (public LoginState LoginToTwitter).

There are two standard ways. If you're interested in just the outcome, but not any metadata, return some enum instead. Set the available values to Success, Suspended, etc. (all your possible outcomes)
If you need some more details, you can always use exceptions. Basically follow the "tell, don't ask" idea and write your function in a way that it returns required values (user id for example? or maybe nothing if you have some global login state) only on success and throws an exception with detailed description of the failure otherwise. Regarding the hierarchy itself, you should most likely implement a LoginException with some more specific subclasses and catch only those. (it makes it easy to verify all relevant exceptions are handled and all unknown ones are passed to higher levels)

Both returning an enum or throwing an exception, as suggested in other answers, are reasonable. But my preference is to return an exception. Sounds crazy, but it lets your caller decide whether to use error checking or exception handling. And, unlike the enum, exceptions are hierarchical, so it makes it much easier to handle entire categories of failures, and can carry arbitrary extra data.
I think Sayse had a similar idea, but he deleted his answer and never really explained it either.

According to clean code tendency you should provide a meaningfull name for your method that reveal intent.
For to know what happened if logging operation could no be completed you can introduce in your flow Exceptions and handle it in the caller context.
see http://msdn.microsoft.com/en-us/library/ms173160(v=vs.80).aspx

You can use an idiom that is frequently used in c. The result of an assignment expression is the expression itself - this means you can capture a result code at the same time as evaluating whether it's a particular value:
if ((status = DoSomething()) == AnErrorEnum.NotAnError)
{//success handler
}
else
{//failure handler
}
I was asked to provide a link to an MSDN article - here is an old version of the spec:
http://msdn.microsoft.com/en-us/library/aa691315(v=vs.71).aspx
"The result of a simple assignment expression is the value assigned to the left operand. The result has the same type as the left operand and is always classified as a value."

Related

What type of Exception should I throw when an unknown value is passed into a switch statement

Edit 1
Updated to make the enum not an argument to the method...
Question
This type of problem comes up a lot with enums in switch statements. In the example code, the developer has accounted for all countries the program is currently using, but if another country is added to the Country enum, an exception should be thrown. My question is, what type of exception should be thrown?
Example Code:
enum Country
{
UnitedStates, Mexico,
}
public string GetCallingCode(Guid countryId){
var country = GetCountry(countryId);
switch (country)
{
case Country.UnitedStates:
return "1";
break;
case Country.Mexico:
return "52";
break;
default:
// What to throw here
break;
}
}
I've looked at
NotImplemented, The exception that is thrown when a requested method or operation is not implemented.
NotSupported There are methods that are not supported in the base class, with the expectation that these methods will be implemented in the derived classes instead. The derived class might implement only a subset of the methods from the base class, and throw NotSupportedException for the unsupported methods.
For scenarios where it is sometimes possible for the object to perform the requested operation, and the object state determines whether the operation can be performed, see InvalidOperationException.
InvalidOperation is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments.
My guess is either NotImplemented or Invalid Operation. Which one should I use? Does someone have a better option (I know rolling your own is always an option)
I would go with ArgumentException, as the agrument is invalid.
EDIT: http://msdn.microsoft.com/en-us/library/system.argumentexception%28v=vs.71%29.aspx
There is also InvalidEnumArgumentException, which might more accurately describe the problem, however, I have not seen anyone use it before.
One option is to do almost a method contracts check in Debug mode. Throw in an extension method for nice looking form:
[Conditional("DEBUG")]
public static bool AssertIsValid(this System.Enum value)
{
if (!System.Enum.IsDefined(value.GetType(), value))
throw new EnumerationValueNotSupportedException(value.GetType(), value); //custom exception
}
I figured maybe only have it in debug mode so it passes your development/test environment and unit tests and in production there's no overhead (though that's up to you)
public string GetCallingCode(Guid countryId)
{
var country = GetCountry(countryId);
country.AssertIsValid(); //throws if the country is not defined
switch (country)
{
case Country.UnitedStates:
return "1";
case Country.Mexico:
return "52";
}
}
I would suggest though that this is actually the responsibility of your GetCountry method. It should recognize that the countryId is not valid and throw an exception.
Regardless, this should really be caught by your unit tests too or somehow better handled. Wherever you convert a string/int into your enum should be handled by a singular method which in turn can check/throw (just as any Parse method should) and have a unit test that checks all valid numbers.
In general, I don't think the various ArgumentExceptions (and the like) are a good candidate because there are several conditions (non-argument) cases. I think if you move the checking code to a single spot, you may as well throw your own exception that accurately communicates to any developer listening.
EDIT: Considering the discussion, I think there are two particular cases here.
Case 1: Converting underlying type to an equivalent enum
If your methods take some sort of input data (string, int, Guid?), your code performing the conversion into the enum should validate that you have an actual enum that's usable. This is the case I posted above in my answer. In such cases, likely throwing your own exception or possibly InvalidEnumArgumentException.
This should be treated pretty much like any standard input validation. Somewhere in your system you are providing garbage-in so handle it as you would any other parsing mechanism.
var country = GetCountry(countryId);
switch (country)
{
case Country.UnitedStates:
return "1";
case Country.Mexico:
return "52";
}
private Country GetCountry(Guid countryId)
{
//get country by ID
if (couldNotFindCountry)
throw new EnumerationValueNotSupportedException(.... // or InvalidEnumArgumentException
return parsedCountry;
}
EDIT: of course, the compiler requires that your method throws/returns, so not so sure what you should do here. I guess that's up to you. If that actually happens, it probably is a bone-headed exception (case 2 below) since you passed your input validation yet did not update the switch/case to handle the new value, so maybe it should throw new BoneheadedException();
Case 2: Adding a new enumeration value which is not handled by your switch/case blocks in your code
If you are the owner of your code, this falls under the "Boneheaded" exceptions described by Eric Lippert in #NominSim's answer. Though this can actually not result in an exception at all while leaving the program in an exceptional/invalid state.
The best for this is likely any place where you perform switch/case (or of the like) runs against the enumeration, you should consider writing a unit test that automatically runs the method against all defined values of your enumeration. So if you are lazy or accidentally missed a block, your unit tests will warn you that you did not update a method to account for the change in your enumeration listing.
Finally, if your enum is coming from a 3rd party which you did not realize they updated the values, you should write a quick unit test that validates all your expected values. So if you wrote your program with checks for UnitedStates and Mexico, your unit test should just be a switch/case block for those values and throw an exception otherwise warning you when/if they end up adding Canada. When that test fails after updating the 3rd party library, you know what/where you have to make changes to be compatible.
So in this "Case 2", you should throw any old exception you want since it will be handled by your unit tests just so long as it accurately communicates to you or consumers of your unit tests just what exactly is missing.
In either case, I don't think the switch/case code should be caring too much about invalid input and not throwing exceptions there. They should either be thrown at design time (via unit tests) or thrown when validating/parsing input (and therefore throw appropriate "parsing/validation" exceptions)
EDIT: I stumbled upon a post from Eric Lippert discussing how the C# compiler detects if a method with a return value ever hits its "end point" without returning. The compiler is good at guaranteeing that the end point is unreachable sometimes, but in cases as yours above, we developers know it's unreachable (except in the circumstances noted above where BoneheadedExceptions come into play).
What wasn't discussed (at least that I saw) what you should do as a developer to resolve these cases. The compiler requires that you provide a return value or throw an exception even if you know it will never reach that code. Googling hasn't magically surfaced some exception to leverage in this case (though I couldn't figure out good search terms), and I'd rather throw an exception and be informed that my assumption that it cannot reach the end is incorrect rather than returning some value which may not inform me of the problem or result in unwanted behaviour. Maybe some UnexpectedCodePathFailedToReturnValueException of some sort would be most valid in this case. When I have some time, I'll do some more digging and maybe post a question on programmers to garner some discussion.
Of the exceptions you've listed, only InvalidOperationException fits your scenario. I would consider using either this, or either ArgumentException or the more specific ArgumentOutOfRangeException since your switch value is provided as an argument.
Or, as you say, roll your own.
EDIT: Based on your updated question, I would suggest InvalidOperationException if you want to use a framework exception. However, for this more generic case, I would definitely prefer to roll my own - you can't guarantee that InvalidOperationException won't be caught elsewhere in the callstack (possibly by the framework itself!), so using your own exception type is much more robust.
I would use InvalidOperationException if the value you're working with is a product purely of your object's current state. As it says:
The exception that is thrown when a method call is invalid for the object's current state.
Even with your updated question, since the particular value you cannot deal properly with was derived from an argument passed to it, I would still use an ArgumentException - you can explain in the error message that information you're derived from the argument doesn't match anything you can deal with.
For both NotImplementedException and NotSupportedException the expectation is that, no matter what the caller does, they're not going to be able to remedy the situation. Whereas ArgumentException and InvalidOperationException are clues that, if the caller would use a different argument, or transition the object to another state (respectively), the call might work.
Personally, I don't think this is the proper place for any Exception at all. If you add a Country, you should add a case to the switch statement. The code shouldn't break because you add a value to an enum.
There is an article on when to use exceptions by Eric Lippert, that categorizes the type of exception you are looking for as: (forgive the wording it is not mine)
Boneheaded exceptions are your own darn fault, you could have prevented them and therefore they are bugs in your code. You should not catch them; doing so is hiding a bug in your code. Rather, you should write your code so that the exception cannot possibly happen in the first place, and therefore does not need to be caught.
it's impossible to pass another value, because your enum limits the possible values to the one you handle. so you don't need any exception.

Best Practice way to indicate that a server request has failed?

I am writing an API that connects to a service which either returns a simple "Success" message or one of over 100 different flavors of failure.
Originally I thought to write the method that sends a request to this service such that if it succeeded the method returns nothing, but if it fails for whatever reason, it throws an exception.
I didn't mind this design very much, but on the other hand just today I was reading Joshua Bloch's "How to Design a Good API and Why it Matters", where he says "Throw Exceptions to indicate Exceptional Conditions...Don't force client to use exceptions for control flow." (and "Conversely, don't fail silently.")
On the other-other hand, I noticed that the HttpWebRequest I am using seems to throw an exception when the request fails, rather than returning a Response containing a "500 Internal Server Error" message.
What is the best pattern for reporting errors in this case? If I throw an exception on every failed request, am I in for massive pain at some point in the future?
Edit: Thank you very kindly for the responses so far. Some elaboration:
it's a DLL that will be given to the clients to reference in their application.
an analogous example of the usage would be ChargeCreditCard(CreditCardInfo i) - obviously when the ChargeCreditCard() method fails it's a huge deal; I'm just not 100% sure whether I should stop the presses or pass that responsibility on to the client.
Edit the Second:
Basically I'm not entirely convinced which of these two methods to use:
try {
ChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);
} catch(ChargeFailException e) {
// client handles error depending on type of failure as specified by specific type of exception
}
or
var status = TryChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);
if(!status.wasSuccessful) {
// client handles error depending on type of failure as specified in status
}
e.g. when a user tries to charge a credit card, is the card being declined really an exceptional circumstance? Am I going down too far in the rabbit hole by asking this question in the first place?
Here's a short list of things to consider. While not comprehensive, I believe these things can help you write better code. Bottom line: Don't necessarily perceive exception handling as evil. Instead, when writing them, ask yourself: How well do I really understand the problem I am solving? More often than not, this will help you become a better developer.
Will other developers be able to read this? Can it be reasonably understood by the average developer? Example: ServiceConnectionException vs. a confusing ServiceDisconnectedConnectionStatusException
In the case of throwing an exception, how exceptional is the circumstance? What does the caller have to do in order to implement the method?
Is this exception fatal? Can anything really be done with this exception if it is caught? Threads aborting, out of memory.. you can't do anything useful. Don't catch it.
Is the exception confusing? Let's say you have a method called Car GetCarFromBigString(string desc) that takes a string and returns a Car object. If the majority use-case for that method is to generate a Car object from that string, don't throw an exception when a Car couldn't be determined from the string. Instead, write a method like bool TryGetCarFromBigString(string desc, out Car).
Can this be easily prevented? Can I check something, let's say the size of an array or a variable being null?
For code readability's sake, let's potentially take a look at your context.
bool IsServiceAlive()
{
bool connected = false; //bool is always initialized to false, but for readability in this context
try
{
//Some check
Service.Connect();
connected = true;
}
catch (CouldNotConnectToSomeServiceException)
{
//Do what you need to do
}
return connected;
}
//or
void IsServiceAlive()
{
try
{
//Some check
Service.Connect();
}
catch (CouldNotConnectToSomeServiceException)
{
//Do what you need to do
throw;
}
}
static void Main(string[] args)
{
//sample 1
if (IsServiceAlive())
{
//do something
}
//sample 2
try
{
if (IsServiceAlive())
{
//do something
}
}
catch (CouldNotConnectToSomeServiceException)
{
//handle here
}
//sample 3
try
{
IsServiceAlive();
//work
}
catch (CouldNotConnectToSomeServiceException)
{
//handle here
}
}
You can see above, that catching the CouldNotConnectToSomeServiceException in sample 3 doesn't necessarily yield any better readability if the context is simply a binary test. However, both work. But is it really necessary? Is your program hosed if you can't connect? How critical is it really? These are all factors you will need to take in to account. It's hard to tell since we don't have access to all of your code.
Let's take a look at some other options that most likely lead to problems.
//how will the code look when you have to do 50 string comparisons? Not pretty or scalable.
public class ServiceConnectionStatus
{
public string Description { get; set; }
}
and
//how will your code look after adding 50 more of these?
public enum ServiceConnectionStatus
{
Success,
Failure,
LightningStormAtDataCenter,
UniverseExploded
}
I think you need to consider a few things in your design:
1) How will the API be accessed? If you are exposing it over web services, then throwing exceptions are probably not a good idea. If the API is in a DLL that you are providing for people to reference in their applications, then exceptions may be ok.
2) How much additional data needs to travel with the return value in order to make the failure response useful for the API consumer? If you need to provide usable information in your failure message (i.e. user id and login) as opposed to a string with that information embedded, then you could utilize either custom exceptions or an "ErrorEncountered" class that contains the error code and other usable information. If you just need to pass a code back, then an ENum indicating either success (0) or failure (any non-zero value) may be appropriate.
3) Forgot this in the original response: exceptions are expensive in the .Net framework. If your API will be called once in awhile, this doesn't need to factor in. However, if the API is called for every web page that is served in a high-traffic site, for example, you definitely do not want to be throwing exceptions to indicate a request failure.
So the short answer, is that it really does depend on the exact circumstances.
I really like the "Throw Exceptions to indicate Exceptional Conditions" idea. They must have that name for a reason.
In a regular application, you would use File.Exists() prior to a File.Open() to prevent an exception from being thrown. Expected errors as exceptions are hard to handle.
In a client-server environment though, you may want to prevent having to send two requests and create a FileOpenResponse class to send both status and data (such as a file handle, in this case).

Should a connect method return a value?

I was looking at some code I've inherited and I couldn't decided if I like a bit of code.
Basically, there is a method that looks like the following:
bool Connect(connection parameters){...}
It returns true if it connects successfully, false otherwise.
I've written code like that in the past, but now, when I see this method I don't like it for a number of reasons.
Its easy to write code that just ignores the returned value, or not realize it returns a value.
There is no way to return an error message.
Checking the return of the method doesn't really look nice:
if (!Connect(...)){....}
I could rewrite code to throw an exception when it doesn't successfully connect, but I don't consider that an exceptional situation. Instead I'm thinking of refactoring the code as follows:
void Connect(Connection Parameters, out bool successful, out string errorMessage){...}
I like that other developers have to provide the success and error strings so they know the method has error conditions and I can know return a message
Anyone have any thoughts on the matter?
Thanks
-Matt
I would opt for the exception versus the out parameters. If you want consumers of your class to care, make them care with the Exception, or else leave them alone. By using the out parameters, you're simply making their lives more inconvenient if they don't have to care by making them use throwaway variables. Also consider that if your function is already in the wild, you're introducing a breaking change if you change the signature (instead of providing an additional overload).
Programmers expect exceptions in error cases, particularly in languages like C#. We've been trained.
I have only an opinion, so take it for what its worth.
A method named like this, "Connect", is an order. It's like giving it to a soldier, "Jump" or "Shoot". You don't expect the soldier to report back unless he's unable to complete the order, and that would be a rare happening.
As such, I have the tendency to not have a return value for such methods, but if there is a chance that under regular usage of the method, there will be failures, then I build a second method, named TryXYZ, returning a bool, and if necessary providing me with the results of whatever XYZ is as out parameters.
This follows the standard set forth by the Parse methods of various numeric types in the .NET BCL.
So in your case, I would probably have:
void Connect(connection parameters);
bool TryConnect(connection parameters, out status);
The nice thing is that if you build the TryConnect method properly, Connect becomes really easy.
Example:
public bool TryConnect(string connectionString, out ConnectionStatus status)
{
... try to connect
... set status, and return true/false
}
public void Connect(string connectionString)
{
ConnectionStatus status;
if (!TryConnect(connectionString, out status))
switch (status)
{
case ConnectionStatus.HostNotFound:
throw new HostNameNotFoundException();
...
}
}
I don't expect my orders to not complete, but in the sense they might, I want to be explicit about it.
I see your points but to add my 2c.
I generally am not a fan of output parameters. If you need to return multiple values from a function re-evaluate what the function is doing, in most case multiple return values is a sign that a method does too much. In your case it is legitimate a complex type would be returned from your connect method (beyond a simple boolean).
I would be in favor of returning a custom type from the connect method that stores all relevant information rather than multiple output parameters. Think about future extensibility, what if you need to include more information down the road. Adding additional output parameters is a breaking change
Also, I tend to disagree with forcing a user to provide memory allocations for all state data. There can be times when I don't care about the success message (maybe I only care if it errors) in which case having to pass both output params is a pain.
I do agree though that checking the return value of the initial method posted isn't ideal.
I don't mind the Connect function returning a boolean and I'm not a big fan of output parameters. If the function did not return the connection state you'd probably have to write a IsConnected function/property (depending on your style) anyway to allow someone to check it, so it saves a step.
As far as expections go, let the exception be caught by the calling code, that'll force the caller to care. :)
I agree that failing to establish a connection (in most cases) should not be seen as an exceptional situation. However to force the user to provide arguments for error string etc. isn't nice either. Other possible solutions:
Use logging. Drawback is that messages are written to the log but not (without much effort) available to the caller.
Use boolean return and provide methods for querying the last error (like errno in C). IMHO not nice either.
Refactor your code, return an object of a connection class. Provide methods to query connection state.
return an instance of a class that gathers all relevant information, aka isSuccessfull(), getErrorString, etc.
Not sure if this is any better than your refactoring code, but hopefully this could give you another idea.
For my projects, I create a method that returns the last error message.
string Error = '';
bool Connect(connection parameters)
{
// do my connection here
// if there's an error set string variable Error
// This way you can set different error message depending on what you're doing
}
string lastErrorMessage(){
// return Error string
}
This way you can do this:
if(!connect(...))
{
string message = lastErrorMessage();
// Then do what you need here.
}
This might not be the best way, but should help you :)

Is this good C# style?

Consider the following method signature:
public static bool TryGetPolls(out List<Poll> polls, out string errorMessage)
This method performs the following:
accesses the database to generate a list of Poll objects.
returns true if it was success and errorMessage will be an empty string
returns false if it was not successful and errorMessage will contain an exception message.
Is this good style?
Update:
Lets say i do use the following method signature:
public static List<Poll> GetPolls()
and in that method, it doesn't catch any exceptions (so i depend the caller to catch exceptions). How do i dispose and close all the objects that is in the scope of that method? As soon as an exception is thrown, the code that closes and disposes objects in the method is no longer reachable.
That method is trying to do three different things:
Retrieve and return a list of polls
Return a boolean value indicating success
Return an error message
That's pretty messy from a design standpoint.
A better approach would be to declare simply:
public static List<Poll> GetPolls()
Then let this method throw an Exception if anything goes wrong.
This is definitely not an idiomatic way of writing C#, which would also mean that it probably isn't a good style either.
When you have a TryGetPolls method then it means you want the results if the operation succeeds, and if it doesn't then you don't care why it doesn't succeed.
When you have simply a GetPolls method then it means you always want the results, and if it doesn't succeed then you want to know why in the form of an Exception.
Mixing the two is somewhere in between, which will be unusual for most people. So I would say either don't return the error message, or throw an Exception on failure, but don't use this odd hybrid approach.
So your method signatures should probably be either:
IList<Poll> GetPolls();
or
bool TryGetPolls(out IList<Poll> polls);
(Note that I'm returning an IList<Poll> rather than a List<Poll> in either case too, as it's also good practice to program to an abstraction rather than an implementation.)
I believe
public static bool TryGetPolls(out List<Poll> polls)
would be more appropriate. If the method is a TryGet then my initial assumption would be there is reason to expect it to fail, and onus is on the caller to determine what to do next. If they caller is not handling the error, or wants error information, I would expect them to call a corresponding Get method.
As a general rule, I would say no.
The reason I say no is actually not because you're performing a TryGetX and returning a bool with an out parameter. I think it's bad style because you're also returning an error string.
The Try should only ignore one specific, commonly-encountered error. Other problems may still throw an exception with the appropriate exception message. Remember that the goal of a Try method like this is to avoid the overhead of a thrown exception when you expect a particular, single sort of failure to happen more frequently than not.
Instead, what you're looking for is a pair of methods:
public static bool TryGetPolls( out List<Poll> polls );
public static List<Poll> GetPolls();
This way the user can do what's appropriate and GetPolls can be implemented in terms of TryGetPolls. I'm assuming that your staticness makes sense in context.
Consider returning:
an empty collection
null
Multiple out parameters, to me, is a code smell. The method should do ONE THING only.
Consider raising and handling error messages with:
throw new Exception("Something bad happened");
//OR
throw new SomethingBadHappenedException();
No, from my point of view this is very bad style. I would write it like this:
public static List<Poll> GetPolls();
If the call fails, throw an exception and put the error message in the exception. That's what exceptions are for and your code will become much cleaner, more readable and easier to maintain.
Not really - I can see a number of problems with this.
First of all, the method sounds like you'd normally expect it to succeed; errors (cannot connect to database, cannot access the polls table etc) would be rare. In this case, it is much more reasonable to use exceptions to report errors. The Try... pattern is for cases where you often expect the call to "fail" - e.g. when parsing a string to an integer, chances are good that the string is user input that may be invalid, so you need to have a fast way to handle this - hence TryParse. This isn't the case here.
Second, you report errors as a bool value indicating presence or absence of error, and a string message. How would the caller distinguish between various errors then? He certainly can't match on error message text - that is an implementation detail that is subject to change, and can be localized. And there might be a world of difference between something like "Cannot connect to database" (maybe just open the database connection settings dialog in this case and let the user edit it?) and "Connected to database, but it says 'Access Denied'". Your API gives no good way to distinguish between those.
To sum it up: use exceptions rather than bool + out string to report messages. Once you do it, you can just use List<Poll> as a return value, with no need for out argument. And, of course, rename the method to GetPolls, since Try... is reserved for bool+out pattern.
The guidelines say to try to avoid ref and out parameters if they are not absolutely required, because they make the API harder to use (no more chaining of methods, the developer has to declare all the variables before calling the method)
Also returning error codes or messages is not a best practice, the best practice is to use exceptions and exception handling for error reporting, else errors become to easy to ignore and there's more work passing the error info around, while at the same time losing valuable information like stacktrace or inner exceptions.
A better way to declare the method is like this.
public static List<Poll> GetPolls() ...
and for error reporting use exception handling
try
{
var pols = GetPols();
...
} catch (DbException ex) {
... // handle exception providing info to the user or logging it.
}
It depends on what the error message is. For instance, if processing couldn't continue because the database connection wasn't available, etc., then you should throw an exception as other people have mentioned.
However, it may be that you just want to return "meta" information about the attempt, in which case you just need a way to return more than one piece of information from a single method call. In that case, I suggest making a PollResponse class that contains two properties: List < Poll > Polls, and string ErrorMessage. Then have your method return a PollResponse object:
class PollResponse
{
public List<Poll> Polls { get; }
public string MetaInformation { get; }
}
Depends on if an error is a common occurance or if it us truly an exception.
If errors are gunuinely rare and bad then you might want to consider having the method just return the list of polls and throw an exception if an error occurs.
If an error is something that is realtively common part of normal operations, as like an error coverting a string to an integer in the int.TryParse method, the method you created would be more appropriate.
I'm guessing the former is probably the best case for you.
It depends on how frequently the method will fail. In general, errors in .Net should be communicated with an Exception. The case where that rule doesn't hold is when the error condidition is frequent, and the performance impact of throwing and exception is too high.
For Database type work I think an Exception is best.
I'd restate it like this.
public static List<Poll> GetPolls()
{
...
}
It should probably be throwing an exception (the errorMessage) if it fails to retrieve the polls, plus this allows for method chaining which is less cumbersome than dealing with out parameters.
If you run FxCop, you'll want to change List to IList to keep it happy.
I think its fine. I would prefer though:
enum FailureReasons {}
public static IEnumerable<Poll> TryGetPolls(out FailureReasons reason)
So the error strings don't live in the data-access code...
C# Methods should really only do one thing. You're trying to do three things with that method. I would do as others have suggested and throw an exception if there is an error. Another option would be to create extension methods for your List object.
e.g. in a public static class:
public static List<Poll> Fill( this List<Poll> polls) {
// code to retrieve polls
}
Then, to call this, you would do something like:
List<Poll> polls = new List<Poll>().Fill();
if(polls != null)
{
// no errors occur
}
edit: i just made this up. you may or may not need the new operator in List<Poll>().Fill()
Please state your assumptions, constraints, desires/goals, and reasoning; we're having to guess and/or read your mind to know what your intentions are.
assuming that you want your function to
create the polls list object
suppress all exceptions
indicate success with a boolean
and provide an optional error message on failure
then the above signature is fine (though swallowing all possible exceptions is not a good practice).
As a general coding style, it has some potential problems, as others have mentioned.
There is also this pattern, as seen in many Win32 functions.
public static bool GetPolls(out List<Poll> polls)
if(!PollStuff.GetPolls(out myPolls))
string errorMessage = PollStuff.GetLastError();
But IMO it's horrible.
I would go for something exception based unless this method has to run 65times per second in a 3d game physics engine or someting.
Did I miss something here? The question asker seems to want to know how to clean up resources if the method fails.
public static IList<Poll> GetPolls()
{
try
{
}
finally
{
// check that the connection happened before exception was thrown
// dispose if necessary
// the exception will still be presented to the caller
// and the program has been set back into a stable state
}
}
On a design side note, I'd consider pushing this method into a repository class so you have some sort of context with which to understand the method. The entire application, presumably, is not responsible for storing and getting Polls: that should be the responsibility of a data store.

Best way to explain why something failed

Suppose I had the following method in an object:
public class foo
{
public bool DoSomethingAwesome()
{
bool bar = DidSomething() //suppose this sends an email;
return bar;
}
}
If I wanted to provide more detail on why DidSomething returned a false would the best practice be to assign a message to a Property to foo, or assign an Out parameter to DoSomethingAwesome?
I think this depends highly on the framework you're using (i.e. it's a convention).
For Win32 - you had the SetLastError,
GetLastError.
For .NET it's usually
throwing an Exception but that could be
changed to match your circumstances.
Probably an out param would be ok.
If you decide to go with the Exception route, MSDN has an entry with "Design Guidelines for Exceptions". And there's a great discussion in the book "Framework Design Guidlines" - chapter 7, which I highly recommend!
It depends very much on what you're doing, but in the situation given—sending an email—I would throw different exceptions based on what went wrong. As sending an email should work pretty much every time, when something bad happens, I'd want to force the caller to handle it rather than ignoring it by default.
In other situtations, where the chance of failure is high, failure can be ignored, or false doesn't necessarily mean failure, I'd create an enum which has values for each type of failure and one for success, and return that rather than a bool.
Look at my answer here:
Handing exception in BLL and return to client (either winforms or webforms)?
Maybe it helps.
If the false condition is not an "exception" (not rarely but evenly occurs) and then you should not use exceptions. In that case using an out parameter is much better.

Categories

Resources