What Roger is talking about, is when an error is implementation-specific
and may change if the implementation changes.

For example, if you have a black box service that saves data, it might
write to the network or it might write to a filesystem, but where it saves
is an implementation detail.  Let's say in the current implementation,
Save() returns a FileNotFoundError if you haven't called Initialize()
first, then people may write code that handles a FileNotFoundError by
calling Initialize().... now if you change the implementation to write to
the network, so now if they haven't called Initialize(), you return a
NetworkNotFoundError in the same situation.... their code will break.   If
you had instead written your own error, or just masked the type of the
error to something generic, then they wouldn't have been able to write
their code that makes bad assumptions.

Note that this is the most simple case of the problem.  In reality, it can
be that some sub-sub-sub package was returning that specific error, and
your code had no idea, it just passed it on up unchanged.  This is where it
gets insidious, because *your* code didn't change.  Some dependency of a
dependency changed that you might not even realize you were calling.  And
now people using your code are broken.  If you masked all returned errors
except the ones you explicitly wanted to return, then this couldn't happen.






On Thu, May 29, 2014 at 3:00 PM, Jeroen Vermeulen <
jeroen.vermeu...@canonical.com> wrote:

> On 2014-05-29 09:50, roger peppe wrote:
>
>> On 29 May 2014 04:03, Tim Penhey <tim.pen...@canonical.com> wrote:
>>
>
>  Errors are worth treating specially here because they're
>> they pass up through multiple layers, so it's very easy to break
>> abstraction
>> boundaries by relying on specific error types. I believe it's very
>> important
>> to *think* about the possible errors that can be returned from a given
>> function, and not just throw up our hands and say "you guys 5 layers down,
>> why don't you just communicate *arbitrary stuff* to the guy 3 layers
>> above".
>>
>
> It may help to consider this as two problems.
>
>
> One: caller needs to know about a specific failure — e.g. because it's a
> failure to the callee but not to the caller.  Definitely part of the
> contract.  You either:
>
> (a) define a super-specific error (exception class, error code, etc.), or
>
> (b) document that standard error X means failure Y in this case, and the
> caller picks up the error as close as possible to its origin.
>
> With these errors you have to make sure that the information isn't diluted
> as it propagates, but usually you don't have to take it too far up the call
> chain.
>
>
> Two: a caller can deal better with some errors, given more detailed
> information.  You can help by attaching more information to the error
> (tags, taxonomy, properties) but only on a best-effort basis.  You accept
> that you don't know exactly which errors can come out of the code further
> down.
>
> For example, if you're writing code which speaks to another program over
> the network, you may want to know: is this connection still usable?  Do I
> know what happened to the operation I requested?  Were we able to connect
> in the first place?  Am I doing something that shouldn't ever work, such as
> mis-spell a command?
>
> With these errors you act on the best information you have, but you can
> always just fail.
>
>
> Jeroen
>
>
> --
> Juju-dev mailing list
> Juju-dev@lists.ubuntu.com
> Modify settings or unsubscribe at: https://lists.ubuntu.com/
> mailman/listinfo/juju-dev
>
-- 
Juju-dev mailing list
Juju-dev@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/juju-dev

Reply via email to