Czy uzywajac kontenera nie powinno sie nigdzie dawac new?

0

Czy jak w projekcie uzyty jest ninject lub autofac to nigdzie nie powinno sie uzywac new?

Trafiłem w jakimś kursie na taką linijkę (pomimo używania kontenera):

var client = new HttpClient();
clien.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
5

Kontener powinien być wykorzystywany do pobierania zależności (serwisów) - wynika to stąd, że w Twoich serwisach powinieneś opierać się na interfejsach, których konkretne implementacje powinien znać / łączyć dopiero kontener (na tym polega cała idea DI).

Za pomocą new powinieneś tworzyć DTO oraz inne tego typu obiekty, których wybór / zachowanie / itd. nie różni się w runtime'ie (takie obiekty nie są formalnie w ogóle zależnościami Twojego serwisu).

Opierając się na Twoim przykładzie: najprawdopodobniej HttpClient powinieneś pobierać z kontenera, podczas gdy MediaTypeWithQualityHeaderValue zostało prawidłowo utworzone za pomocą new.

3

To zalezy gdzie tworzy sie nowy obiekt- kontekst jest wszystkim. Ciezko odpowiedziec bez tego. Ogolnie tam gdzie sie da najlepiej stosowac Dependency Injection i wykorzystywac kontener do tworzenia obiektow. Natomiast w tym konkretnym przypadku ktory podales z HttpClient to nie powinno sie tworzyc nowej instacji za kazdy razem kiedy chcemy wykonac request pod ten sam adres.

HttpClient is intended to be instantiated once and reused throughout the life of an application. The following conditions can result in SocketException errors:
Creating a new HttpClient instance per request.
Server under heavy load.
Creating a new HttpClient instance per request can exhaust the available sockets.

Zrodlo

0

@Aventus: czyli np wydzielic HttpClient do osobnej klasy i zrobic go jako statycznego np:

public static class ClientHelper
{
  public static HttpClient Client {get; private set;}
  public static void Init()
  {
    Client = new HttpClient();
    Clien.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
  }
}
2

Jeśli masz możliwość wstrzykiwać zależności to ja bym stworzył dedykowaną klasę (np. MyRequestService) dla konkretnego requestu. Ta klasa wiedziała by po jakim kluczu wyciągnąć potrzebny URL np. z konfiguracji. Następnie wyabstrahował bym to do interfejsu (w celu podmienienia tego w testach) i zarejestrował tą implementację wraz z interfejsem w kontenerze, jako singleton. Wtedy kontener zajmie się prawidłowym zarządzaniem "życia" tego obiektu.

3

Wtrącę swoje dwa grosze, chociaż lekko dywaguję :]

Kontener powinien być wykorzystywany do pobierania zależności (serwisów) - wynika to stąd, że w Twoich serwisach powinieneś opierać się na interfejsach, których konkretne implementacje powinien znać / łączyć dopiero kontener (na tym polega cała idea DI).
Za pomocą new powinieneś tworzyć DTO oraz inne tego typu obiekty, których wybór / zachowanie / itd. nie różni się w runtime'ie (takie obiekty nie są formalnie w ogóle zależnościami Twojego serwisu).

Wstrzykiwanie zależności można łączyć z polimorfizmem, ale samo w sobie wstrzykiwanie nie ma z polimorfizmem nic wspólnego.

In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client's state.[1] Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
The intent behind dependency injection is to decouple objects to the extent that no client code has to be changed simply because an object it depends on needs to be changed to a different one. This permits following the Open / Closed principle.

changed to a different one możne oznaczać, że np raz wstrzykujemy stringa 'kasia', a raz 'basia', albo raz wstrzykujemy HttpClienta łączącego się do klastra A, a raz do klastra B.

Robienie interfejsów z jedną produkcyjną implementacją to już w ogóle moim zdaniem bezsens (YAGNI), ale mam przeczucie, że w C# jest dość popularne.

0

Przykład z mojego podwórka:
Stwórz sobie fabrykę abstrakcyjną Clienta Http.
I ją możesz sobie wstrzykiwać, a nie będzie Cię kłuło w oczy, że masz gdzieś 'new'

0

@Wibowit:

Robienie interfejsów z jedną produkcyjną implementacją to już w ogóle moim zdaniem bezsens (YAGNI), ale mam przeczucie, że w C# jest dość popularne.

Ale to chyba nie było odniesienie do tego co pisałem?

1

Najlepiej to by było zacząć od podstaw i opowiedzieć na pytanie po co w ogóle wstrzykujemy? co chcemy przez to osiągnąć? przecież nie robimy tego bo tak :D

  • wstrzykujemy po to by móc podmienić implementację wstrzykiwanego typu bez modyfikacji klasy do której wstrzykujemy
  • a potrzebujemy podmieniać implementację przede wszystkim na potrzeby testów by móc testować daną klasę

Więc jak piszemy test dla danej klasy to od razu mamy odpowiedź czy potrzebujemy by dana zależność była wstrzykiwana czy nie.
A jak nie piszemy testu, to zastanówmy się jakbyśmy testowali daną klasę, to czy byśmy chcieli testować w izolacji od danej zależności czy nie, jeśli w izolacji to mamy kandydata na wstrzyknięcie, jeśli nie to możemy użyć "new".

0

Robienie interfejsów z jedną produkcyjną implementacją to już w ogóle moim zdaniem bezsens (YAGNI), ale mam przeczucie, że w C# jest dość popularne.

bo to nie java i inaczej wszystko trzeba by było oznaczyć jako virtual żeby to zamockować do unit testów, albo używać narzędzi które mogą co prawda pozwalać na zmianę implementacji nawet statycznych klas, ale operują na ILCode bezpośrednio, poniżej poziomu języka i trzeba zaufać jakiejś magii co jest czasem nieintuicyjne; łatwo też gdzieś zgubić konfigurację i dopuścić faktyczną implementację do testów, potem nagle po kilku miesiącach ktoś sprawdza czemu testy się wolno wykonują i okazuje się że lecą zapytania do rzeczywistej bazy danych albo dysku

też nie po to domyślnie metody i własności nie są wirtualne żeby je spowalniać do poziomu javy, a posiadanie interfejsu ma zazwyczaj swoje korzyści w przyszłości kiedy nagle chcemy część kodu wydzielić do biblioteki i nagle potrzebujemy drugiej implementacji - poza tym to dosłownie dwa kliknięcia - extract interface -> ok; można trzymać na początku w tym samym pliku

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0