Czy użycie DI / IoC powinno usunąć wszystkie wystąpienia słowa kluczowego „new”?

21

Czy użycie Wstrzykiwania zależności i kontenera Odwrócenie kontroli powinno usunąć wszystkie wystąpienia newsłowa kluczowego „ ” z kodu?

Innymi słowy, czy każdy obiekt / zależność, bez względu na to, jak proste lub krótkotrwałe, powinien być „zarejestrowany” w kontenerze IoC i wprowadzony do metody / klasy, która musi ich użyć?

Jeśli nie, gdzie narysujesz linię, między którą zależności / obiekty zostaną zarejestrowane w kontenerze IoC, a tym, co zostanie utworzone „w linii” jako konkretne odniesienie za pomocą newsłowa kluczowego?

CraigTP
źródło
Miałem tę samą myśl: „czy„ nowy ”to 4-literowe słowo?”
Michael Easter

Odpowiedzi:

27

Unikaj dogmatów. Rób to, co wydaje się właściwe.

Wolę używać „nowego” dla struktur danych, które nie zachowują się.

Jeśli klasa ma zachowanie, to sprawdzam zakres tego zachowania. Jeśli jest bezpaństwowiec i nie ma zależności, skłaniam się ku „nowemu”. Refaktoryzację zaczynam dopiero wtedy, gdy muszę dodać zależność do zasobów stanowych (takich jak baza danych lub plik) lub do innych klas z takimi zasobami.

Alex Beynenson
źródło
15
+1 za „unikaj dogmatów”. Zbyt łatwo wpaść w pułapkę po prostu podążania za ruchami bez zrozumienia, co się dzieje lub gdzie należy go właściwie użyć.
Wayne Molina,
@Alex Lubię to. Bardzo pragmatyczne podejście. Co ciekawe, miałem zamiar dodać trochę kodu do mojego pytania pokazującego newzależność mojego kodu, która spowodowała moje pytanie. Była to prosta klasa bez per se funkcjonalności i „zachowania”, jedynie proste właściwości.
CraigTP
11

W mojej książce rozróżniam zależności stabilne i niestabilne . Najważniejsze jest stosowanie DI z lotnymi zależnościami, ale często można osiągnąć nawet luźniejsze sprzężenie, również poprzez abstrakcję i wstrzykiwanie stabilnych zależności.

Należy pamiętać, że stosowanie DI nie powinno opierać się na pojemniku DI . W przypadku, gdy używana jest DI Poor Man , żadne newsłowa kluczowe nie są usuwane - są one po prostu przenoszone do Korzenia Kompozycji .

Niektórzy ludzie wolą DI biednego człowieka od kontenerów DI. Koszty utrzymania mogą być wyższe, ale w zamian zyskujesz bezpieczeństwo podczas kompilacji. Jak ostatnio słyszałem, jak Dan North powiedział: „ newjest nowy new” :)

Rozumie się przez to po prostu, że zamiast implementować Składnik główny z kontenerem DI, zawierałby on całą masę zagnieżdżonych newinstrukcji.

Mark Seemann
źródło
Mark, aby rozwinąć nieco mój komentarz na Twitterze , Programiści to właściwe miejsce na koncepcyjne, tablicowe pytania, które nie dotyczą konkretnego błędu w implementacji.
Adam Lear
3
Przepełnienie stosu zawiera ponad 2000 pytań w tagu wstrzykiwania zależności i wiele z nich jest podobnych do tego. Programiści mają 23 pytania w tym samym tagu. Na podstawie tych liczb, gdzie deweloper powinien mieć największą szansę na uzyskanie odpowiedzi na takie pytanie?
Mark Seemann
1
Wiele z tych pytań całkowicie poprzedza Programistów. Ta strona została stworzona, aby usunąć koncepcyjne pytania z SO i dać im dedykowany dom. I wciąż się rozwijamy. To praca w toku, ale idealnie migrowane byłyby tu pytania, które nie wiążą się z konkretnymi problemami z implementacją. Tymczasem robimy, co możemy.
Adam Lear
3

„nowy” nie jest niedozwolonym słowem kluczowym. Moje osobiste zasady:

Wszystkie „usługi” (nazywam usługę klasą zaprojektowaną w celu zapewnienia jednej lub więcej metod związanych z jedną i tylko jedną rzeczą, na przykład: dostęp do bazy danych, pobieranie / aktualizowanie danych związanych z daną domeną) są zarejestrowane w kontenerze MKOl. Żadna klasa nie powinna podejmować decyzji o tym, jak uzyskać wdrożenie danej usługi, z której musi skorzystać. Dlatego za każdym razem, gdy potrzebujesz skorzystać z istniejącej usługi, powinieneś skonfigurować swoją klasę i kontener MKOl, aby zapewnić Ci ją. Wyobraź sobie, że nie wiesz, jak działa twoja implementacja, może to być usługa internetowa, nie obchodzi cię to.

