Freezing the hash is beneficial at this point because it saves repeated expensive
computation if that hash is to be used later in performance-sensitive situations, such as
when serving as a cache key or similar.
This compares the memory cost of inheritance from the following superclasses:
- dry-configurable using two top-level settings
- dry-configurable using the same two settings, just nested one level deeper
- dry-core class attributes
- hanami-utils class attributes
- a plain old Ruby class, serving as a "control" for the benchmark
This major refactoring simplifies the code base by removing speacial treatment
for nested configs. I also added a dedicated class for settings, now it acts as
a factory for configs which kind of makes sense.
The `clone` methods were removed since they didn't really work. You can't clone
a frozen object and set instance variables after that since the new object is
frozen already.
Finally, dry-configurable now uses fewer instance variables, one for settings
and another one for config, this is it.
Using dry-struct was neat in some ways, in that a config object is effectively a typed struct, but it introduced unsatisfiable gem dependency cycles, e.g. that dry-struct required dry-types, and dry-types required dry-container, and dry-container was already using dry-configurable.
Secondly, with the dry-struct dependency bringing in those extra transitive depdencies, dry-configurable became less lightweight, and less palatable for others to use, especially given it has such a narrow, low-level focus.
We'll reintroduce type support via another approach with doesn't have these downsides.
This reverts the following commits:
- 1caa28e3b4
- abefc03b94
- 208e6a426f
- 600d60703d
- 2ecae98d89
- Using `Dry::Types['any']` to allow previous users to continue using
the previous api
- Show a warning message explaining that in the future the api will
change
- Add test to show still works with old api