DI bez frameworka z klasami z ograniczoną widocznością

0

Wszyscy używamy na co dzień różnych frameworków i często nawet nie zastanawiamy się jak one funkcjonują. Pomyślałem sobie że napiszę jakąś prostą aplikację bez tej całej magicznej otoczki frameworka i zrobię to w czystej Javie (język w tym przypadku nie ma znaczenia) po czym okazało się że pewne rzeczy są niemożliwe do wykonania.
Weźmy taki przykład. Mamy 2 klasy. Jedna z nich jest Serwisem (albo fasadą - czymś co stanowi pewnego rodzaju API dla naszego modułu/pakietu lub po prostu szeregu funkcjonalności) i udostępnia prostą operację - powiedzmy rejestrację użytkownika. Dodatkowo ten serwis korzysta z innej klasy np. DAO (albo jakieś inne Repository które zapisuje tych użytkowników w bazie/na liście/do pliku) i ta klasa chcielibyśmy aby była prywatna dla modułu/pakietu ponieważ chcemy aby operacje zapisu były wykonywane zawsze przez Serwis a nie z jego pominięciem (bo np. w serwisie może być też dodatkowo walidacja). W jaki sposób zrobić teraz wstrzykiwanie zależności tego DAO do Serwisu np. przez konstruktor bez frameworka? To w ogóle możliwe?
Jeśli jedna z klas jest publiczna a druga podlega pewnym ograniczeniom to nie jesteśmy wstanie utworzyć instancji tej pierwszej w dowolnym miejscu naszej aplikacji. Korzystając z frameworka często mamy taką możliwość. Pytanie więc jak do tego podejść i jak rozwiązać taki problem?

3

Krótko - potrzebn jest trzecia klasa - taki config modułu gdzie decydujesz co wystawiasz. Fabryką / provider / builder serwisu.

Tworzy Ci domyślną implementację, a jednoczesnie umożliwa wstrzelenie innych zależności w testach:

stary przykład:
https://github.com/javaFunAgain/ratpong/blob/master/src/main/java/pl/setblack/pongi/scores/ScoresModule.java

W tym projekcie nie chowam specjalnie implementacj - ale dzieki tego typu klasom móglbym. (Bardzo zresztą podobne do @Configuration w Springu )...

1

Niech Twój prywatny moduł udostępni stworzony obiekt lub lepiej fabrykę czy buildera. A w środku może być użyty DI albo fabryka, jak chcesz.
Korzystając z DI, przynajmniej w świecie .net, jeśli mam widoczność klasy ustawioną na "moduł", to nie użyje jej i nie podepnę w ... nazwijmy to module głównym. Korzystając z frameworków da się to obejść, ale robiąc konfigurację per moduł, a nie ngle uwidaczniać daną klasę w głónym module.

Także tutaj to nie problem (chyba że Java ma inaczej) z użyciem frameworka lub nie, ale z granicami między modułami jakie wyznaczasz.

1

Potrzebny Ci interfejs dla serwisu, interfejs będzie publiczny dla modułu, a implementacje serwisu i repository/dao prywatne plus dodatkowa jakaś fabryka w której to składanie nastąpi;

public interface IService
{
    void Foo();
}

internal class Service : IService
{
    private readonly Repository repository;


    public Service(Repository repository)
    {
        this.repository = repository;
    }

    public void Foo()
    {
        repository.Foo();
    }
}

internal class Repository
{
    public void Foo()
    {

    }
}

public class Factory
{
    public IService CreateService()
    {
        // composition root
        return new Service(new Repository());
    }
}

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