Dear all,
1. I cannot use a global/outer try/catch statement, because the MException caught doesn't contain any reference/handle to the object that threw it. Concretely, if the main script is:
try model = Model() ; project = model.addProject( 'Test' ) ; project.addScenario( NaN ) ; catch ME ... end
with
classdef Project < handle methods function addScenario( obj, name ) assert( ischar( name ), ... ) ; ...
there is no way to get a handle on project from ME, which stores only text (msgID, message), a stack (struct array of names and line numbers), and causes (cell array of other MException objects).
2. If I extend a little this mechanism with:
classdef Core < handle methods function assert( obj, test, varargin ) ... ... classdef Project < Core methods function addScenario( obj, name ) obj.assert( ischar( name ), ... ) ; ...
I could update the MException object in Core.assert (adding clauses), but again, there is no way to add a Project handle to a MException object, so there is no point in having the outer try/catch statement.
3. Accounting for this, I can extend a bit the mechanism and implement something along the following line:
classdef Core < handle methods function assert( obj, test, varargin ) if ~test obj.errorManager( varargin ) ; ... classdef Project < Core methods function addScenario( obj, name ) obj.assert( ischar( name ), ... ) ; end function errorManager( obj, varargin ) ... end ...
which is somehow satisfactory, because I can add an errorManager method to each sub-class of Core, as a separate file in each class folder, and implement as much error management/analysis/reporting as I want without "loading" the rest of the code in the class definition.
Yet, this is not completely satisfactory. I can easily truncate the (DB) stack from the report that I generate, i.e. the first two entries ( Project.errorManager and Core.assert) that should not be displayed, to avoid confusing users who should see Project.addScenario at the top as the source of the error.
But when I throw an exception ultimately from the error manager or elsewhere, it becomes difficult to prevent MATLAB from displaying these first entries. I looked for a way to pass or define a start stack depth for MATLAB to truncate the stack and I didn't find any. The stack property of MException objects is read-only so I am unable to (re)define it.
There are still a few messy alternatives, e.g. throw an exception, post-process the report (easily done using REGEXP and the output of getReport(ME)), print it to stderr, and generate an "empty enough" error, but these tricks seem to be ugly.
Hence my questions:
- Did I miss a fundamental mechanism for managing these situations properly?
- Do you have any cleaner alternative approach? (Keeping in mind that adding clauses to a MException object is not flexible enough).
Thank you,
Cedric
Best Answer