Loop try catch

A simple cause of failure in software systems is a single problematic item in a set causing the entire set to fail.

Trivially, it looks like this:

for (const item of items) {
    processItem(item)
}

When something goes wrong in processItem() and throws an error, either the whole set fails to process, or all the subsequent items fail.

The trivial example has a trivial improvement:

for (const item of items) {
    try {
        processItem(item)
    } catch (err) {
        // Do something useful with the error.
    }
}

It might be desirable that the whole set fails if some items fail (like a circuit breaker), but often it’s better that the other items go through.

In that case, listing the failed items, logging them, reporting the error or falling back to some backup mechanism might be good things to do.

As with many common failures, it seems simple and obvious, but still seems to exist in many systems. It’s worth thinking through the implications of different failure scenarios and the most useful way to handle them.