How do you name and organize your exceptions? - delphi

When introducing new exception types I am always a but unsure how to do this correctly. Is there a common convention? How do you do it?
I am interested in the scope you organize them (Keep them in the unit they are used in? Have a unit on component level? Package level? Application?)
This also influences naming. How much context do you include? Is it better to make them very specific (like EPersonIDNotFoundError) or try to make them reusable (like ENotFoundError)?
And what about the suffix "Error" - when should I add it and when leave it? I cannot see the logic e.g. in Classes.pas:
EWriteError = class(EFilerError);
EClassNotFound = class(EFilerError);
EResNotFound = class(Exception);

The only real convention I know of, is to prefix them with E.
I haven't really given it much thought in the past, but now I think of it, it seems to me that both Error and Exception are commonly used as a postfix. If you mix them, I'd say that Exception relates to something that goes wrong unexpectedly, like a connection that is broken, or a file that turns out to be unreadable, while an error relates more to wrong input, for instance a number was expected, but someone typed text.
The VCL seems to follow certain conventions too, but it seems to add a postfix only if it wouldn't be clearly and error without it, for instance
EConvertError, EMathError, EVariantError
vs
EAccessViolation, EInvalidPointer, EZeroDivide
The latter describe the error itself, where the first list need the postfix to indicate an error in a certain process or entity.
These examples are found in SysUtils, maybe you can take a look there, because it contains many exception classes as well as base classes for an even larger amount of exception. Very few of those end in Exception, except for some very specific errors that indeed you hope to never come across, like EHeapException and ESafecallException.

When creating a new exception I make it application wide. I start from the most detailed error to the most general, like class(Exception) and I name them accordingly.
So, in your example, I would use EPersonIDNotFoundError, ENotFoundError, Exception.
It really depends on how much detail you want from your error messages and what you include in your log (if you keep a log of errors)

Normally for simple applications you can get away with Exception.Create('ErrorMessage'). Where exceptions get powerful is being able to detect the kind of response required by looking at the class. Delphi already does this by the Abort procedure, which raises EAbort. EAbort is 'special' in that it does not trigger an 'error' as such, i.e. it is a kind of 'silent' exception. You can use this class-specific action to examine an exception and do different things. You could create a EMyWarning, EMyVeryNastyError etc, each descended from the basic Exception type.
Further, you can define a new exception class to carry more information out to the point where the exception is trapped. For example with the code (not checked):
EMyException = class( Exception )
constructor Create( const AErrorMessage : string; AErrorCode : integer ); reintroduce;
PUBLIC
ErrorCode : integer
end;
constructor EMyException.Create( const AErrorMessage : string; AErrorCode : integer );
begin
inherited Create( AErrorMessage );
ErrorCode := AErrorCode;
end;
You now have the possibility to set 'ErrorCode' when you raise the exception and you have it available when the exception is caught. Exceptions are pretty powerful.

Which scope to organize them in?
Use one unit for the whole application where you try to fit in the most general exceptions. Everything else goes into the unit where the exception is thrown. If you need these exceptions in other units then move them to a common unit used by the subsystem you are working on.
How about naming?
Try to make one or two levels of "general" exceptions like ENotFoundError. Put these in the application global file. Don't try too hard to generalize because you can't know what exception will come later requiring you to change everything. Create specialized exceptions on unit level inheriting from the global ones.
What about "Error" postfix?
Stop thinking about it. Add it. Unless it sounds stupid.

Related

Delphi casting with as and Supports difference

