M
Mike Hofer
That's certainly true, and only you can decide which way the trade-off tips
for your particular API. However, the larger and more diverse the intended
developer audience for your API, the more emphasis you should be placing on
the interests of the API users versus those of the API developers.
That's a very valid point, and one well worth consideration. Even if
the code is well documented, and the end-user documentation is clear,
a user who is simply testing code may be in for a surprise when an
exception is thrown by the library and they've never worked with it
before. It's something I hadn't thought of before.
It's a shame there's no way to build or modify the stack trace to
remove the entries so that they accurate reflect the offending
routine.
See my response to Jon. The cases where the framework does this are
probably not desirable.
Are you sure that all the developers in your intended API audience are all
that competent, experienced, etc.? If so, then you have no worries.
I am expecting a *certain* degree of competence. I would expect that
anyone using this library is looking for a way to improve code
quality, much like a user who seeks out NUnit to improve code quality
through the use of TDD. However, as you've said, it's certainly going
to be interesting to see what happens when users look at the thing and
they've never seen it before, and the stack trace contains additional
entries.
Where do you get that idea? If encouraging argument validation was a
serious goal for the folks on the CLR or language teams at Microsoft,
declarative validation would have made its way out of the Spec# research pit
quite some time ago, and they would never have permitted the introduction of
automatic properties without support for declarative validation. Heck, they
could have done as little as salvaging the XC# post-compiler
(http://www.resolvecorp.com), which seems to have suffered a largely ignored
demise sometime before Visual Studio 2005 was released.
Personally, I would argue that there is next to no framework support for
doing the right thing with respect to argument validation, but then I might
just be a bit bitter...
Whoops! That was my bad! By "framework" I was referring to the
framework that I am developing. I usually refer to the .NET Framework
with "Framework" (capital F). (I'm a spelling nazi, but always forget
that this is the Internet, and it doesn't universally apply, and
others may not pick up on that.)
What I should have said was that the purpose of the framework that I
am developing is to refactor complex code. The .NET Framework itself
almost certainly *never* does this, as you well know, but gives you
the raw building blocks, and then you have to refactor the hell out of
it.
My apologies for not being clear on that.
Again, if it actually buys you nothing because your intended audience are
sufficiently sophisticated, then it's probably not worthwhile. However,
it's not actually all that much more work to put the throws in the target
There's a way to avoid the impact on the stack trace, but it's terribly
inelegant and would require adding more code to the target method. However,
just for the sake of completeness, here it is...
Since the call stack for an exception is generated when it is thrown, your
target method would wrap its validation method calls in a try catch that
explicitly rethrows any caught argument exceptions. e.g.:
Try
Validate.That(siteId, "siteId").IsNotNegative()
Validate.That(name, "name").IsNotNullOrEmpty()
Validate.That(buildingIdToIgnore,
"buildingIdToIgnore").IsGreaterThan(-2)
Validate.That(connection).IsOpenAndIsNotNull()
Catch ex As ArgumentException
Throw ex
End Try
Personally, I think it's far less palatable than the alternatives, but
ymmv...
Just brainstorming here, but let me run this by you. Since I can't
modify the stack trace itself, and since I don't want additional
information in it, what if I used a custom exception class, such as a
ParameterValidtationException, and that class shadowed the StackTrace
property. I could then rewrite the stack trace so that I could fetch
it, remove the extra entries, and then expose the cleaned list to the
end user? Further, I could then extend that class with specific
exception types, if need be, to mimic the standard argument
exceptions.
It might have several advantages: most notably, it keeps the stack
trace clean, but it also tells you explicitly that the exception was
thrown by the validation framework. With some optimization, the code
to clean the stack trace can be kept clean, small, and fast.
Thoughts?