Interesting.

Validation is the case I am thinking of - but it might also apply to any 
situation where you offer a different path of control - i.e. not stepping 
back up the stack. That's why I mentioned CPS. That's also (maybe) why true 
tail calls would be useful.

The mention of binding dynamic vars is interesting and I will look at this. 
It still leaves the question of how/when to pass control to actually manage 
or respond to the validation error. I have generally kept away from dynamic 
vars to date because I don't have a good feel for when and where they are 
and are not a good choice. This would be a great area for a blog post - or 
clojure docs doco -  if anyone who has used them extensively can offer a 
good view of pros and cons, whens and when nots :)

Marko, do you have a good example of doing what you say?

The reasons given for not using Exceptions are still not really convincing 
to me (yet). Although I do accept that some things may become more 
difficult to manage if you don't take care in what you do. This is 
generally true. I just see Exceptions as a way of managing control with 
pros and cons, not an anti pattern.

Maybe a more general question is what alternative control flows are 
available - which are possible but not available - and which are good for 
which situations.

Apologies to the original questioner for changing the focus of the recent 
posts.

Dave


On Wednesday, 20 March 2013 19:36:46 UTC+11, Marko Topolnik wrote:
>
> Exceptions are a perfect tool for flow control, if used judiciously. The 
> typical criticism revolves around their incompetent usage, and a more 
> general criticism can be made against a mechanism that is subverted all too 
> easily.
>
> If you responsibly keep to the "good parts", exceptions could be the way 
> to go. Validation is one example where I love them because it happens all 
> around, but validation failures are all handled uniformly.
>
> However, I would also urge you to explore other approaches, such as having 
> a dynamically-bound variable that collects all the validation failures, 
> which will potentially give you better diagnostics than the fail-fast 
> behavior of validation excptions.
>
> -marko
>
> On Wednesday, March 20, 2013 2:24:12 AM UTC+1, Dave Sann wrote:
>>
>> I am interested in this view that exceptions are an anti pattern. I have 
>> heard it voiced before.
>>
>> I am not sure that I understand why.
>>
>> As I see it you have a choices:
>>
>> 1. Handle in the result  - and test this result repeatedly all the way 
>> back to the caller
>> 2. Handle "out of band" - Throw an exception, allow the stack to unwind 
>> and catch where it matters
>>
>> [And maybe - but I am not very knowledgeable on this and it won't work 
>> today on the JVM anyway
>>  3. Use continuation passing style with TCO to shortcut the return to 
>> follow an exception path]
>>
>> So, ignoring 3.
>>
>> Why is 2 preferable over 1? There are certainly pros and cons.
>>
>> Dave
>>
>>
>> On Wednesday, 20 March 2013 09:42:11 UTC+11, James Reeves wrote:
>>>
>>> I'd argue that using exceptions for control flow is something of an 
>>> anti-pattern, even in Java.
>>>
>>> In this case a better mechanism might be to use polymorphism. For 
>>> instance:
>>>
>>> (defprotocol Validatable
>>>   (validation-errors [x] "Return the validation errors for x."))
>>>
>>> (defn valid? [x]
>>>   (empty? (validation-errors x)))
>>>
>>> Then you can define a general function to validate and store that item 
>>> in a database:
>>>
>>> (defn store-valid [db x]
>>>   (if (valid? x)
>>>     (store db x)
>>>     (validation-error-response x)))
>>>
>>> - James
>>>
>>>
>>> On 19 March 2013 16:43, Julien Dreux <[email protected]> wrote:
>>>
>>>> Hi all,
>>>>
>>>> Coming from a Java background, I am having a hard time understanding 
>>>> how validation error propagation should work in clojure web APIs.
>>>>
>>>> To be clear, this is similar to how my Java web service would be setup:
>>>>
>>>> /** Method that validates the model, accesses the DB. If something went 
>>>> wrong, throw an exception */
>>>> public void validateAndCreateUser(User u) throws ValidationException, 
>>>> EmailAlreadyInUseException, ... {
>>>>   ...
>>>>   if(...) {
>>>>     throw new ValidationException(fieldName);
>>>>   } else if (...) {
>>>>     throw new EmailAlreadyInUseException(u.getEmail());
>>>>   }
>>>> }
>>>>
>>>> /** Endpoint method, catches & formats the exceptions thrown by the db 
>>>> method. **/
>>>> @POST("/api/user/create")
>>>> public Response createUser (User u)  {
>>>>   ..
>>>>   try{
>>>>     validateAndCreateUser(u);
>>>>     return Response.ok();
>>>>   } catch (Exception e) {
>>>>     return generateExceptionResponse(e); //Method that maps exceptions 
>>>> to responses.
>>>>   }
>>>> }
>>>>
>>>> For all of Java's clunkiness, this had the benefit of not having to 
>>>> write tons of if/else statements for validation handling. Exception were 
>>>> just thrown from anywhere, bubbling back up to inital call, and if not 
>>>> handled in the endpoint method, a specialized class mapped them into a 
>>>> proper response. The exceptions contained all the information needed to 
>>>> generate 'rich' error messages back to the client.
>>>>
>>>> Being a Clojure newbie, I wonder what a good pattern is for a similar 
>>>> situation. So far, I have a method that validates models based on a 
>>>> schema, 
>>>> that returns
>>>>
>>>> {:success true}
>>>>
>>>> or 
>>>>
>>>> {:success false :errors ["error 1" "error 2" ...]}
>>>>
>>>> But I don't know how to avoid having to write if/else conditions of the 
>>>> sort in each function between my endpoint and db functions.
>>>>
>>>> (if (validation :success)
>>>>   (follow-normal-path)
>>>>   (handle-validation-errors validation))
>>>>
>>>>
>>>> Any guidance appreciated.
>>>>
>>>> Cheers,
>>>>
>>>> Julien
>>>>
>>>> -- 
>>>> -- 
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Clojure" group.
>>>> To post to this group, send email to [email protected]
>>>> Note that posts from new members are moderated - please be patient with 
>>>> your first post.
>>>> To unsubscribe from this group, send email to
>>>> [email protected]
>>>> For more options, visit this group at
>>>> http://groups.google.com/group/clojure?hl=en
>>>> --- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "Clojure" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to [email protected].
>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>  
>>>>  
>>>>
>>>
>>>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to