Hacker News new | ask | show | jobs
by barrkel 4385 days ago
Better libraries express their dependencies in a pluggable way, which makes them more testable as well as composable.

The top-level application is usually a composition of libraries.

So in practice, I'm sanguine about apparently transitive dependencies. I prefer when exceptions from one library's plugged-in dependency flow through unmolested, as I see the libraries as mostly a flat dependency of the larger application. If you pull in dependencies transitively without paying much attention to them, you're sowing seeds for trouble with versioning, security scope, risk of stale projects if they're open source, etc.

I think of this as a corollary of Spolsky's law of Leaky Abstractions. Passing through exceptions means not trying to fool anyone into thinking they can work with the high-level abstraction without understanding anything about what's going on underneath.

Ideally the standard library provides base classes that act as core categories for different kinds of exceptions - IO, programmer error, data format error, etc. - so that general code can be written after a fashion when necessary. But I think you're fooling yourself if you think that such general code can be written the majority of the time, much less all the time. What's underneath always leaks through, one way or another, and if you try to ignore the thing that's underneath, you'll end up with brittle inefficient code.

Where high-level wrapping exceptions are justified is where there is an obvious chokepoint in the design - where the interface between several layers is very narrow. But this typically is at the junction between a service and a client - e.g. a web front end and back end, or async job queuing service, etc. - something where there is a service loop and probably service-specific logging of original exceptions, anyway.

1 comments

> Passing through exceptions means not trying to fool anyone into thinking they can work with the high-level abstraction without understanding anything about what's going on underneath.

Except this is not what happens in reality, very few people see an internal exception type and go investigate the details.

Sure it's shitty practice, but it seems orthogonal to whether the internal exception types are exposed.

I'm not saying people should just ignore what is underneath, I just think that as a library developer, you significantly constrain what you can do without breaking API compat by exposing internal exceptions.

You could take a hard line stance and say that it should be a breaking change and people should go and re-evaluate the library after the change, etc, and then rewrite their code to deal with new exceptions. But in reality it just means that library will no longer get updated, and will effectively become stale for no good reason.