What is the difference in casting using Supports vs as keyword, besides that with as I first need to check if cast is possible with is keyword.
Supports will provide an interface if that interface is supported.
is determines if a class/interface derives from another class/interface.
as does the same thing as is, but also returns a type-checked cast.
If you have already confirmed with is that a cast will succeed, you don't need to use as, you can just do a direct cast, which is more efficient:
if(pSomeObjectRef is TMyObject) then
TMyObject(pSomeObjectRef).MyUsefulMethod(...);
As Delphi does not support multiple inheritance, using interfaces is the only way to implement that kind of behavior. An object which can be more than one thing, not just itself or its ancestors.
If you're not using interfaces, you shouldn't need to use Supports().
Using as to cast allows you to cast an object reference to an interface, as well as to a reference to a different class of object. Personally, I don't use as, and I rarely see it in the code I'm looking at. Since as can raise an exception, you ought to take steps to avoid the exceptions, and catch them if they are raised. As you can check these anyway, there should never be a need to use as.
When casting to an interface, rather than relying on the exception to catch the interface not being there, you can use the result of Supports():
if (SysUtils.Supports(pSomeObjectRef, IMyWantedInterface, diInterfaceRef)) then
begin
diInterfaceRef._AddRef(); // removed when diInterface falls out of scope
...
end
else
begin // it doesn't support the interface!
...
end;
Whether you want to catch exceptions (which some people like, some people don't - it does make the code less linear), or code for if..else, is usually a matter of preference. I prefer not to rely on exceptions (but I still have try..finally or try..except blocks), but of course other opinions are available!

Possible obscure causes for Abstract Error in Delphi?

In a Delphi 7 project we installed FastMM. Soon after that we noticed one of the forms started to issue Abstract Error message on close. I have debugged this extensively and I can't find the reason so far. The usual reason for this error message doesn't seem to apply here. The application doesn't define abstract classes. I also searched the form for a possible use of TStrings or something like that. Most importantly, we didn't (well, we think we didn't) make any changes to this form. It just broke.
Are there some other possible causes for this error besides trying to call unimplemented method?
Is there some possibilty that FastMM has enabled some obscure bug in the application, that remained hidden until now?
If the answer to these questions is no, then I'll just continue to search for an unimplemented method call, relieved that I am not missing something else.
If there is memory corruption then all sort of errors can be raised and it is very difficult to find the cause.
To answer your questions: 1) Yes abstract error can also be caused by memory corruption, and 2) Yes enabling FastMM can make bugs visible that normally pass unnoticed (but should still be fixed).
Some general advice for finding memory errors:
Try "FullDebugMode" setting in FastMM.
Make sure everything you Create is matched with a Free.
Make sure nothing is freed more than once.
Make sure an object is not used after it has been freed (or before it has been created).
Turn on hints and warnings (and fix them when they occur).
"It just broke" - it was probably always broke but now you know.
I have seen problems when closing a form as part of a button event. The form gets destroyed and then the remainder of the button messages get dispatched to a no-longer existing button. The Release method avoids this by (from memory) posting a wm_close message back to the form
Answer to question 1 "Are there some other possible causes for this error besides trying to call unimplemented method?"
Yes. This is what caused in my case an Abstract Error:
TWinControl(Sender).Visible:= FALSE;
This worked when sender was a TButton but raised the error (of course) when the sender was something else (like TAction). It was obviously my fault. I should have used "as" instead of a hard typecast.
Answer to question 2: Yes. I have seen that happening too. We should be very clear that this doesn't mean that FastMM is buggy. The bug was 'dormant'. FastMM only triggered it.
Actually you should rely on FastMM even more to find your issue. Switch FastMM to full debug mode for this. It will help you with:
Make sure an object is not used after it has been freed (or before it
has been created)
Also, in a few cases, the whole project was screwed up and I got the Abstract error. Nothing worked until I deleted the DPROJ file. Just do a compare between your current DPROJ file and the one in your back and you will see how the IDE f**** up the file.
You MUST also fix ALL warnings the compiler shows! The compiler is serious about that. It wouldn't raise an warning without a valid reason. Fix that and you will probably fix your problem.
In this particular case I would also replace all .Free with FreeAndNil().
You could try to add u_dzAbstractHandler to your project. It should raise the abstract error where the method was called, so it is easier to debug it. Of course this only helps when the error occurs when running in the debugger.
https://osdn.net/projects/dzlib-tools/scm/svn/blobs/head/dzlib/trunk/src/u_dzAbstractHandler.pas
Could be that one of your abstract functions/procedures in the base class is not implemented;
try this :
e.g
type
TBaseClass = class (TObject)
public
procedure DoSomething; virtual; abstract; //not implemented procedure
end;
type
TInheritedClass = class (TBaseClass)
public
procedure DoSomething; override;
end;
//Implementation
procedure TInheritedClass.DoSomething;
begin
//your code
end;

