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 8 years ago.
Improve this question
So I'm a little concerned about my error handling... Currently my execution path looks something like this:
Users.aspx -> App_Code/User.cs -> Data Layer/User.cs
So now when I try to update a user record, I put my Try/Catch block in the event handler and ensure that only the App_Code class interacts with the data layer. Exceptions that happen on the data layer, to my understanding, should bubble up to the event handler below.
In the data layer, I started off with this:
public void Update()
{
var product = (from p in db.products
where p.productid == id
select p).FirstOrDefault();
if (product != null)
{
// update the thing
}
}
More info on reddit.
After chatting with a friend, he recommended something like this:
public void Update()
{
int count = db.users.Count(u => u.userid == id);
if (count == 0) // no user found
{
throw new ValidationException(String.Format("User not found for id {0}.", id));
}
if (count > 1) // multiple users
{
throw new ValidationException(String.Format("Multiple users found for id {0}.", id));
}
var user = db.users.FirstOrDefault(u => u.userid == id);
// update the user record
}
Then I went onto IRC where they suggested I create my own Exceptions.
I can see the pros here, but it seems a bit unnecessary when my friend's option will work just fine.
Basically I'm just really confused as to how I should handle this... Obviously my initial option is insufficient, but it seems like creating my own exceptions might be complicating things too much.
So what should I do here?
Think of the other side here. As in, who is consuming that API. Whoever calls that method, they probably want to know that something went wrong. Exceptions provide that (return values could, too), while your initial approach doesn't.
Now consider that the consumer might want to distringuish the two cases »no users found« and »multiple users found«. In that case they're out of luck because you throw the same exception for both and have no way of distinguishing the two cases¹. In this case having distinct exception types for the different things that could have gone wrong can help.
But only if you actually need that capability in the caller. If you're using that method yourself, it's not part of a public API where you don't know how it might be used, and whether distinguishing those cases would be useful, I'd say don't bother.
I've used my own exception types rarely so far, and mostly when writing parsers for something where the exception type could hint at what exactly went wrong and you could use additional properties of the exception to generate a useful error message. In most other code I don't think I've ever done that.
¹ You could compare the exception message, but I'd advise never to do that. The message is for a user or developer to read. It could be translated into other languages (e.g. all exceptions from .NET are in your UI language, usually) which makes such an approach very brittle.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I've been introducing some new C# language features to my team - safe navigation is one of those.
Are there any significant performance reasons to avoid usage of safe navigation for every single object/property call?
e.g.:
myObject?.Field?.FieldValue
vs.
myObject.Field.FieldValue
I know this makes it so every field is null checked - but outside of a tight loop, don't the bugs this catches make it worth it? Or does this encourage lazy coding?
EDIT:
I found an entire article on this topic, hopefully it is helpful for others!
don't the bugs this catches make it worth it?
Quite on the contrary: applying safe navigation everywhere would hide bugs, rather than catching them.
Navigating a null reference by mistake is a bug in the implementation which could mean one of two things:
A field from which you navigate was not supposed to be null
You forgot to null-check a field that is legitimately null
Applying safe navigation is a good choice for case #2, because it lets you perform null check with less code. However, it is a poor choice for case #1, because it lets the object or a variable remain in a state that is incorrect from the standpoint of your program's logic.
That is why programmers should use their discretion when applying safe navigation, deciding each case individually.
Don't safely Navigate when
1) Null is actually an invalid logic for what you're doing
public string ProcessHash(User user)
{
var hash = user?.Password?.Hash
...
}
It's called Safe Navigation not Easy Null Check for a reason. Imagine you're destined to read the code above.
Does ProcessHash expect the user parameter as a null argument? If so, is the Password property of it also supposed to become null? How would you know if the previous coder has used "?." instead of "." just because he's a fan of Elvis? you'd have to analyse the whole code to find out.
2) Null is having another meaning than an unavailability in your code
What does a blind man see? Darkness? Or simply nothing?
What is an empty grocery basket?
// This is a good
Basket<Grocery> basket = new Basket<Grocery>();
var count = basket.Count(); // returns 0
// This smells bad!
Basket<Grocery> basket = null
var count = basket?.Count ?? 0;
3) You're using ?. and extension methods as a pipeline operator!
Don't use ?. to chain Properties and Methods together just because it reduces the lines you write and makes your code cool. there's lots of more well thought high level abstractions behind pipelines in fancy functional codes you see in other languages.
var resp = this.Bind<IceCreamDTO>()?.Validate()?.ToEntity()?.Insert()?.ToResponse();
There's 2 thing wrong with kind of code above.
Imagine if there was an error while validating the bound object. can you return what was wrong with it to the requester? well you can... but it's bad.
// That's not how this works. that's not how any of this works.
try
{
var resp = this.Bind<IceCreamDTO>()?.Validate()?.ToEntity()?.Insert()?.ToResponse();
...
} catch (ValidationException exp)
{
return exp.Errors.ToResponce();
}
well not clearly in the example above(realize it's all method calls not property calls), this also might break encapsulation principles if you're Navigating methods and properties together.
// Privacy violation
bool passwordValidation = user?.Password?.Hash?.Validate(hash);
// Property Security
bool passwordValidation = PasswordHash.Validate(user, hash);
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
This is probably quite a simple question, but what is the best practice for return types on a try-catch block? At the moment, I'm doing stuff like this:
public List<SomeAttribute> FindAttributes(int id)
{
try
{
//Some query and some logic
}
catch (Exception ex)
{
Logger.Error(ex);
return new List<SomeAttribute>();
}
}
Is there anything particularly awful about this? The exception will get logged, and the method will return an empty list - which the calling function can handle. Is it better to return null? If so why?
In general one considers three strategies to handle partial functions (functions where only a subset of the input domain is valid): Total, Defensive, and Nominal.
Total
That means that you always return an answer. In this case you can for instance think about returning a null-pointer, in the case of String.IndexOf for instance one returns -1.
Advantages:
It is sometimes easier for a the caller not to think about potential errors. Sometimes the return value can be useful. For instance if you want to cut off a the first part of a string up (and including the first comma), you can code this as:
string foo = "Foo,Bar"
string foocut = foo.SubString(foo.IndexOf(',')+1); //Bar, in case no comma, it returns the entire string
Thus resulting in more compact code. But on the other hand it's sometimes hard to determine what the best return value is.
Disadvantages:
It requires engineering to determine the "best" return value. There are many options and each option will only be beneficial for a part of the callers.
It is sometimes impossible to distinguish between valid output where nothing went wrong and the (default) output in case something went wrong.
Defensive
Here you throw an exception (or don't catch the exception). It is up to a (domain-specific) caller to determine why the exception has been thrown and handle accurately. Util methods have in general not much knowledge about the system and thus don't know why the exception occurred.
Advantages:
The exception can be handled by the caller with the best knowledge (thus some kind of "chain of responsibilities"). This can result in better error handling (providing useful messages to the user). Not "An error has occurred in SQL query ...", but "The username already exists."
Disadvantages:
Error handling is sometimes hard. Especially in C# where one doesn't need to annotate which exception can be thrown by a method. It is not easy to cover all kinds of exceptions. It is possible that an uncatched exception will return to the top Main call crashing the application. For some applications like a webserver, that's not always an option.
Nominal
Here you document your methods and provide precoditions: in the documentation you specify what are the correct ways to use that method. This isn't always possible since sometimes the fact whether a method succeeds depends on external factor (the availability of a server, the type of OS,...). Factors a programmer doesn't necessarily controls.
Advantages:
Results in well documented (and sometimes strictly) defined methods.
Implementing the method (callee) is easier since it can assume everything will work fine.
Disadvantages:
Not always possible (sometimes the result does depend on factors one cannot control).
Writing the caller is harder, since it it has a contract that it will only call the method with the correct arguments.
It is also hard to document all conditions as well as validating that each call satisfies them. Sometimes code contracts are used to handle validation (partially) automatic.
Most programs don't stick with one strategy but mix them: for instance some exceptions are handled total, others nominal and others defensive. Or some module follows the defensive strategy whereas the other uses nominal programming.
I know the title is a little too broad, but I'd like to know how to avoid (if possible) this piece of code I've just coded on a solution of ours.
The problem started when this code resulted in not enough log information:
...
var users = [someRemotingProxy].GetUsers([someCriteria]);
try
{
var user = users.Single();
}
catch (InvalidOperationException)
{
logger.WarnFormat("Either there are no users corresponding to the search or there are multiple users matching the same criteria.");
return;
}
...
We have a business logic in a module of ours that needs there to be a single 'User' that matches some criteria. It turned out that, when problems started showing up, this little 'inconclusive' information was not enough for us to properly know what happened, so I coded this method:
private User GetMappedUser([searchCriteria])
{
var users = [remotingProxy]
.GetUsers([searchCriteria])
.ToList();
switch (users.Count())
{
case 0:
log.Warn("No user exists with [searchCriteria]");
return null;
case 1:
return users.Single();
default:
log.WarnFormat("{0} users [{1}] have been found"
users.Count(),
String.Join(", ", users);
return null;
}
And then called it from the main code like this:
...
var user = GetMappedUser([searchCriteria]);
if (user == null) return;
...
The first odd thing I see there is the switch statement over the .Count() on the list. This seems very strange at first, but somehow ended up being the cleaner solution. I tried to avoid exceptions here because these conditions are quite normal, and I've heard that it is bad to try and use exceptions to control program flow instead of reporting actual errors. The code was throwing the InvalidOperationException from Single before, so this was more of a refactor on that end.
Is there another approach to this seemingly simple problem? It seems to be kind of a Single Responsibility Principle violation, with the logs in between the code and all that, but I fail to see a decent or elegant way out of it. It's even worse in our case because the same steps are repeated twice, once for the 'User' and then for the 'Device', like this:
Get unique user
Get unique device of unique user
For both operations, it is important to us to know exactly what happened, what users/devices were returned in case it was not unique, things like that.
#AntP hit upon the answer I like best. I think the reason you are struggling is that you actually have two problems here. The first is that the code seems to have too much responsibility. Apply this simple test: give this method a simple name that describes everything it does. If your name includes the word "and", it's doing too much. When I apply that test, I might name it "GetUsersByCriteriaAndValidateOnlyOneUserMatches()." So it is doing two things. Split it up into a lookup function that doesn't care how many users are returned, and a separate function that evaluates your business rule regarding "I can handle only one user returned".
You still have your original problem, though, and that is the switch statement seems awkward here. The strategy pattern comes to mind when looking at a switch statement, although pragmatically I'd consider it overkill in this case.
If you want to explore it, though, think about creating a base "UserSearchResponseHandler" class, and three sub classes: NoUsersReturned; MultipleUsersReturned; and OneUserReturned. It would have a factory method that would accept a list of Users and return a UserSearchResponseHandler based on the count of users (encapsulating the logic of the switch inside the factory.) Each handler method would do the right thing: log something appropriate then return null, or return a single user.
The main advantage of the Strategy pattern comes when you have multiple needs for the data it identifies. If you had switch statements buried all over your code that all depended on the count of users found by a search, then it would be very appropriate. The factory can also encapsulate substantially more complex rules, such as "user.count must = 1 AND the user[0].level must = 42 AND it must be a Tuesday in September". You can also get really fancy with a factory and use a registry, allowing for dynamic changes to the logic. Finally, the factory nicely separates the "interpreting" of the business rule from the "handling" of the rule.
But in your case, probably not so much. I'm guessing you likely have only the one occurrence of this rule, it seems pretty static, and it's already appropriately located near the point where you acquired the information it's validating. While I'd still recommend splitting out the search from the response parser, I'd probably just use the switch.
A different way to consider it would be with some Goldilocks tests. If it's truly an error condition, you could even throw:
if (users.count() < 1)
{
throw TooFewUsersReturnedError;
}
if (users.count() > 1)
{
throw TooManyUsersReturnedError;
}
return users[0]; // just right
How about something like this?
public class UserResult
{
public string Warning { get; set; }
public IEnumerable<User> Result { get; set; }
}
public UserResult GetMappedUsers(/* params */) { }
public void Whatever()
{
var users = GetMappedUsers(/* params */);
if (!String.IsNullOrEmpty(users.Warning))
log.Warn(users.Warning);
}
Switch for a List<string> Warnings if required. This treats your GetMappedUsers method more like a service that returns some data and some metadata about the result, which allows you to delegate your logging to the caller - where it belongs - so your data access code can get on with just doing its job.
Although, to be honest, in this scenario I would prefer simply to return a list of user IDs from GetMappedUsers and then use users.Count to evaluate your "cases" in the caller and log as appropriate.
i think i sort of know the answer to this, but there are always many ways to do things (some of which are clearly wrong :) )...
I have a little recursive function to find an employees manager's id. this is being used in a import script and it may be that the persons immediate manager has left (been disabled) so we need to find that employees (the manager) manager (and so on) so we can assign stuff to them. in case it isn't obvious, the EmployeesToDisable is a generic list of employees that are marked as disabled in this import.
I guess what i am really asking, is : is the overhead associated with catching an exception too much of a trade off to make in this instance. and should i be doing this differently.
this does work fine, but feels like it is bad form..
i have code thus:
private Guid getMyEnabledManagersID(OnlineEmployee e)
{
Employee manager;
try
{
//see if Employee e's manager is in the disabled list.
manager = (from emp in EmployeesToDisable where emp.EmployeeID.Equals(e.ManagerID) select emp).Single();
//yes they are, so need to call this again
return getMyEnabledManagersID(manager);
}
catch
{
return e.ManagerID;
}
}
Leaving aside the recursion, you should perhaps just use SingleOrDefault and test for null. Actually, you probably don't need the full employee object - you can probably suffice with just returning the id (throughout), i.e.
private Guid getMyEnabledManagersID(Guid managerId)
{
var disabled = (from emp in EmployeesToDisable
where emp.EmployeeID == managerId
select (Guid?)emp.ManagerID).SingleOrDefault();
return disabled == null ? managerId : getMyEnabledManagersID(disabled.Value);
}
Actually, the biggest concern I have with the original form is that it isn't specific to the type of exception; it could be "thread abort", "zombie connection", "deadlock", etc.
As others have pointed out never do that. That is a "worst practice". The exception is there to tell you that you have a logic bug in your program. By catching the exception and continuing on, you hide the logic bug.
Only use Single when you know, positively and for sure, that there is exactly one element in the sequence. If there might be other numbers of elements in the list then use First, FirstOrDefault, SingleOrDefault, or write your own sequence operator; it's not hard to do.
The main reasons to not use this worst practice are:
1) As I said, it hides a bug; those exceptions should never be caught because they should never be thrown in a working program. The exceptions are there to help you debug your program, not to control its flow.
2) Using exceptions as control flow like this makes it difficult to debug a program. Debuggers are often configured to stop on any exception, whether it is handled or not. Lots of "expected" exceptions make that harder. Exceptions should never be expected, they should be exceptional; that's why they're called "exceptions".
3) The catch catches everything, including stuff that probably indicates a fatal error that should be reported to the user.
Apart from other answers,
Try/Catch are very costly operations, your simple if statement is faster in terms of performance then expecting a catch and then following the logic.
Try/Catch should not be part of business logic, instead they should only be part of error handling.
You could use FirstOrDefault() instead of Single and handle the returned null value.
I have a simple question for you (i hope) :)
I have pretty much always used void as a "return" type when doing CRUD operations on data.
Eg. Consider this code:
public void Insert(IAuctionItem item) {
if (item == null) {
AuctionLogger.LogException(new ArgumentNullException("item is null"));
}
_dataStore.DataContext.AuctionItems.InsertOnSubmit((AuctionItem)item);
_dataStore.DataContext.SubmitChanges();
}
and then considen this code:
public bool Insert(IAuctionItem item) {
if (item == null) {
AuctionLogger.LogException(new ArgumentNullException("item is null"));
}
_dataStore.DataContext.AuctionItems.InsertOnSubmit((AuctionItem)item);
_dataStore.DataContext.SubmitChanges();
return true;
}
It actually just comes down to whether you should notify that something was inserted (and went well) or not ?
I typically go with the first option there.
Given your code, if something goes wrong with the insert there will be an Exception thrown.
Since you have no try/catch block around the Data Access code, the calling code will have to handle that Exception...thus it will know both if and why it failed. If you just returned true/false, the calling code will have no idea why there was a failure (it may or may not care).
I think it would make more sense if in the case where "item == null" that you returned "false". That would indicate that it was a case that you expect to happen not infrequently, and that therefore you don't want it to raise an exception but the calling code could handle the "false" return value.
As it standards, you'll return "true" or there'll be an exception - that doesn't really help you much.
Don't fight the framework you happen to be in. If you are writing C code, where return values are the most common mechanism for communicating errors (for lack of a better built in construct), then use that.
.NET base class libraries use Exceptions to communicate errors and their absence means everything is okay. Because almost all code uses the BCL, much of it will be written to expect exceptions, except when it gets to a library written as if C# was C with no support for Exceptions, each invocation will need to be wrapped in a if(!myObject.DoSomething){ System.Writeline("Damn");} block.
For the next developer to use your code (which could be you after a few years when you've forgotten how you originally did it), it will be a pain to start writing all the calling code to take advantage of having error conditions passed as return values, as changes to values in an output parameter, as custom events, as callbacks, as messages to queue or any of the other imaginable ways to communicate failure or lack thereof.
I think it depends. Imaging that your user want to add a new post onto a forum. And the adding fail by some reason, then if you don't tell the user, they will never know that something wrong. The best way is to throw another exception with a nice message for them
And if it does not relate to the user, and you already logged it out to database log, you shouldn't care about return or not any more
I think it is a good idea to notify the user if the operation went well or not. Regardless how much you test your code and try to think out of the box, it is most likely that during its existence the software will encounter a problem you did not cater for, thus making it behave incorrectly. The use of notifications, to my opinion, allow the user to take action, a sort of Plan B if you like when the program fails. This action can either be a simple work around or else, inform people from the IT department so that they can fix it.
I'd rather click that extra "OK" button than learn that something went wrong when it is too late.
You should stick with void, if you need more data - use variables for it, as either you'll need specific data (And it can be more than one number/string) and an excpetion mechanism is a good solution for handling errors.
so.. if you want to know how many rows affected, if a sp returned something ect... - a return type will limit you..