-
-
Save holsee/5336517 to your computer and use it in GitHub Desktop.
class Nails | |
def to_s | |
"nails" | |
end | |
end | |
class Glue | |
def to_s | |
"glue" | |
end | |
end | |
class PowerSaw | |
def initialize(power_source) | |
@power_source = power_source | |
end | |
def to_s | |
"#{@power_source} power saw" | |
end | |
end | |
class HandSaw | |
def to_s | |
"hand saw" | |
end | |
end | |
class Electricity | |
def to_s | |
"electrical" | |
end | |
end | |
class Carpenter | |
def build_something | |
puts "Building something in wood with #{fixings} and #{tool}" | |
end | |
end | |
module ManualToolsModule | |
def tool | |
HandSaw.new | |
end | |
def fixings | |
Glue.new | |
end | |
end | |
module PowerToolsModule | |
def power_source | |
Electricity.new | |
end | |
def tool | |
PowerSaw.new power_source | |
end | |
def fixings | |
Nails.new | |
end | |
end | |
# reopening the class to mix the module in | |
class Carpenter | |
include ManualToolsModule | |
end | |
# or (alt registration which replaces first registration) | |
class Carpenter | |
include PowerToolsModule | |
end | |
Carpenter.new.build_something | |
I totally get what you are saying here. I guess it's a mindset thing to some degree. Are classes loosely coupled in a dynamic language by default because it's easier to change the behaviour compared to a static language.
I wonder if IoC is more popular in status languages because it is the only way to get nice loosely coupled classes whereas in dynamic languages there are other options that are easy and so people take that approach even if these methods are not strictly IoC/loosely coupled as seen by a purest.
Just a word on testability. For me, being able to mock/test easily is not the goal of IoC but a nice side affect of doing it. Obviously in ruby we can mock anything using the language features but my feeling is that we do this because it's the easy way rather than the "right" way.
Andy I'm relatively new to ruby, so these are not words of a seasoned rubyist.
I think everything is loosely coupled by the dynamic nature and the new instance creation is nowhere near the consumer. The module itself in this example could be refined, each method defined within simple acting like a factory method that you might see in the IoC container. The part that feels dirty is the monkey patching at a class level, where it would be nice to do this upon the instantiation on a per instance basis.
I still feel there is some value to be had from an IOC container and am not convinced otherwise myself. I'd be eager to work with you on this experiment as I too find it interesting, to see what the most idiomatic way would be to achieve your goals. Instance Lifetime management outside of the class is something I miss in ruby.
IoC + param injection is a pattern which really helps keep classes clean, tiny and single purposes, but 'ruby is like play dough' so by creating new instances outside of a container, favouring poor mans DI is no big deal as testing in isolation is totally possible by replacing a Class with a mock or stub version. This always bites you in the ass for testability in staticly typed languages. I think this is the major argument agains the need for a container.