Exception thrown Constructor Injection - AutoFac Dependency Injection

I have an Autofac DI Container and use constructor injection to inject configuration settings into my SampleClass. The Configuration Manager class is created as a singleInstance so the same single instance is used.
public ConfigurationManager()
{
// Load the configuration settings
GetConfigurationSettings();
}
public SampleClass(IConfigurationManager configurationManager)
{
_configurationManager = configurationManager;
}
I am loading the configuration settings from a App.config file in the constructor of the configuration Manager. My problem is i am also validating the configuration settings and if they are not in the App.config file a exception is thrown, which causes the program to crash. Which means I cant handle the exception and return a response.
I am doing this the wrong way? Is there a better way to load the configuration settings Or is there a way to handle the exception being thrown.
Edit
ConfigurationManager configurationManager = new ConfigurationManager();
configurationManager.GetConfigurationSettings();
//Try catch around for the exception thrown if config settings fail
//Register the instance above with autofac
builder.Register(configurationManager()).As<IConfigurationManager>().SingleInstance();
//Old way of registering the configurationManager
builder.Register(c => new ConfigurationManager()).As<IConfigurationManager>().SingleInstance();
You are doing absolutely the right thing. Why? You are preventing the system from starting when the application isn't configured correctly. The last thing you want to happen is that the system actually starts and fails later on. Fail fast! However, make sure that this exception doesn't get lost. You could make sure the exception gets logged.
One note though. The general advice is to do as little as possible in the constructor of a type. Just store the incoming dependencies in instance variables and that's it. This way construction of a type is really fast and can never really fail. In general, building up the dependency graph should be quick and should not fail. In your case this would not really be a problem, since you want the system to fail as soon as possible (during start-up). Still, for the sake of complying to general advice, you might want to extract this validation process outside of that type. So instead of calling GetConfigurationSettings inside that constructor, call it directly from the composition root (the code where you wire up the container) and supply the valid configuration settings object to the constructor of the ConfigurationManager. This way you -not only- make the ConfigurationManager simpler, but you can let the system fail even faster.
The core issue is that you are mixing the composition and execution of your object graph by doing some execution during composition. In the DI style, constructors should be as simple as possible. When your class is asked to perform some meaningful work, such as when the GetConfigurationSettings method is called, that is your signal to begin in earnest.
The main benefit of structuring things in this way is that it makes everything more predictable. Errors during composition really are composition errors, and errors during execution really are execution errors.
The timing of work is also more predictable. I realize that application configuration doesn't really change during runtime, but let's say you had a class which reads a file. If you read it in the constructor during composition, the file's contents may change by the time you use that data during execution. However, if you read the file during execution, you are guaranteed to avoid the timing issues that inevitably arise with that form of caching.
If caching is a part of your algorithm, as I imagine it is for GetConfigurationSettings, it still makes sense to implement that as part of execution rather than composition. The cached values may not have the same lifetime as the ConfigurationManager instance. Even if they do, encoding that into the constructor leaves you only one option, where as an execution-time cache offers far more flexibility and it solves your exception ambuguity issue.
I would not call throwing exceptions at composition-time a good practice. It is so because composition might have a fairly complex and indirect execution logic making reasonable exception handling virtually impossible. I doubt you could invent anything better than awful
try
{
var someComponent = context.Resolve<SampleClass>();
}
catch
{
// Yeah, just stub all exceptions cause you have no idea of what to expect
}
I'd recommend redesigning your classes in a way that their constructors do not throw exceptions unless they do really really need to do that (e.g. if they are absolutely useless with a null-valued constructor parameter). Then you'll need some methods that initialize your app, handle errors and possibly interact with user to do that.

What's the cost of reraising an exception?

