I found the `cognitect.anomalies` namespace useful to provide some
uniformity in error codes and their meaning.

https://github.com/cognitect-labs/anomalies



On Fri, Oct 26, 2018 at 6:03 PM Oleksii Kachaiev <kacha...@gmail.com> wrote:

> Sean, that's what I'm actually talking about.
>
> 1. There's no standard way to return "predictably" bad result. I don't
> know what you meant with "documented way through its return value". There's
> no Either with Left/Right (Scala, Haskell), no Result with Ok/Error (Rust),
> there's no "second value with an error" (Go) etc etc etc. You have to come
> up with your own way to distinguish bad and good result. And they will be
> different for different libraries. And that's right the problem I've stated
> in my message. No unification means manually work in each use case.
>
> 2. The standard library throws exceptions even when the error might be
> conveyed as the result of the call. Probably because of #1 - there's no way
> to express that.. Well... except exceptions. So, we're running circles here.
>
> BR,
>
> On Saturday, October 27, 2018 at 12:48:27 AM UTC+3, Sean Corfield wrote:
>>
>> For any library – for any function – there are always two classes of
>> unhappy path:
>>
>>
>>
>>    1. Expected, known failure modes.
>>    2. Unexpected, exceptional failure modes.
>>
>>
>>
>> The former should not use exceptions. The library/function should signal
>> the error in a documented way through its return value. Calling code should
>> check the return value to see if the library/function failed in one of the
>> expected, known, documented ways it is known to be possible to fail in, and
>> respond accordingly.
>>
>>
>>
>> The latter can (and should) use exceptions. An exception says “I got into
>> a state I can’t handle because I wasn’t expecting to get there!” and maybe
>> the caller can handle that and maybe it can’t. Library/function authors can
>> help callers here by:
>>
>>
>>
>>    1. Providing a clear but succinct message for the exception,
>>    2. And providing as much potentially useful detail in the ex-data as
>>    possible.
>>
>>
>>
>> Does Java (and its standard library) overuse exceptions? Yes, absolutely.
>> It throws exceptions for all sorts of completely predictable failure modes.
>> We don’t need (or want) to be Java.
>>
>>
>>
>> Clojure provides perfectly good features to support both the expected and
>> the unexpected failure modes and, in particular, provides an excellent way
>> to convey information about the point of failure even when our code doesn’t
>> know how to recover.
>>
>>
>>
>> As Alex says, there may be value in providing a spec in your library for
>> the sort of ex-data you provide around exceptions. You’ll already be in
>> “regular Clojure land” as far as functions that return values that may
>> indicate success or expected, known failure modes.
>>
>>
>>
>> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
>> An Architect's View -- http://corfield.org/
>>
>> "If you're not annoying somebody, you're not really alive."
>> -- Margaret Atwood
>>
>>
>> ------------------------------
>> *From:* clo...@googlegroups.com <clo...@googlegroups.com> on behalf of
>> Oleksii Kachaiev <kach...@gmail.com>
>> *Sent:* Friday, October 26, 2018 2:28:35 PM
>> *To:* Clojure
>> *Subject:* Re: An Error spec?
>>
>> I've got the idea that you're not going to including anything like this
>> into core library. I just want to clarify because I'm actually a bit
>> confused here, and I think I'm not the only one. We promote
>> doing functional programming, staying declarative when possible, using data
>> with small pure testable functions as much as we can... and at the same
>> time declaring the "official" way of handling errors using exceptions,
>> which are side-effects by their nature, even tho' they play really poorly
>> with:
>>
>> * laziness (which is a default behavior for most operations with most
>> collections in the language)
>>
>> * multi-threaded code (especially in case of "opaque" jumps between
>> threads/executors when using core language concurrency primitives, or even
>> trying to emulate async event loop, i.e. with core.async)
>>
>> * macros (often macroexpand screws up the only feature we love about
>> exceptions: traces, making them pretty much useless)
>>
>> I thought that the design approach of using data and staying declarative
>> should also be applied to errors handling. And a contract declared for a
>> function should reflect not only "the happy path" but all potential cases.
>> We see a lot of languages put some mechanics into the core library or
>> language design (i.e. Scala, Rust, Haskell, Go etc) because errors and
>> errors handling is a very significant part of our programs that we just
>> cannot ignore. You can like or dislike them, you can always come up with
>> something very specific for your application or library. But the key idea
>> here is that core functionality is a rule of thumb for libraries &
>> ecosystem in general. So, when I do pick up library I can assume by default
>> the way errors are handled. Most probably my code and libraries that I'm
>> already using would play nicely with each other. Which is not the case in
>> Clojure. As a creator of a few Clojure libraries, I always have to design
>> upfront what my library will do with errors, either with my own
>> implementation or embracing/adopting one of the existing libraries to
>> handle control flows. And each time I'm struggling with the choice because
>> I know perfectly well that a) most other libraries in the ecosystem would
>> not be aligned with it automatically, b) most applications/users will be
>> forced to learn how to deal with the control flow in this specific case.
>> More libraries you use = more cases of how errors are handled here and
>> there = more time you need to teach them to talk to each other. It seems to
>> me that the "write about your exceptions in the documentation and pray all
>> users of your code will read that carefully and think through really hard"
>> approach (which is the state of the art right now) makes ecosystem of the
>> language & libraries more fragile and more fragmented than it might be.
>>
>> Thanks,
>>
>> On Friday, October 26, 2018 at 10:42:13 PM UTC+3, Sean Corfield wrote:
>>>
>>> I would likely only spec the status 200 OK responses. We use 400-series
>>> status values when we send back an error. You might consider that to be the
>>> “exception” of the HTTP world 😊
>>>
>>>
>>>
>>> We actually do have a documented format for 400-series responses but
>>> pretty much any part can be omitted so callers might occasionally not be
>>> able to ascertain a reason beyond “it failed”…
>>>
>>>
>>>
>>> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
>>> An Architect's View -- http://corfield.org/
>>>
>>> "If you're not annoying somebody, you're not really alive."
>>> -- Margaret Atwood
>>>
>>>
>>> ------------------------------
>>> *From:* clo...@googlegroups.com <clo...@googlegroups.com> on behalf of
>>> Didier <did...@gmail.com>
>>> *Sent:* Friday, October 26, 2018 11:35:20 AM
>>> *To:* Clojure
>>> *Subject:* RE: An Error spec?
>>>
>>> Sean, if you were to Spec your API responses, what would you do for your
>>> error response?
>>>
>>> This is my issue. I operate in a distributed environment. If I produce a
>>> set of data, but one field failed to compute properly, maybe a downstream
>>> system was down, maybe some information I was given to compute was
>>> corrupted, or missing, etc. And say this producing service has no user
>>> facing component, failing it is not logical. So I need to publish the
>>> partial result, and the error field should indicate an error. In my case it
>>> publishes a document entry in a nosql datastore, and events about it.
>>>
>>> Now, some other system will eventually consume that document, to display
>>> it to the user. When it does, it must appropriately handle the fact that
>>> some fields were in error.
>>>
>>> My documents are fully specced. So that consuming services can easily
>>> know their shapes and structure, so they can be sure to support them fully.
>>>
>>> In such scenario, exceptions aren't useful, but only because Java
>>> exceptions are crap at serialization. So I need to do the same thing you
>>> are, marshal my exception into an error and serialize that into my
>>> document. Then I spec the field appropriately.
>>>
>>> Now, I feel a lot of people using Spec would have such a use case, as
>>> its a logical tool to model data at your boundaries, and so I felt it might
>>> make sense to offer a spec macro for it.
>>>
>>> --
>>> 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/d/optout.
>>>
>> --
>> 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/d/optout.
>>
> --
> 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/d/optout.
>

-- 
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/d/optout.

Reply via email to