Hacker News new | ask | show | jobs
by rorrr2 4703 days ago
Holy shit that function adapters example is convoluted. I'd say fewer than 5% of my programmer coworkers would figure out what's going on.

    func init() {
        http.HandleFunc("/", errorHandler(betterHandler))
    }

    func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            err := f(w, r)
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                log.Printf("handling %q: %v", r.RequestURI, err)
            }
        }
    }

    func betterHandler(w http.ResponseWriter, r *http.Request) error {
        if err := doThis(); err != nil {
            return fmt.Errorf("doing this: %v", err)
        }

        if err := doThat(); err != nil {
            return fmt.Errorf("doing that: %v", err)
        }
        return nil
    }
2 comments

Less than 5% of your coworkers understand decorators? I don't want to sound snooty but this is a pretty trivial application of higher order functions.
I have to agree; it's basic stuff even for a Python weenie like me.
It's basic stuff because you're a Python weenie; I don't see much use or discussion of decorators outside the Python world.
For what it's worth, this is also a very common pattern in ruby, using blocks:

  def with_error_handler
    if error = yield
      puts "error: #{error}"
    end
  end

  def do_things
    error = do_this
    return "error doing this: #{error}" if error
    error = do_that
    return "error doing that: #{error}" if error
    nil
  end

  with_error_handler do
    do_things
  end
Having said that, I did need to read the Go version more than once to grok it. I theoretically like Go's syntax for defining functions that take functions, but in practice I find it quite hard to scan, especially if there are more parameters on top of the function, or the passed function has multiple returns, or (god forbid!) it takes a function itself - it can all become quite a lot of bookkeeping.
They might not be called decorators, but they're also used in JavaScript and other languages with higher-order functions.
Decorators are a special Python syntax for this use, the more general term for what is going on is "higher-order functions".

Which are pretty important, and not specific to python.

yes, of course, but the discussion I replied to was talking about this specific idiom, this application of higher order functions, and not about the use of higher order functions generally.
I guess I work a lot with average developers. Not every corp is Google.
Since you're a developer let's assume it's just that your estimate is way off :) Multiply it by 3 and pad it with an extra 10% or so.
It's important to compare with the previous slide, to see the problem this is trying to solve. It'd be really easy to do a lot of

  if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
  }
all over the place, as the error return type isn't part of the standard Handler signature.

The decorator approach lets you return errors from your handlers, and then have your actual error handling centralized; you may want to send an e-mail to the ops team, send it to a third party exception management web service, etc.