Functions should do one thing. They should do it well. They should do it only.

The function sum() does one thing – summing up a numeric vector.

base::sum(1, 2, 3)
#> [1] 6

If the caller passes sum() non-numeric values then the function fails.

base::sum(1, "2", 3)
#> [1] "Error in base::sum(1, \"2\", 3) : invalid 'type' (character) of argument"

An example of a Single-Responsibility Principle (SRP) violation, happens when a programmer adds the responsibility of error handling to the sum function:

# Decorating `sum` with failproof mechanism:
# 1. Return NA when sum fails
# 2. Extract the result
sum <- purrr::safely(base::sum, otherwise = NA_real_)
sum <- purrr::compose(sum, ~ purrr::pluck(.x, "result"), .dir = "forward") 

With the decorated sum() function, the behaviour for non-numeric values alters

sum(1, 2, 3)
#> [1] 6
sum(1, "2", 3)
#> [1] NA

The decorated sum() function violates Single-Responsibility Principle. Nevertheless, its failproof quality is desirable in production systems. This is because:

  1. Production system should be failure safe; and
  2. The decorated function requires no changes in the codebase. Without it, a programmer would have encapsulated sum() instances with tryCatch statement such as this:
tryCatch(sum(x), error = function(e) return(NA_real_))