| Exception handling is an essential part of the | | | | The name of the routine in which the exception |
| programming experience, it polishes the application | | | | occurred. |
| and is a bulwark against somewhat forgivable | | | | Line number. If available the code line number or last |
| oversight. We most likely will not cover every | | | | declared line number when the exception occurred. |
| situation in the first build of an application but at least | | | | This can really help pin point the line of code the |
| we can include the ability to handle unforeseen | | | | exception occurred within. |
| runtime exceptions and build some useful tools utilising | | | | Class or module name. This helps locate the code |
| exception systems to help with the application | | | | that threw the exception. |
| development process.CUSTOM EXCEPTIONS | | | | Call stack: This can be useful to trace the series of |
| =================Custom built exceptions are | | | | events prior to the exception. |
| a handy tool for both release and development | | | | Active controls or forms: The current active control |
| versions of an application. They can be used in the | | | | and/or form which could give a clue as to what the |
| following ways:Custom Exceptions as Developer | | | | user was trying to do when the exception occurred, |
| Warnings | | | | although the call stack could cover this instead. |
| ---------------------------------------We can use exceptions | | | | Source of the exception: Perhaps the exception was |
| to remind us of not providing requisite information to | | | | caused by an application interactivity or |
| a class or object. For example: We build a class as an | | | | interoperability. |
| interface to multiple vendor databases, let's call it | | | | Time of the exception: Maybe the user went to |
| Multiple Vendor Management (MVM) class. To connect | | | | lunch before reporting the exception. It may help to |
| to a particular database we perforce provide the | | | | know that when the exception occurred there was a |
| instantiated MVM class with the vendor database | | | | concurrent hiatus of intranet connectivity. |
| type we are connecting to via a database_type | | | | User explanation: An explanation for the user on |
| method within the class. The MVM class also has a | | | | how the exception impacts their ability to carry out |
| SQL_select method that can be called to return a | | | | their tasks. It probably is not necessary to confuse |
| recordset from our chosen vendor database. Within | | | | the user with exactly what went wrong, just that |
| the SQL_select method is a switch (select case) | | | | the application can not perform their task at the |
| statement which decides how to send the 'select | | | | present time.HANDLING HIDDEN ASSUMPTIONS |
| request' to our chosen database type. If we fail to | | | | ===========================As a rule I |
| provide the vendor database type to our class and | | | | put exception handling into almost every routine to |
| call the SQL_select method at runtime or a debug | | | | neutralise the spectre of the hidden assumption. I am |
| compilation, a default (case else) option within our | | | | currently working with a business process |
| switch (select case) statement throws a custom | | | | diagramming application in which there are scripted |
| exception for developers. The custom exception will | | | | reports. One particularly critical report every now and |
| remind a developer during runtime testing that the | | | | then can not complete it's processing, this is a legacy |
| requirements of the class have not been fulfilled | | | | report which has code that makes inadequate use of |
| during our coding. Below is an example of where our | | | | exception handling. Every time the report stops I |
| custom exception can be used:Private Sub | | | | diagnose the problem as missing Lane symbol names |
| SQL_select(SQL As String)dim exp_developer_1 as | | | | within the diagram the report is trying to process. |
| RuntimeException | | | | The developer who had scripted the report |
| exp_developer_1 = new RuntimeException | | | | mistakenly assumed that there would always be a |
| exp_developer_1.Message = "'database_type' | | | | name attributed to a Lane symbol, but when a user |
| property is not set." | | | | forgets to enter a Lane symbol's name, the report |
| exp_developer_1.ErrorNumber = -90000dim rs As | | | | stalls and has no way to handle the exception that is |
| RecordSetselect case database_typecase | | | | thrown. The hidden assumption is: A Lane symbol has |
| MySQL_DATABASE | | | | a name property therefore there is a name value |
| if Connect_mysql then | | | | available within that property. Of course the |
| rs = mysql.SQLSelect(SQL) | | | | developer and client most likely tested the report |
| end if // Connect_mysqlcase ODBC_DATABASE | | | | against well formed diagrams before releasing the |
| if Connect_odbc then | | | | first build so the exception was never thrown during |
| rs = odbcdb.SQLSelect(SQL) | | | | testing. This is not really any party's fault but the |
| end if // Connect_odbccase REAL_DATABASE | | | | result of human fallibility that has not been catered |
| if connect_rbdb then | | | | for by utilising exception handling.EXCEPTION |
| // replace any instance of the word DISTINCT with | | | | LISTENER |
| UNIQUE to cater for RBDB syntax. | | | | ==================Instead of building a |
| SQL = | | | | central exception handler to provide exception |
| Replace_passed_regex_strings(SQL,"sDISTINCTs"," | | | | notification or central exception reporting we could |
| UNIQUE ") | | | | create an class that captures exceptions and |
| rs = rbdb.SQLSelect(SQL) | | | | performs functions based upon the type of |
| end if // Connect_rbdbcase else | | | | exceptions it receives. One function might be to |
| Raise exp_developer_1end selectException | | | | capture exceptions into a collection and provide |
| errd=New MessageDialog | | | | advice to calling routines as to what kinds of services |
| if err = exp_developer_1 then | | | | the application can provide the user at any one time, |
| d.Set_Icon_Caution_Triangle | | | | for example: We have an application that accesses |
| else | | | | several diverse data sources which upon start up fails |
| d.Set_Icon_Stop | | | | to connect to one of it's data sources and throws an |
| end ifd.ActionButton.Caption = "OK"#if TargetWin32 | | | | exception. The exception is handled and passed to |
| or TargetLinux Then | | | | the Exception Listener. From now on any event that |
| //ERR_MODULE is a constant that holds the | | | | opens a form can call the Exception Listener to see if |
| module's/form's name + a full stop | | | | any details the form provides the user are |
| d.Title = ERR_MODULE + "SQL_select"if err = | | | | inaccessible and as a result can disable controls that |
| exp_db_error then | | | | allow the editing or reading of those details. The |
| d.Message = d.ERROR_NUMBER_TEXT + | | | | latter scenario would allow the user to still perform |
| cstr(exp_db_error.ErrorNumber) + _ | | | | some duties although in a limited way, which is better |
| EndOfLine + d.ERROR_DESCRIPTION_TEXT + | | | | than not allowing the user to do any work and may |
| exp_db_error.Message 'message | | | | still enable the user to finish their work tasks with the |
| elsed.Message = d.ERROR_NUMBER_TEXT + | | | | limited functionality provided. When I say limited |
| cstr(err.ErrorNumber) + _ | | | | functionality we could be speaking of only a minor |
| EndOfLine + d.ERROR_DESCRIPTION_TEXT + | | | | disruption to functionality overall.Another benefit of |
| err.message 'message | | | | an Exception Listener could be the ability to |
| end if | | | | periodically check the collection of exceptions it holds |
| #else//ERR_MODULE is a constant that holds the | | | | and try to resolve the original cause of the |
| module's/form's name + a full stop | | | | exceptions. In the example above where our |
| d.Message = d.ERROR_ROUTINE_TEXT + | | | | application could not access a data source, the |
| ERR_MODULE + "SQL_select" + EndOfLine | | | | Exception Listener could thread a retry of the |
| if err = exp_db_error then | | | | connection whilst the application is running and upon a |
| d.Message = d.Message + d.ERROR_NUMBER_TEXT | | | | successful connection notify it's clients of the |
| + cstr(exp_db_error.ErrorNumber) + _ | | | | availability of details from the data source again and |
| EndOfLine + d.ERROR_DESCRIPTION_TEXT + | | | | remove the exception from the collection. This is |
| exp_db_error.message 'message | | | | better than the user having to save what they are |
| elsed.Message = d.Message + | | | | doing, close the application and reopen it to |
| d.ERROR_NUMBER_TEXT + cstr(err.ErrorNumber) + | | | | reconnect to a previously inaccessible data source.If |
| _ | | | | our Exception Listener was a software bus it could |
| EndOfLine + d.ERROR_DESCRIPTION_TEXT + | | | | publish any messages to it's subscribers within the |
| err.message 'message | | | | application and we could have a real-time release of |
| end if | | | | limited functionality within forms, web pages and |
| #endifd.AlternateActionButton.Caption = "Details to | | | | other interfaces.Statistical Analysis of Application |
| Clipboard" | | | | Functionality |
| d.AlternateActionButton.Visible = True | | | | -------------------------------------------------Statistical analysis |
| b=d.ShowModalSelect case b | | | | of the amount of functionality that can be provided |
| case d.ActionButton | | | | by an application can also be published by the |
| case d.AlternateActionButton | | | | Exception Listener where a missing data source may |
| d.Details_to_clipboardcase d.CancelButton | | | | be determined to reduce the application's functionality |
| end selectfinally | | | | by 25%. The user can be notified that the application |
| // clean up | | | | is only 75% functional which would be useful |
| if dNil then d=Nil | | | | information in a unstable environment. The |
| return rs | | | | percentage of functionality would rise or fall based |
| End SubCustom Exceptions used for Call Stack | | | | upon exception resolution and exceptions thrown |
| Retrocession | | | | respectively.Exception Cluster Explanation |
| --------------------------------------------------A custom | | | | -----------------------------With a collection of exceptions |
| exception could be used to create a call stack ( | | | | within the Exception Listener we could abstract out a |
| break out scenario. For example, we have an | | | | comprehensive explanation of what an application's |
| application that is six calls down a call stack of | | | | current capabilities and limitations are by diagnosing |
| database transaction routines and a critical data error | | | | clusters of various exceptions and/or exception |
| has occurred. Instead of handling the exception, | | | | types. When a user tries to perform a task and |
| exiting the routine and allowing the parent routine to | | | | receives an exception the notification of the |
| continue processing it's database transactions we use | | | | exception could provide the ability to open an |
| a custom exception to roll back all calls within the call | | | | explanation dialogue instead of only providing the |
| stack and their transactions. We throw the custom | | | | ability to dismiss the exception notification. The |
| exception within the current routine whose exception | | | | Exception Listener could provide a comprehensive |
| handler rolls back our current routine's database | | | | report upon current application limitations that are |
| transactions and then throws the custom exception | | | | producing current system behaviour. For example, |
| again within the exception handling section of our | | | | even though our application may have successfully |
| routine's code. The exception handler in our current | | | | connected to an Account system we cannot retrieve |
| routine cannot handle the newly thrown custom | | | | a staff member's salary transactions because our |
| exception so transfers control back up the call stack | | | | application cannot access the necessary employee |
| to the previous routine. The previous routine handles | | | | identification details on a Human Resources system |
| the custom exception in the same way, and so on | | | | that is offline. Throwing an exception that informs |
| until we reach the top of the stack, having rolled | | | | the user that an accounts routine can not perform its |
| back all routines' database transactions. The initiating | | | | task does not explain why this has happened and the |
| routine of the stack can then report the exception | | | | user will most likely contact the help desk for the |
| or, the routine that caught the first exception could | | | | explanation, whereas a comprehensive explanation |
| report the exception (see heading Exception | | | | from the Exception Listener which explains the |
| Notification Detail further on in article for why we | | | | effects of a Human Resources system being offline |
| would do this) and then start the retrocession of the | | | | could instantly explain why the accounts routine is |
| stack.Custom Exception Generics | | | | failing the user.SUMMARY |
| --------------------------Custom exceptions do not need | | | | =======Exception handling is an integral and |
| to be specific in their reporting detail, they are | | | | sometimes unappreciated part of any programming |
| custom built so we can change their messages to | | | | regimen. Points covered were:Custom exceptions help |
| better fit the circumstance in which we want to | | | | with the development process using custom |
| throw the exception. For instance, say we have a | | | | developer exceptions to remind developers of missed |
| custom database exception:dim exp_db_error as | | | | requirements during coding. |
| RuntimeException | | | | Custom exceptions can retrocede through a call |
| exp_db_error.number = -10001 | | | | stack and rollback prior transactions and processes. |
| exp_db_error.message = "Database file can not be | | | | Exceptions can handle the scripting of our hidden |
| found."We raise this exception within a routine where | | | | assumptions. |
| the database file is found but is corrupt, we can | | | | Exception Listeners can provide the ability to limit |
| change the message to better fit the circumstance | | | | services within an application allowing the user to |
| of the exception:exp_db_error.message = "Database | | | | perform tasks albeit some functionality will be |
| file is corrupt." | | | | disabled. |
| Raise exp_db_errorThe exception number relates to | | | | Exception Listeners can provide comprehensive |
| database specific issues but the message the user | | | | explanations of limited application behaviour and the |
| receives is more relevant to the situation than a | | | | possible cause of thrown exceptions. |
| generic exception message.EXCEPTION | | | | Exception Listeners can provide a statistical |
| NOTIFICATION DETAIL | | | | percentage of application functionality. |
| =============================Details | | | | Exception Listeners can periodically try to resolve |
| provided in exception notifications perforce should be | | | | earlier exceptions that reduce a system's |
| useful to both the developer and the end user. A | | | | functionality. |
| basic exception-type number and description is usually | | | | Exception notifications can provide enough detail for |
| too vague or concise to be of use to either party. | | | | a developer or vendor to pinpoint the cause of an |
| What good is an exception notification that | | | | exception in code whilst concurrently providing a |
| states:Exp No: 4026 | | | | useful explanation to assuage user anxiety over an |
| Exp Desc: Index out of boundsAn exception | | | | exception.Duane Hennessy |
| notification needs to provide two types of useful | | | | Senior Software Engineer and Systems Architect |
| information, diagnosis information for the developer | | | | Bandicoot Software |
| or the vendor of the application and explanatory | | | | Tropical Queensland, Australia |
| information for the end user or the the vendor's | | | | (ABN: 33 682 969 957)Your own personal library of |
| client. Useful details to provide can be:Routine name. | | | | code snippets. |