(no title)
feca | 12 years ago
For example, compare the proposed solution:
MegaLotto.configure do |config|
config.drawing_count = 10
end
MegaLotto::Drawing.new.draw
With the alternative: MegaLotto::Drawing.new(10).draw
If you want to make it extensible, you can use keyword arguments: MegaLotto::Drawing.new(size: 10).draw
The interface and the implementation are simpler, but also the performance is better because there are less method calls. If you look at the code of both implementations, you will find the simpler one easier to understand. As a side effect, you will also get simpler stack traces if anything goes wrong.
route66|12 years ago
soveran|12 years ago
dennyabraham|12 years ago
danso|12 years ago
I do agree that the constructor should have the option of passing in a Hash, which is then passed directly to the Configuration option.
feca|12 years ago
If you have this in many different places:
You don't have the information of how many numbers you are getting back. That's not a big deal, but adds to the cognitive load (or requires some comments). Also, if you need to draw different numbers in several different places, you will have to change the configuration many times: And as soon as you do that, you may need to take multi-threading into account, because you are mutating the class.Extrapolating, it is like defining the size of an array:
If instead you configure Array.new to have a given size for all instantiations, you also lose locality and you may run into thread safety issues.In the case of MegaLotto::Drawing.new needing multiple configuration options, you can use keyword arguments. If you need too many arguments, maybe the abstraction is wrong. Even if you want to move forward with too many arguments, you can add getters/setters to the newly created instance:
But this is not optimal design given the elements we have.ballard|12 years ago
A setting maybe needed per app, per process, per thread, per class|module, per subclass|include/extended module, per instance or per method call. (Phew.) And that's probably only 90% of use-cases, not counting apps configured by something like a JSON api, ZooKeeper or Chef databags.
The trick is to isolate config from behavior out of code as much as possible, scala style. An obvious example is to use environment variables so apps can be reconfigured without touching code.