Hi.

> > I'd like to stress that using exceptions for control flow is, by default, an
> > anti-pattern.  It should pose question about how to improve CM so that you
> > don't have to fall back on this kind of construct...
> 
> Please don't focus only on this example but look at the rest of the
> arguments. Retrieving the building blocks from one exception to build
> something else meaningful to the user application is *not* control flow.
> 
> > 
> > IIUC the above code, the problem that might occur is not a complex
> > computation that fails, but a "wrong" usage (from the viewpoint of the
> > called code) due to a missing parameter. Wouldn't it be possible to have a
> > checking method in "ParameterJacobianProvider" such as
> > 
> >   public boolean isValidParameter(String ... paramNames) {
> >     // return "true" if all passed parameters are known,
> >     // false otherwise.
> >   }
> > 
> > and "somehow" make the check in order to avoid making a call that will fail?
> 
> You don't understand. You focus on *one* example, with *one* exception
> and don't look at it as one case of a more general problem.

Did you indicate what that general problem was?
"I want to access the pattern" is not a problem description.

>From what I read here, I can only assume that what you say is: "I didn't
find another way to do it". You give me an example, and I provide feedback
on that example.

> I
> unfortunately cannot provide an example for every hundred of patterns we
> have in the enumerate and wait for you to answer with one specific
> precondition checker for each one. Also bear in mind that it is not
> always possible to know beforehand some call will lead to an error.

I noted that (from the previous mail). [Do I need to add that I knew it from
before?  The code I work on also takes input that could be found to be
invalid only after a few computations that fail and finally throw an
exception. It is a specific exception whose type indicates what kind of
failure happened; it stores the parameters that were ultimately found to be
incompatible, and accessors can provide the values.]

> Preconditions are not a solution to everything and errors don't mean
> user did a "wrong" use or sent "illegal" parameters.

I noted that (from the previous mail and before).
Can we agree that what can be checked beforehand, should be (if just because
having an explicit check makes the code self-descriptive)?

Thus, let's push that aside and focus on the other problems.

> There are many
> cases when you cannot know something will fail and you have to first try
> it, then get an exception,

Yes (answered above).

> attempt to identify it

That is the crux of our diverging opinions.
In Java, we have exceptions as types; we should be using the feature.
Instead, your usage is a C-style solution (and the set of "errors" being an
"enum" instead of plain strings does not change much about the chosen scheme
itself).
[I agree with the "enum" strategy for localization, not for anything else.]

In my opinion, the "attempt to identify" should be trivial:

 try {
   // "something"
 } catch (TheExceptionYouWantToCatch e) {
   // "do what is possible at your level"
 }

[I've been saying on this list that specific exceptions are useful. Your
example shows that they are useful. Yet, every time, I get: "No, they are
not" and the usual "there are too many enums" (let's fix that, then).]

> and finally do what is
> possible at your level. But for this, you need some valuable information
> that is already carried by the exception, but currently hidden and with
> no accessor.

A type is defined by the set of values it can take (iow the information it
contains). If you are interested by the kind of failure, let's have as
specific exception. If you are interested in the parameters that led to it,
they can be stored in the exception object. If accessors are missing, let's
add them.

After all, that's _exactly_ what you do (although in a contorted way): you
extract the kind of failure from the pattern instance, and you extract the
values from the "messages" stored in the "context". [When I wrote this code,
the intention was that the "pattern" and "message" parts of the exception
were for error message display and localization. For all purposes this part
of the context should have stayed a "black box".]

There is another distinct part of the context that was supposed to be used
for holding _user_ information, to be set (resp. retrieved) with the "setValue"
(resp. "getValue") method. That "public" part of the context can be
enhanced as the exception propagates (catch, set additional info, rethrow)
to the place where you can possibly do something.

The dichotomy was a neat idea, I think.
Forcing the "black box" to become part of the API (i.e. your request below)
is not.

> 
> What I ask for (read make a request as a user) is for two getters for
> parameters that already exist. I need these pieces of data and I don't
> want you to judge why I need them. Without these getters, I would be
> forced to do even uglier hacks like parsing the message or using
> reflection to get the fields.

This argument is going nowhere unfortunately; you give me an example, then
discuss about something else once I demonstrate how it could be be done
otherwise. [Decide on a course of action based on the cause of failure is
not the same thing as customizing a message. But both are more easily done
when dealing with specific exceptions. I showed the first, base on your
provided example; I could show the second, pending another example...]

It's not because you are able to write something even more obscure, that
this is the "ideal" code.
Then, I don't "judge why you need" something, I give an opinion about
another way to design a code, if we were blessed with some additional
utilities (like specific exceptions) in order to spare repetitive,
distracting (boiler-plate) constructs later. [It's exactly what I asked to
be modified from the time when all the exceptions in CM were built by a
factory and their messages were constructed on the spot...]
In the end, there is also a part of aesthetics in these discussions. [It is
_my_ opinion that if you really need what you say you need, then there is
something broken in the library. That you are happy with your workaround
will not change my opinion about the brokenness of the code that forces you
to use that hack.]

Obviously, a code that does the job is equivalent to another one.
The only differences which I'm discussing here are in the eye of the
developer.

There must be something imprecise in the CM project description which I've
read somewhere, mentioning "state-of-the-art". I understood it as "best
practices in Java programming and OO design", but I must have been wrong.


Sorry for the long and notably useless post,
Gilles

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to