question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RFC: Improve Error Handling

See original GitHub issue

One of the main goals of Cerebral is to understand the “flow” of your application. Signals give us a nice high level view of our app logic, but often times error handling clutters and adds noise to our otherwise beautiful signals.

A key design goal for error handling should be, in my opinion, that you only need to explicitly handle errors where and when your program requires it. Otherwise, error handling actually detracts from the readability of your program, cluttering it with low level book keeping instead of expressing your intent (which is what Cerebral is all about).

The Problem

Take this (Cerebral 1) signal for example:

module.addSignals({
  mounted: [
    setupDeviceSettings,
    setAuthHeaders,
    fetchCurrentUser, {
      success: [
        copy('input:currentUser', 'state:currentUser'),
        copy('state:currentUser.current_account_id', 'state:navbar.newPost.account_id'),
        fetchPosts, {
          success: [
            copy('input:posts', 'state:posts'),
            when('flags.showCommentsButton'), {
              true: [
                fetchComments, {
                  success: [copy('input:comments', 'state:comments')],
                  error: [(e) => { console.log('comments error', JSON.stringify(e)); }]
                }
              ],
              false: [/*noop*/]
            }
          ],
          error: [(e) => { console.log('fetch posts error', JSON.stringify(e)); }]
        },
      ],
      error: [(e) => { console.log('fetchCurrentUser error', JSON.stringify(e)); }]
    }
  ]
})

This signal is really just about fetching some related resources from some APIs. We need to get the: currentUser, their posts and finally the comments for their posts. We can’t render the first view until we have that data.

Notice how repetitive the error handling is above and the “pyramid of doom” with indentation creeping to the right of the screen. In this case, the developer is forced to define the error path for each API call and provide an explicit error handling action. But, really, all we care about in this instance is: 1) did everything work? or 2) did something prevent us from getting this data?

The Solution

As we talked about in the hangout, I’d like to start a discussion around a better error handling solution for Cerebral. What if we could re-write the signal above like (please forgive this hodgepodge of Cerebral 1 and 2 syntax 😛) :

module.addSignals({
  mounted: sequence([
    setupDeviceSettings,
    setAuthHeaders,
    fetchCurrentUser, {
      success: [
        copy('input:currentUser', 'state:currentUser'),
        copy('state:currentUser.current_account_id', 'state:navbar.newPost.account_id'),
        fetchPosts, {
          success: [
            copy('input:posts', 'state:posts'),
            when('flags.showCommentsButton'), {
              true: [
                fetchComments, {
                  success: [copy('input:comments', 'state:comments')]
                }
              ],
              false: [/*noop*/]
            }
          ]
        }
      ]
    }
  ], {
    error: [flash('Error fetching data')]
  })
})

The idea is to provide a named path at the top level that can be invoked if any of the nested paths throw an error. Conceptually, a nested error will “bubble up” to the top of the signal chain until it is handled. In the event that you want more specific error handling, you simply define error paths like in the first example. The key thing is that now you are not forced to repeat yourself with error handling when your application doesn’t require you to. Already, with just this one change, I think the logical flow is clearer for “the next developer”. You can more easily scan the signal without mentally removing the error paths.

It’s always a difficult balance between being low level + explicit vs concise/abstract. In this case, however, I think handling errors more concisely would benefit from a higher level API and convention.

Anyway, that’s all I have for now. Everyone please weigh in with ideas, excitement, or objections. 😄

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:70 (61 by maintainers)

github_iconTop GitHub Comments

3reactions
christianalfonicommented, Mar 21, 2017

hah, awesome… it worked on first try… implementation driven development 😄 Implement first, tes after!

2reactions
christianalfonicommented, Mar 21, 2017

Hehe, yeah, abort is implicit… like, by reading the code you never know which one can cause an abort to happen. That said, it cleans up so well for these types of scenarios 😃

Ah, man, just got very happy. The “merge execution” (client/server) logic is perfect for handling ABORT 😃 Cause it is generic. It basically is a signal that has an “executedBy” prop. Meaning that an abort can fire off a new function tree execution, only it attaches the “executedBy” prop. It will automatically get inlined on the exact action that caused it… do not have to do anything 😃 Only thing is identifying it is an ABORT execution and style it.

Woop woop 🎉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Revised Error Handling for BGP UPDATE Messages RFC 7606
Finally, it revises the error handling procedures for a number of existing attributes. This document updates error handling for RFCs 1997, 4271, 4360,...
Read more >
RFC [Discussion]: Improve unserialize() error handling
Hi. I've now written up an RFC as a follow-up for the "What type of. Exception to use for unserialize() failure?" thread [1]: ......
Read more >
2965-project-error-handling - The Rust RFC Book
This RFC establishes a new project group, under the libs team, to drive efforts to improve error handling in Rust. Motivation. The error...
Read more >
Error Handling in RFC | SAP Community
How errors can returnd in RFC? ... Error Handling in RFC. 687 Views ... You can define them in Exceptions & raise them...
Read more >
RFC: How to improve error handling and messages for users
Hi all,. the intention of this thread is to encourage everybody to commit work and thoughts they have on to improve the error...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found