Is this
try
DoSomethingThatMightThrowAnException;
except
on E : ESyntaxError do
begin
if (E.ErrorCode = errMissingBracket) then
HandleError
else
raise;
end;
end;
slower than this?
try
DoSomethingThatMightThrowAnException;
except
on E : EMissingBracketSyntaxError do
begin
HandleError;
end;
end;
What's the difference to be expected? Does it matter? Note that this could happen several times through the call stack.
What's the difference to be expected?
The difference between the scenarios you described is minimal.
However there is a signifcant difference between raising an exception and not raising one at all (using error results).
Does it matter? Note that this could happen several times through the call stack.
You should only use exceptions for "exceptional situations". If the error is frequent, especially for example in a loop then it deserves to be elevated to a fully fledged use-case scenario.
If you don't do this, what starts out seemingly simple, quickly deteriorates into a situation where your except block becomes bigger than the rest of your routine.
Ordinarily it should be quite trivial to check the condition and deal with it as an explicit branch in main-line code.
I.e. instead of:
begin
try
//Do1
//Do2 (possibly raising an exception that you can handle)
//Do3
//Do4
except
//Dealing with main-line cases in exception handlers is
//very bad, leading to difficult to read code in the future.
end;
end;
Rather write:
begin
//Do1
//LDo2Result := Do2
//NOTE: Do2 can still raise exceptions in EXCEPTIONAL situations.
// But for "main-line" use-case scenarios should rather return explicit
// results that can be handled.
if LDo2Result = d2rNoErrors then
begin
//Do3
//Do4
end;
if LDo2Result = d2rBracketMissing then
begin
//DoX
end;
end;
The above is generally better in both performance and maintainability than either of the scenarios you describe. However, as with all things software development related: you get a pallette of guidlines and techniques, but you need to apply your experience to choose "the best tool for the specific job currently at hand".
Unless your program's logic severely relies on exceptions (which is probably a sign of bad design) I think it will hardly matter since exception handling will only be 0.5% of the cpu time your application takes.
But taking a wild guess, I don't think there will be much of a performance difference, since internally the exception will be passed on either way.
On the other hand, I prefer the second method a lot more since you are expressing what you want syntacticly in the language, which is good. But I understand that method one can be preferred in some cases, especially when the context is bigger and more complex.
Disclaimer: I have never programmed in Delphi and I know nothing about the internals of the language. There might as well be a huge difference in performance, I don't know.
The performance difference is negligible in the context of a real-world application. On my machine raising and handling an exception (with a null handler) takes about 0.3 milliseconds, and if I add extensive logging, abut 1.3 milliseconds. So if the exceptions are truly exceptional, it will not make one jot of difference to your application's performance.
I've had a quick look at the assembler the compiler spews out for above code snippets. Turns out that the bytes right after jmp #HandleOnExeption contain data such as the exception class pointers you use in the on clauses (if any).
I'm not that well versed in assembler to know exactly what's going on, but enough to understand what is roughly going on and come to this conclusion:
I suspect System.pas' HandleOnException does a call #IsClass already, and passes the exception on if no suitable handler is found, so if you use on e:Exception and re-raise, this will add a little code and make two calls extra:
one back to your exception handling section (in all cases)
one call #RaiseAgain (in cases the exception gets re-raised)
So, there's a difference. A minor one, but still, it's there.

Delphi Win32 Programming/Access Violation problems