Wszystkie fasole lub modele mają być tworzone przy użyciu słowa kluczowego „new” lub fabryki zarejestrowanej w MKOl, gdy potrzebuję ich do włączenia niektórych domyślnych właściwości. Istnieje również szczególny przypadek klas użyteczności zawierających tylko metody statyczne (na przykład: matematyczna usługa użyteczności). Jeśli są one całkowicie samodzielne i nie potrzebują żadnego połączenia z bazą danych ani innej usługi zarejestrowanej przez MKOl, zostawiam je poza MKOl i należy je wywoływać statycznie. Jeśli jednak jedna taka klasa musi korzystać z istniejącej usługi zarejestrowanej w MKOl, zmieniam ją na klasę singleton i rejestruję w MKOl.

Jalayn
źródło
2

Chciałbym tylko dodać do istniejących odpowiedzi, które zostały wychowane, newjest całkowicie w porządku, aby tworzyć obiekty, które są obiektami o czystej wartości (tj. Mają tylko właściwości / getters / setters). Zobacz blog testowy Google, aby uzyskać więcej szczegółów.

Jacek
źródło
+1 za link. Punkt 9 w tym blogu odpowiada na pytanie i zapewnia pragmatyczne rozróżnienie między tym, co powinno, a czego nie powinno być new
wydane
1

Oczywiście zależy od używanego języka. Jeśli twój język zmusza cię do używania obiektów do reprezentowania zarówno rzeczywistego obiektu, jak i rekordów (obiekt wartości, struktury), odpowiedź najprawdopodobniej nie.

Mówiąc wyłącznie o „prawdziwych” obiektach, nie ma nic złego w jawnym tworzeniu instancji. Musisz jednak pamiętać, że wszystkie klasy powinny przestrzegać zasady jednej odpowiedzialności. Klasa nie powinna być odpowiedzialna za wybór implementatora usługi, na której polega. Są jednak klasy, które ponoszą tak wielką odpowiedzialność, tj. Zapewnienie implementatorów niektórych usług. IoC może być taką klasą. W rzeczywistości każdy rodzaj fabryki jest taką klasą.

Podsumowując: tylko takie klasy powinny bezpośrednio tworzyć instancję obiektów, za co należy wybrać klasy, które mają zostać utworzone.
Te kryteria mogą być pomocne: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator

back2dos
źródło
1

Jedno słowo: Nie.

Więcej słów: wstrzyknięcie zależności jest dokładnie tym. Jest to środek, za pomocą którego wprowadzasz zasoby, od których zależy inny obiekt, ale nie powinny znać skomplikowanych szczegółów z innego źródła. Używanie DI nie oznacza, że ​​NIC w twoim programie nie powinno wiedzieć, jak utworzyć dowolny inny obiekt; w rzeczywistości uważam, że dla nietrywialnego programu bardzo niemożliwe jest całkowite uniknięcie „nowego” słowa kluczowego (lub alternatyw opartych na odbiciu). Jednak DI oznacza, że ​​obiekty, które nie powinny MIEĆ wiedzieć, jak tworzyć złożone obiekty wymagające wielu zależności, które ściśle połączą ten obiekt z drugim, nie powinny mieć całej tej ściśle powiązanej wiedzy.

Badałbym dwie główne teorie projektowania oprogramowania O / O, GRASP i SOLID. GRASP powie ci, abyś przestudiował cel obiektu i zapytał siebie: „Czy ten obiekt powinien być odpowiedzialny za tworzenie nowych obiektów tego innego rodzaju? Czy to część„ opisu zadania ”tego obiektu?” SOLID idzie o krok dalej: „S” oznacza „zasadę pojedynczej odpowiedzialności”, która jednoznacznie stwierdza, że ​​obiekt powinien mieć jedno zadanie i powinien być jedynym obiektem w programie, który wykonuje to konkretne zadanie.

Dlatego GRASP ogólnie zachęca do przejrzenia istniejących klas, dla których tworzenie tych nowych obiektów, i znalezienia takiej, dla której zadanie tworzenia tego obiektu pasuje do tego, co obiekt już robi, przy zachowaniu pożądanego poziomu „spójności”. SOLID powie ci, że spójność jest kluczowa; zadanie tworzenia tych obiektów powinno zostać powierzone jakiejś fabryce, która powinna zostać wprowadzona do twojej klasy. Myślę, że wraz ze wzrostem złożoności twojego programu, przestrzeganie którejkolwiek z tych metod, z chęcią refaktoryzacji, będzie skutkować bardzo podobnymi architekturami.

KeithS
źródło