Programowanie - dyskusje pozostałe

Dependency Injection: co, jak i dla kogo?

Założony przez nuno69 7 wpisów ostatni wpis 3 lata temu

#1

Generalnie Dependency Injection to skomplikowany termin dla czegos, z czego raczej kazdy z nas korzysta (juz tlumacze).
Na przyklad gdy mamy klase
internal class MyAPIClient {
private HTTPClient _client; // Wiem wiem, ktos sie zaraz przyteguje ze przeciez na HTTPClienta trzeba uwazac (to jest przyklad i nie robcie tego w domu)
// Dalsza czesc naszej kalsy
// konstruktor
public MyAPIClient(HttpClient client) {
// Konfiguracja HTTPClienta przekazanego przez uzytkownika
// Konfiguracja calej reszty
}
}
Tutaj mamy przyklad DI przez konstruktor (przekazujemy zaleznosc, w tym wypadku HTTPClient, w konstruktorze klasy). No i to jest proste i oczywiste, ale mamy tez kilka innych typow DI
- DI przez metode: tutaj tez jest dosyc latwo. Jezeli dana zaleznosc tyczy sie tylko jednej metody to nie ma przeciwwskazan zebysmy przekazali te zaleznosc do metody, na przyklad
bool MakeAPICall(string url, HTTPClient client) {
// konfiguracja klienta
// Wykonanie requesta
// zwrocenie kodu statusu
Jest tez DIprzez wlasciwosc. Wracajac do przykladu 1
internal clas MyAPIClient {
public HTTPClient client {get; set; }
// Cala reszta talatajstwa.
}
Wtedy HTTPClienta nie przekazujemy w konstrukterze ani w metodzie, tylko pozwalamy na dowolne manipulowanie nim z dowolnego miejsca. Moim zdaniem wyglada to paskudnie ale wiem, ze jest to jakos tam stosowane.
Kolejnym i ostatnim typem DI jaki chce teraz omowic (spoko, to nie poradnik tylko pytanie) jest ten AMbientContext, gdziepo prostu na chama nadpisujemy klase mockupem jezeli potrzebujemy wykonac test.
Na to wszystko dochodza jeszcze te wszystkie frameworki IOC, pokroju Needledla Rubiego czy Auto FAC dla C#.
Kiedy czego uzywac? Zapraszam do dyskusji
- "Intelligence and wisdom is like jam. The less you have, the harder you're trying to spread it arround." - French proverb

#2

O, ja też mam z tym problem xD czy przekazywać, kiedy przekazywać itd. Z chęcią zachęcę do wypowiedzenia się w temacie kogoś innego, kto już to rozgryzł.

#3

Ilu programistów, tyle opinii. Ja na przykład uważam, że jeśli przekazywać klasę, to tylko w konstruktorze, a w każdym innym przypadku powinno używać się lambdy. Ale to moja opinia i wiem, że wielu się z nią nie zgodzi. :)
#StandWithUkraine

Shoot for the Moon. Even if you miss, you'll land among the stars.

#4 Edytowano

Pamiętaj też, że C# jest językiem silnie typowanym, a np. Ruby już nie.
Więc dochodzi sporo walidacji.

class Calculus
def calculate(x) = 0
end

class SquareCalculus < Calculus
def calculate(x) = x**2
end

class HalfCalculus < Calculus
def calculate(x) = x/2.0
end

class MultipleCalculator
def initialize(calculator)
@calculator = calculator
raise(RuntimeError, "Debilu, to nie jest odpowiednia klasa") if !calculator.is_a?(Calculus)
end

def calculate(x, count)
count.times {x = @calculator.calculate(x)}
return x
end
end

Gdybyśmy wykorzystywali przekazywanie klasy przez metodę, za każdym razem musielibyśmy sprawdzać, czy invoker podaje nam klasę Calculus, czy jakiegoś stringa albo whatever innego.
#StandWithUkraine

Shoot for the Moon. Even if you miss, you'll land among the stars.

#5

Ja przez metode przekazuej tylko wtedy, gdy
1. Inicjalizacja obiektu jest kosztowna a istnieeje prawdopodobienstwo, ze program nigdy nie wykorzysta danej zaleznosci.
2. Zaleznosc jest specyficzna dladanej metody.
3. (C#) w pewnych przypadkach przekazanie przez metode jest jedyna mozliwoscia jezeli chcemy uniknac problemow z GC.
Ale skad taka popularnosc frameworkow o ktorych wspomnialem? Nie mowie o RUbym, bo tutaj dochodzi walidacja.
- "Intelligence and wisdom is like jam. The less you have, the harder you're trying to spread it arround." - French proverb

#6

A jakie są jeszcze inne sensowne sposoby niekoniecznej inicjalizacji gdy musimy skorzystać w śmietniku więcej niż w jednym miejscu z tej konkretnej klasy? :D

#7

Lazy initialization?
- "Intelligence and wisdom is like jam. The less you have, the harder you're trying to spread it arround." - French proverb