I'm not sure whether `define_method` a few dozen times is a worse tradeoff here or not.

Conceivably, someone might do Weird Things(tm) and modify the backing Hash at runtime. This is I think the only edge case where `method_missing`/`respond_to?` excels.

Everything else can be done the same regardless of `define_method` or `method_missing`/`respond_to?`.

If you want to handle exceptions here, I think perhaps it's best not to subclass from Hash at that point, and rather just use the Hash as an internal data structure like so:

``` ruby
module Dotenv
  class InvalidConfigValue < StandardError; end

  class Configuration
    def initialize(env)
      @env = env || {}
    end

    def method_missing(meth, *args, &blk)
      key = meth.to_s.upcase

      if meth.to_s =~ /\?z/
        @env.has_key? key
      else
        @env.fetch(key)
      end
    rescue IndexError
      raise InvalidConfigValue,
        "Undefined environment variable `ENV['#{key}']`"
    end

    def respond_to?(meth, include_private = false)
      key = meth.to_s.upcase

      if @env.has_key? key.gsub(/\?\z/, "")
        true
      else
        super
      end
    end
  end
end
```