I wasn't entirely sure how to name this, so apologies in advance.
You see, I'm trying to teach myself Win32/DirectX programming, utilizing Delphi (my language of choice) using this site - http://rastertek.com/tutindex.html
Of course, the site being all in C++, I have to port it to Delphi. It seemed simple enough, at first. I'm on the second tutorial for DirectX 11 - setting up the framework and getting the initial window to show up.
Now for my actual problem. I was getting Access Violation errors. So I found and started to use MadExcept to try and find out what was going on. So it tells me the lines, but I'm clueless as to how to solve the issues at hand.
I have everything set up to mimic as well as I can the original source code. The only real difference being that in the instances where a pointer to a class for a variable, such as the case with m_input, m_grahics, and system, I made a type for those. So I have the TSystemClass, TInputClass, TGraphicsClass, and then I have PSystemClass, etc. that = ^TSystemClass, etc. I figured that this would make things a bit simpler and more neater. On a side note, I assume it should be said, but I for the construction of the copy constructors made the initial classes inherit from TPersistent so I could use it's Assign procedure.
So, back to the Access Violation errors. So first, the problem was in the main program with system being of type PSystemClass. So for a reason unknown to me, when I tried to use system.create, it was at that very instant, creating the access violation. I then realized however that I wasn't assigning system the system.create. So I tried this, and it said that, and rightfully so I suppose, at compile time an error that the two were incompatible since system.create is of type TSystemClass, and system is of PSystemClass. So I tried typecasting it, and that worked. but once again, still getting the dreaded access violations.
So then I had an odd idea, maybe I should call the regular constructor right from the TSystemClass itself. And I tried, needed to typecast again. So I did. And it worked! No longer an access violation error there! Now... New problem! Or rather in this case "problems". There's 3 things now listed in the call stack in MadExcept. The first one:
m_hinstance := GetModuleHandle(nil);
It's saying that this is causing an access violation error. Though why is this, exactly? From what I understand and have read, if GetModuleHandle is set to null/nil, it should retrieve the handle for the file that called it, right? And from what the documentation says, that should be executable.
However note: I'm not sure if the fact that I have the main program, the systemclass stuff, the inputclass stuff, and the graphicsclass stuff, all in different program/unit files to mimic the nature of the original source code. So is this possibly what's causing it? And if so how would I fix it? By putting all of the code from the unit files into the main program file? Though that, in my own personal opinion, would be quite messy and unintuitive.
The next one baffles me even more.
InitializeWindows(ScreenWidth, ScreenHeight);
I'm not dealing with anything other then a function to register the window class and set things up for the window and all here. So I'm not quite sure what the problem here is since it only deals with 2 parameters and they're defined and all already before it's called. So I'm not quite sure what the problem here is at all and what exactly is causing the access violation.
and then finally the final one is in the main program:
return := system.initialize;
Return is what I used in all instances of the result variable of the original source code, as result is of course a built in variable of all functions.
I suppose if system is never able to properly do what it's meant to do then something could/should happen here. Likewise, because I used TSystemClass.Create (typecasted to PSystemClass) earlier to create system would that do anything here? And is it possibly linked to the other two because they're not able to do their own thing properly?
And on a final note; there is one last thing actually on the call stack in MadExcept.
It says Kernel32.dll in the module section, but aside from the main thread, it lists nothing else. (If this information is needed I'll gladly put it up).
Thanks in advance to anyone who's read this far and I hope to find some help on this problem so I may further my studies.
You're instantiating your classes all wrong. Here's an example from TSystemClass.Initialize:
m_Input := PInputClass(m_Input.create);
That's a variable you declared as a PInputClass.
Earlier, in TSystemClass.Create, you initialized that variable:
m_Input := nil;
So, since you have a null reference, it should be clear that you can't call any methods on it. In particular, you cannot call Create on it. Instead, call Create on the class you want to instantiate: TInputClass.Create.
That constructor returns a value of the type you constructed, a TInputClass. It doesn't return a PInputClass, so your type-cast is wrong. As Cosmin's comment explains, Delphi object variables are already pointers. It's exceedingly rare to have to declare a pointer type based on Delphi classes. The correct code is this:
m_Input := TInputClass.Create;
After that line, you check whether m_Input is null. You never have to do that in Delphi; a constructor either returns a valid object, or it doesn't return at all. If there's a problem constructing an object, the constructor throws an exception and the assignment statement never executes. (The original C++ code does it wrong, too. The new operator hasn't returned a null pointer on failure for over a decade, long before anyone was in a position to start writing a DirectX 11 tutorial.)
You should first of all try to get rid of the TPersistent inheritance. If you want to pass an object to a library its interface should be exactly the same as the original that is used in C++. By inheriting from TPersistent you take a whole lot of load into your class that might be not needed or might even be the reason of your problems.
Additionally it would help if you posted the exact output of the exceptions. Or even the CallStack. That might help tracing down the error.

Resources