- Use of ThrowAsCaller to hide helper functions.
- This code assumes object has name better to use evalc and disp of object in portable code.
- Any number of types of exception are possible.
- From the command line MException.last can be used to retrieve the exception object.
Error management in OOP framework.
3 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
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
0 commentaires
Réponse acceptée
Philip Borghesani
le 1 Déc 2017
Modifié(e) : Philip Borghesani
le 1 Déc 2017
I am not sure if this code helps you or not but have you tried subclassing MException to add an object?
Things to look for in code:
classdef ObjException < MException
methods
function obj=ObjException(src,varargin)
obj=obj@MException(varargin{:});
obj.sourceObj=src;
end
function rep=getReport(obj,varargin)
rep=sprintf('Object Error on object %s\n%s', obj.sourceObj.name, getReport@MException(obj,varargin{:}));
end
end
properties
sourceObj
end
end
classdef testobj
methods
function meth(obj,arg)
assert(obj,arg);
end
function assert(obj,cond,varargin)
if ~cond
if nargin>2
ex=ObjException(obj,varargin{:});
else
ex=ObjException(obj,'testobj:AssertFailed','assertion failed');
end
throwAsCaller(ex);
end
end
function error(obj,varargin)
ex=ObjException(obj,varargin{:});
throwAsCaller(ex);
end
end
properties
name
end
end
>> to=testobj
>> to.name='foo'
>> to.meth(true)
>> to.meth(false)
Object Error on object foo
Error using testobj/meth (line 4)
assertion failed
2 commentaires
Plus de réponses (0)
Voir également
Catégories
En savoir plus sur Software Development Tools dans Help Center et File Exchange
Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!