12

I explained last week in great detail to a new team member of a dev team (yeah hire or fire part 2) why it is an extremely bad idea to do proactive error handling somewhere down in the stack...

Example
Controller -> Business/Application Logic -> Infrastructure Layer

(shortened)

Now in the infrastructure layer we have a cache that caches an http rest call to another service.

One should not implement retry or some other proactive error handling down in the cache / infra stack, instead propagate the error to the upper layer(s) like application / business logic.
Let them decide what's the course of action, so ...
1) no error is swallowed
2) no unintended side effects like latency spikes / hickups due to retries or similar techniques happens
3) one can actually understand what the services do - behaviour should either be configured explicitly or passed down as a programmed choice from the upper layer... Not randomly implemented in some services.

The explanation was long and I thought ... Well let's call the recruit like the Gremlin he is... Gizmo got the message.

Today Gizmo presented a new solution.

The solution was to log and swallow all exceptions and just return null everywhere.

Yay... Gizmo. You won the Oscar for bad choices TM.

Thx for not asking whether that brain fart made any sense and wasting 5 days with implementing the worst of it all.

Comments
  • 7
    Oh God no. The good 'ol exception blackhole AKA catch all.

    Ffs, the whole fucking point of exceptions is handle them if you can *solve* them fully, otherwise, let them bubble up or do what you need *and rethrow*.

    I blame python and JavaScript for this, btw.
  • 1
    Yay for gremlin 😂
  • 1
    I think It's the metaphor of human roles in an organization for subsystems in a program. Every intern intuitively understands that people are expected to sort out their own issues. If you describe what "the job of" a component is, that naturally implies that the component should figure out how to manage any and all complications.

    The breakthrough for me personally was to only ever anthropomorphize software when it's in a caller position. The callee - even if it acts as a caller elsewhere - should behave like a good tool. Do a very simple thing, behave predictably, elevate failures.
  • 0
    @lorentz it’s easier to think of layers as people, totally agree
  • 0
    I find the cache doing network things a bit odd to be honest. Retry is something that can be a concern of the deep client as long as it can be configured. It can even be a wrapper around the client or completely outside the application (service mesh for example).
  • 1
    @hjk101 that's what point 3 in the rant was made for.

    Cache is doing network with a client, not the cache itself.

    The troublesome part is that in the loading cache function, that loads for a key an entry for the cache, Gizmo wrote more or less the following inside a lambda:

    for (retry=1; retry <= 3; retry++) {
    try {
    return client->fetch(...)
    } catch(Exception exc) {
    // noop
    }
    }
    return null;

    Which is on so many levels wrong xD
Add Comment