Re: Common way of error handling?

From: Date: Sat, 13 May 2000 12:59:22 +0000
Subject: Re: Common way of error handling?
References: 1 2  Groups: php.pear 
Request: Send a blank email to php-pear+get-101@lists.php.net to get a copy of this message
Stig Bakken wrote: > > Ulf Wendel wrote: > > > > Hi! > > > > Is there a common way of error handling in PEAR modules? > > There isn't. Personally, I like Java's exceptions in that you throw > objects, and that you can subclass exception classes. DB has a somewhat > abstracted error concept (where the definition of "error" currently is > "negative integer"). It would make sense to steal some from Java and > extend this to make the error concept "an object of this class (or a > subclass)" and make it general at the same time. I also like the way to adopt the java way (again). I've played a lot with the problem of error handling. I started somewhat similiar the way you have choosed in DB just not that elegant. This way has some problems: - return values suddenly change their type - you have long lists (array or defines) with error messages Later on I decided to have one class "error" that handles errors. I passed the error message and the error number to it an let it do the work. It was up to "error" to supress the message, print it or even halt the script. With PHP we can't realize the java way, because we don't have try-catch and throw. But we could overtake some ideas from the class hierarchie, mix the exception and the execption handling within one class hierarchie to get some of java features. (Puh - he seens to be drunk, what does he mean?) Let's look at the key features we need: 1. It must be easy to create an exception within a module. 2. All PEAR modules should have a predefined default behaviour. 3. Each PEAR module must be able to override the predefined behaviour. 4. Each PEAR module must be able to control the reaction on an exception (show, halt), override its own default behaviour. 5. The user should be able to override the default behaviour of a module. Extended "features": 6. There're predefined exceptions. 7. There're different "levels of exceptions": error, warning, notice). 8. There're diffent "kinds of exception": - Runtime (caused by the module itself) - User (caused by the programmer when using the module) - IOException +++ creating an exception +++ Creating an exception must be as easy as possible and the programmer must be able to decide wether to rely on the default exception handling or to override it. + Syntax new pear_NameOfException ( [string $message, int $errno , string $filename, int $linenum, bool $auto_handle ]); + Examples <?php new pear_notice("my notice"); ?> Create a simple note. It's up the the default pear_notice class how to handle it. I suggest don't show, don't halt. <?php new pear_warning("my warning", -1000, __FILE__, __LINE__); ?> Create a warning, provide the exception handler with an error code, the current filename and the current line number. It's up to the default pear_warning class how to handle it. I suggest show, but don't halt. Show always means "show all possible informations, no matter if $errno, $file or $linenum are defined". <?php $err=new pear_error("my_error", -1, __FILE__, __LINE__, false); ?> Create an Error, provide the exception handler with an error code, the default filename and the current line number. The default exception handling is switched off. Now you can decide to call: - $err->handle(), default handling - $err->show(), show the error but don't halt - $err->halt(), show the error and halt As your PEAR modules controles the bahaviour, you can exit your function returning a value of the promised type or halt if necessary. +++ default behaviour of PEAR modules +++ We can gain default behaviour if we use polymorhism. Up to this point we haven't thought about the class hierarchie not even on what classes we need. We have to start with it now to understand my thoughts. We have two basis tasks: - defining exceptions - handling defined exception Translating this to the oo world gives something like this (kind of UML notation): --------------------- | exception handler | | | | show(), halt() | --------------------- ^ 1 | | 1 --------------------- | exception | | | | create exception | --------------------- The default PEAR behaviour resides on level three: --------------------- | PEAR | | exception handler | --------------------- ^ 1 | | 1 --------------------- | exception handler | | | | handle() | --------------------- ^ 1 | | 1 --------------------- | exception | | | | create exception | --------------------- On level four I placed predefined PEAR exceptions such as PEAR_Warning, PEAR_Error, PEAR_Notice: --------------------- | PEAR_Warning | | | --------------------- ^ 1 | | 1 --------------------- | PEAR | | exception handler | | | | handler_warning() | | handler_error() | | handler_notice() | --------------------- [...] On level four a class is usually pretty small, there's only a constructor (see creating an exception). The constructor passes most of its arguments to exception::exception() and calls pear_exception_handler::handle() if requested (default). That's all. Level four is a keypoint. I can't make up my mind how it should look like. Does the class tree branch on the "level of an exception" (notice, warning, error) and stop as shown or do we follow the Java way? Java has no need to mix the event handling and event creation together. They have try-catch and throw, we do not. In Java there is no need to define "levels of exceptions". It's up to who ever catches the exception to "rate" it, to give it a certain "level" (notice, warning, error). Java branches the tree at this point on the "kind of an exception" (Runtime, IOException). Translated to the PHP/PEAR world we would get something like this if we like the idea of "levels": exception::exception_handler::pear_exception_handler::pear_runtime::pear_runtimeerror::pear_wrongparamcount exception::exception_handler::pear_exception_handler::pear_ioexception::pear_ioerror::pear_direrror ... somewhat to complicated. The concept of "levels" (notice, warning, error) seems to be a must in the PHP world. I suggest rating it that high the class modell stops on level four. Introducting a deeper class modell would mean overdoing it. exception::exception_handler::pear_exceptiion_handler::pear_warning::pear_io exception::exception_handler::pear_exceptiion_handler::pear_warning::pear_runtime exception::exception_handler::pear_exceptiion_handler::pear_error::pear_io Instead of this preferr a "faulty" compromise: default exceptions stay on level four: pear_notice, notes that fit nowhere else pear_warning, warnings that fit nowhere else prear_error, errors that fit nowhere else pear_ioexception, an error while dealing with io pear_runtime, a warning that is cause due to wrong use of functions +++ default behavoir of a module +++ Each PEAR module can override the default PEAR exceptions classes and even more provide new exceptions, although I don't thing that this is really necessary for most of the smaller modules. +++ the user should be able to control the exception handling +++ This is necessary e.g. for customizing the handleException() methods that prints the exception, or instance vars such as show_error or halt_on_error. The user could even want use mail() to get informed by e-mail whenever an error occurs. Customization can be done by modifing the exception classes of the module. Experienced users might even modify the pear exception classes. +++ API +++ He're an API demo of the sketched modell: <?php class my_pear_module { function createNotice() { new pear_notice("my_notice"); } function createWarning() { new pear_warning("my_warning", 1000, __FILE__, __LINE__); } /** * @return bool $ok */ function createError() { if (true) { $err = new pear_error("my_error", 1, __FILE__, __LINE___, false); $err->show(); return false; } return true; } } my_pear_module::createNotice(); my_pear_module::createWarning(); my_pear_module::createError(); ?> The class hierachie is pretty simple (as shown above). It takes less than 200 loc in PHP, it's flexible and can be configured widely. It does not come with major restrictions. How about it? Ulf

« previous php.pear (#101) next »