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.