Struktury wtrysku Dependency Injection w Ruby zostały uznane za niepotrzebne. Jamis Buck napisał o tym w zeszłym roku w swoim blogu na blogu LEGOs, Play-Doh, and Programming.Podstawienie implementacji języka wykonawczego z Ruby
Ogólnie przyjętą alternatywą wydaje się być użycie pewnego stopnia wtrysku konstruktora, ale po prostu dostarczanie wartości domyślnych.
class A
end
class B
def initialize(options={})
@client_impl = options[:client] || A
end
def new_client
@client_impl.new
end
end
Podejście to jest w porządku przez mnie, ale wydaje się, że brakuje jednej rzeczy od bardziej tradycyjnych konfiguracjach: sposób na zastąpienie implementacje w czasie wykonywania na podstawie jakiegoś zewnętrznego przełącznika.
Na przykład z Dependency Injection ram mogę zrobić coś takiego (pesudo-C#):
if (IsServerAvailable)
container.Register<IChatServer>(new CenteralizedChatServer());
else
container.Register<IChatServer>(new DistributedChatServer());
Ten przykład tylko rejestruje inną IChatServer
realizacji w zależności od tego, czy nasz serwer centeralized jest dostępna.
Ponieważ wciąż używamy konstruktora w Ruby, nie mamy programowej kontroli nad zależnościami, które są używane (chyba że sami określimy siebie). Przykłady, które podaje Jamis, wydają się dobrze dostosowane do tego, aby zajęcia były bardziej testowalne, ale wydaje się, że brakuje im możliwości zastępowania.
Moje pytanie brzmi: jak rozwiązać tę sytuację w Ruby? Jestem otwarty na wszelkie odpowiedzi, w tym "po prostu nie musisz tego robić". Chcę tylko poznać perspektywę Rubiego na te tematy.