Our company has recently transitioned from VB6 to VB.NET. Unfortunately all the error handling remains as On Error GoTo. This has not made it easy to track down errors that customers send back to tech support. As of now, the blocks of code that the On Error surrounds is entire subroutines, not uncommonly hundreds of lines of code for one sub, and possibly making calls to other routines. My question is how to best go about converting to Try...Catch blocks. I assume I can just substitute On Error GoTo Errorline for try and Errorline for catch. But this seems like too much for one try...catch block to encompass.
VB6's big weakness with error-handling is that the runtime does not provide a way for your code to get at the execution stack (method A called method B called method C, etc.) when an exception occurs; even if your On Error block catches the exception, you code doesn't know "where it is". To get around that deficiency, VB6 programmers have learned to enclose every method, in every module, with a catch-all On Error block, sometimes so that their own code can keep track of the execution stack for logging purposes. There were even third-party tools that could be used to instrument your code with On Error blocks, for exactly that purpose (VB/Rig, VB-Failsafe).
.Net's Exception object, however, does provide a .StackTrack property that represents the execution stack to the point of failure, so it's no longer necessary to use On Error blocks in every method, just so you can learn where your code failed, post-mortem.
Here is one simple strategy you can use, as you transition:
First, as you suggested, replace all of your "boilerplate" On Error Goto Errorline / :Errorline with Try / Catch ex As Exception blocks. But, do this only in the "top-level" methods where execution can "begin". In VB, these are usually all of the Event methods in your forms that directly handle system events (_Click, _MouseDown, _Timer, etc.)
Second, remove all the boilerplate error handling from "lower-level" methods -- methods that are merely called from the "top-level" or other "lower-level" methods.
Now you have provided a "safety net" of Try/Catch exception handling that will protect your app from dying from an unhandled exception. When an exception does occur, even deep in the execution stack, your code will unwind back to the nearest Catch, usually one of your UI event-handler methods. But, you will have the ex.StackTrack property that documents the execution up to the failure, module by module, method by method, with the source code line-number at each level.
One exception to the above strategy is when you find an error-handling block that is not boilerplate -- it was written specifically to handle a certain error(s), and to respond specifically. Leave this code in place, but again replace the On Error Goto Errorline / :Errorline with Try / Catch ex As Exception.
Here's a helpful rule of thumb: In your "top-level" methods, enclose the entire method in a "boilerplate" Try/Catch. In your "lower-level" methods, only write Try/Catch blocks around code where you can anticipate that certain exceptions will occur -- ones that your code wants to specifically respond to.
It's not unreasonable, or "too much", for a Try/Catch block to encompass large chunks of code. You should always strive to keep your methods as short as possible, but there is no reason to arbitrarily truncate or partition a long method just because it's enclosed by a Try/Catch.
Related
In my MQL4 expert advisor I need to check this code before it is executing, weather it is correct or not. Is there a way to use a try/catch blocks for this? It is written in C language.
OrderSelect( i, SELECT_BY_POS );
if ( OrderType() == OP_SELL ){
OrderClose( OrderTicket(), OrderLots(), Ask, 3 );
}
As it was suggested in comments, try/catch is done to let your code to throw an exception and catch it. If not catching your program would shutdown, if not throwing then result might be unknown.
The MQL4 programming language does not have exceptions at all (but it is possible to shutdown by invoking a critical error like calling -1 element of the array or dividing by zero). You do not need to throw an exception here even if you could.
OrderSelect() returns boolean value so you may check if it is false then continue the loop or return. OrderClose() returns boolean (the result - succesful closing or not) so you are advised to check if that function returns true of false, if false - need to log an error and try again
Well, let me have a different view - there is a way to do it:
Given your plan is to find a way, how to enable a use of the try/catch clause in MQL4/5 domain, there is a way to do it.
While many pieces of advice say it is not possible or it is not needed, let's accept a fact the O/P asked for it and focus on how.
In case, there is indeed a need to have a try/catch fused part of code,
I would implement such code inside an externally #import-ed code, via DLL and select such the target eco-system, that has the native try/catch language constructors available for algorithm that wishes to work within it's fused code-blocks.
Daniel's example about intentional throwing the MQL4-system execution to trash, by an explicit attempt to access Array[EMPTY] is interesting, so far it was enough to call ExpertRemove() and enjoy the proper system termination of the code, including an OnDeinit(){...} handle pass-through. Suiccidal call seems to be quite a brutal mode bypass of the system code termination +1 for that #DanielKniaz.
Cool Man, indeed!
On my point of view in the MQL4 expert advisor functions there is no way to use try catch method as java.you can only catch the errors before executing via other methods like checking the validity of the orderticket and etc
So, the question is in the title.
The only one thought that comes in mind why we need to introduce custom Exception class is to pass additional info with exception raising.
Any additional reasons?
There are several reasons why you may want to create custom exceptions:
Add custom logic to an exception, to simplify the interaction with the exception itself. ActiveRecord::RecordInvalid is an example: the message is built from the actual record errors, and a reference to the record itself is stored in the exception.
Differentiate errors to improve error handling. Having different error types allows you to specifically rescue only certain types of errors, and not all the errors. You can also have different rescue blocks depending on the error type.
Re-raising typed errors. This is very important for libraries that internally relies on other libraries. A good practice of software composition is that library A uses B internally, whatever error B raises should be wrapped into an A error to make sure that the users of A don't have to deal with B directly.
In general, providing custom errors enhances the error handling experience. A good resource to learn more about errors is Avdi's book Exceptional Ruby. Highly recommended.
To avoid the Pokemon exception handling (Gotta' catch them all) anti-pattern it is better to raise your own exception types.
When using a library for example you should get meaningful error types - for example AuthorizationError or TimeOutError - it lets programmers deal with exceptions by type instead of matching the error message or adding a clunky system of numeric codes which does not really belong in an object oriented language.
Can anyone please explain difference between below two approaches.
Logging in controller's OnException event:
try
{
//code
}
catch
{
//rollback trasanctions
throw;
}
Or, logging in catch block:
try
{
//code
}
catch
{
//logging here
//rollback trasactions
throw;
}
The Controller's OnException method is used when an unhandled exception occurs in the processing of the request. It is indicates what functionality should happen if an unexpected exception occurs. You should really only use this as a safeguard in the event that you messed up or the system failed in an unexpected, fatal way.
If you are executing some piece of code that you expect to throw a specific exception, wrap it in try block, and handle the specific exception accordingly. This defensive approach will help you debug issues as soon as they happen, rather than wait for them to bubble up to a point where you don't know the cause.
Think about it, if you have multiple action methods and only one OnException method per controller, then you have a much more complex issue to handle, because any of the action methods or filters could have thrown the error. However, if you catch an exception called by a specific service call then you already know exactly what caused the unexpected behavior, and it will be much easier to address accordingly.
Read this for greater understanding: Eric Lippert has an excellent article in which he breaks down the different categories of exceptions that we encounter and offers best practices for addressing them. It is available at http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx . In case you don't know who Eric Lippert is, he is very smart and you should listen to him if you code in C#. His main points are:
Don’t catch fatal exceptions; nothing you can do about them anyway, and trying to generally makes it worse.
Fix your code so that it never triggers a boneheaded exception – an "index out of range" exception should never happen in production code.
Avoid vexing exceptions whenever possible by calling the “Try” versions of those vexing methods that throw in non-exceptional circumstances. If you cannot avoid calling a vexing method, catch its vexing exceptions.
Always handle exceptions that indicate unexpected exogenous conditions; generally it is not worthwhile or practical to anticipate every possible failure. Just try the operation and be prepared to handle the exception.
Update
Just realized I didn't explicitly address the "logging" question. It probably makes most sense to avoid handling your fatal/exogenous errors in a controller scope, because you will end up duplicating your logic, often. This behavior is better handled in a global action filter.
This codeproject article Exception Handling in ASP.NET MVC explains how to override the default HandleErrorAttribute and leverage an ErrorController so that it can be applied globally.
In addition, the following 5-part blog series gives an in depth analysis of the different options you have for error handling in MVC applications: http://perspectivespace.com/error-handling-in-aspnet-mvc-3-index-of-posts
Could anyone please guide me on what's the best practice to handle exception in ASP.NET MVC?
Controller?
Model?
Model (Contains EF logics i.e. save, update etc) throw any exception and catch in Controller?
In any method or block of code where you may expect specific exceptions (interacting with a database or an external service which may or may not not be available, etc.) wrap that code in a Try/Catch to catch the specific exception(s) in question. You'd want to know exactly what kind of exceptions occurred to handle them properly. (Naturally, use a Finally block to dispose of any open resources.) How to properly handle them is up to you and how you want your application to behave.
You should definitely have a global exception handling to catch anything unexpected which falls through the cracks. At no point should an unhandled exception bubble up to the user. The global exception handler should just present the user with a friendly error message and should log the exception and notify you of what happened. Generally, a good goal is to identify the exception and add error handling code to catch it in its localized state before it bubbles up to global. The goal, over time, should be to have as few global exceptions as possible and to have any potentially-exception-generating code have its own error handling to guard against those cases.
An example of the latter could be something as simple as a particular method receiving null arguments that you want to check for before using those arguments. One thing you want to avoid, however, is using exception handling for logic flow. For example...
Let's say you have a method which takes a custom object as an argument:
public MyMethod(MyObject obj)
{
// ...
}
Your original code assumes that obj will always have a value. However, after some time of production use, you discover that obj is sometimes null and that it's throwing a NullReferenceException from within that method, which is being caught by the global exception handler.
You may be tempted to just wrap the code in MyMethod in its own Try/Catch block to catch that exception. This isn't necessarily a good idea (though there may be cases where it is). Instead, you'd want to check for null at the start of the method:
public MyMethod(MyObject obj)
{
if (obj == null) throw new ArgumentNullException("obj can not be NULL");
// ...
}
This encapsulates the method better and allows it to throw controlled exceptions. Exceptions aren't bad things, only unexpected exceptions. Note that the above will still throw the exception which will still bubble up to the global handler. Thus, it's also a good idea to wrap the calls to this method in a Try/Catch block in order to catch the ArgumentNullException and handle it accordingly. Perhaps the code which calls this method can fix the null reference and try again, perhaps it can try something else, etc. You still don't want it to bubble up to the global handler if possible, since this has become an "expected" exception and can be handled accordingly.
Naturally, you still want to avoid the throwing/catching of the expected exceptions in the above example, so similar checks for null should happen before calling the method so that the method isn't even called.
Maybe if the object is null you can directly present the user with an error message and log the error and notify you of as much information about the state of things as possible so that you can research why it's null and fix it. Maybe being null is a perfectly acceptable state of that object at that time according to the logic of the application. If so, check if it's null and don't bother calling the method. Just carry on as normal.
It's a lot of error-checking and handling code, but that's a good thing.
Edit: Another thing to note about exception handling is that you should catch the exception only if you can actually handle it at that time. If the method can't handle it internally, let the exception bubble up from the method to the calling method, and so on. Thus, the only exceptions which should reach the global handler are exceptions which you can't actually handle anywhere in the code (which is why it's a good goal to fix and prevent global exceptions).
"Handle" in this case would mean being able to actually do something about it. Maybe that something is to just log it and carry on, maybe that something is to perform some specific logic, etc. But to catch, log, and re-throw is bad design. If you can't recover from the exception, let it bubble up.
The best way is to catch the exception globally, log it using Elmah. Otherwise you will have to put all your exceptions in your every controller code and that would be a lot of repetition especially for CRUD operations
There is a post by Raymond Chen, where he tells how bad IsBadXxxPtr function is by eating guard page exception.
I don't quite understand how it is applied to Delphi. Who and how should normally (i.e. without call to IsBadXxxPtr) process this exception?
I do know that Delphi inserts a code, which (for example) access a memory for large static arrays - exactly for this reason: to expand stack.
But if guard page exception is raised: who will handle it in a Delphi application? Can't I accidentally mess with it by using try/except in inappropriate way? Will Delphi's debugger notify me about these exceptions?
Windows structured exception handling (SEH) is has a two-phase structure. When an exception occurs, Windows first looks for a handler for the exception by following the registered exception handler chain (the head of which is stored in fs:[0] on x86, i.e. the first dword in the segment pointed to by the FS segment register - all that ugly 16-bit segment-offset logic didn't go away in 32-bit, it just became less relevant).
The search is done by calling a function with a particular flag, a pointer to which is stored in each exception frame on the stack. fs:[0] points to the topmost frame. Each frame points to the previous frame. Ultimately, the last frame on the list is one that has been provided by the OS (this handler will pop up a app-crash dialog if an unhandled exception reaches it).
These functions normally check the type of the exception, and return a code to indicate what to do. One of the codes that can be returned is basically, "ignore this exception and continue". If Windows sees this, it will reset the instruction pointer to the point of the exception and resume execution. Another code indicates that this exception frame should handle the given exception. A third code is "I'm not going to catch this exception, keep searching". Windows keeps on calling these exception filter functions until it finds one that handles the exception one way or the other.
If Windows finds one that handles the exception by catching it, then it will proceed to unwind the stack back to that handler, which consists of calling all the functions again, only passing in a different flag. It's at this point that the functions execute the finally logic, up until the handler which executes the except logic.
However, with the stack page guard exception, the process is different. None of the language's exception handlers will elect to handle this exception, because otherwise the stack growth mechanism would break. Instead, the filter search filters all the way through to the base exception handler provided by the OS, which grows the stack allocation by committing the appropriate memory, and then returns the appropriate return code to indicate that the OS should continue where it left off, rather than unwind the stack.
The tool and debugging infrastructure are designed to let these particular exceptions play out correctly, so you don't need to worry about handling them.
You can read more about SEH in Matt Pietrek's excellent article in MSJ from over a decade ago.
From looking at the comments, it looks to me like the "guard page exception" mess takes place entirely within the kernel, and is not something that you need to be worrying about from user space.
You've gotta remember that this article was written for C++, which is nowhere near as advanced as Delphi on the memory management front. The uninitialized pointers issue is a lot less of a mess in Delphi than in C/C++ for two reasons:
Delphi checks for uninitialized variables at compile time, which (for whatever reason) a lot of C compilers tend to have trouble with.
Delphi initializes all of its dynamic memory to 0, so you don't have random heap garbage to deal with that might look like a good pointer when it's really not. This means that most bad pointers give you access violations, which are easy to debug, instead of silently failing and corrupting memory.