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 <julien...@gmail.com> 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 clo...@googlegroups.com >>> Note that posts from new members are moderated - please be patient with >>> your first post. >>> To unsubscribe from this group, send email to >>> clojure+u...@googlegroups.com >>> 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 clojure+u...@googlegroups.com. >>> 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 clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com 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 clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.