On 9/2/12 4:44 PM, Gilles Sadowski wrote: > 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.
Probably what you remember reading is this on the home page: " All algorithms are fully documented and follow generally accepted best practices." We have never claimed to be anything more than a practially useful, open source, open-development Java mathematics library implementing standard algorithms with no dependencies or IP encumberance and good documentation. This is consistent with how other Commons components describe themselves. The key is that *usefulness*, *ease of use* and *approachability of the code* is more important than any one developer's idea of what constitutes "best coding practices" or "state-of-the-art" Java (whatever that means). It seems a reasonable compromise in this case would be to provide the getters that Luc is asking for (making the library easier to use), while at the same time continuing to build out the exception hierarchy so that more use cases can be handled without programmatically unpacking exception contexts. Phil > > > 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 > > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org