Wpis z mikrobloga

Mam zagwozdkę co jest lepsze.
Załóżmy taki typowy scenariusz: mamy gdzieś w logice biznesowej ogólny typ do zapisu/odczytu danych np IDataStorage. Potrzebujemy użyć ten typ w jakimś konkretnym ficzerze. W związku z tym żeby odseparować ogólny mechanizm do obsługi danych i uprościć użycie tworzymy po stronie ficzera jakiś własny typ np IFeatureDataStorage który będzie wrapował IDataStorage i udostępniał metody bezpośrednio skrojone pod feature.
Ficzer posiada jakiś widok(i) oraz ViewModel albo Controller (w zależności od architektury UI'a). Ten ViewModel/Controller będzie używał IFeatureDataStorage.
I teraz opcje są dwie:
1. Opcja standardowa czyli ViewModel/Controller będzie zawierał IFeatureDataStorage (przekazany przez konstruktor). W takim wypadku będzie on sam sterował odpowiednim wywoływaniem IFeatureDataStorage.
2. ViewModel/Controller będzie implementował IFeatureDataStorage. Można powiedzieć że jest on po prostu drugą UI'ową implementacją storage. W takim wypadku coś nadrzędnego (np nadrzędny ViewModel albo Controller) będzie sterował obydwoma implementacjami IFeatureDataStorage czyli będzie w odpowiednich momentach odczytywał z jednego i zapisywał do drugiego i odwrotnie.

Czy jest jakieś preferowane rozwiązania z punktu widzenia dobrego OO?
Wydaje mi się że jeżeli są zapisywania i odczytywania danych na bieżąco, np przy każdej zmianie na UI'u a nie tylko na 'wejściu' i 'wyjściu', to pierwsza opcja jest preferowana bo tylko dany ViewModel/Controller wie kiedy coś się zmieniło.
W przeciwnym wypadku gdy odczytujemy coś na wejściu i zapisujemy na wyjściu to druga opcja jest chyba lepsza ale tego nie jestem pewny.

#pytanie #programowanie #programista15k
  • 14
  • Odpowiedz
  • Otrzymuj powiadomienia
    o nowych komentarzach

@Saly:

zwał jak zwał

no nie bo dziedziczenie to nie implemetnacja interfejsu, to są dwie powiedziałbym przeciwstawne koncepcje, jedna jest zalecana interfejsy) w dobrym OO a druga banowana (dziedziczenie konkretnych typów).

Cytowany tekst...ten dylemat sprowadza się do implementowania logiki w klasie vs ekstracja jej do jakiejś
  • Odpowiedz
@LeopoldStuff: poczytaj trochę o DDD, polecam książkę Erica Evansa. Gdzie wyczytałeś, że dziedziczenie konkretnych typów jest jest opcją banowaną? xD Przecież implementowanie interfejsu i dziedziczenie ma zupełnie dwa różne cele.
  • Odpowiedz
@LeopoldStuff: ogólnie klasy powinny mieć wąską specjalizację (literka S z SOLID) czyli kontroler powinien tylko służyć do kontrolowania przepływu obsługi requestu użytkownika, a nie też posiadać logikę związaną z rozmową z bazą danych, a druga sprawa to kod służący do komunikacji z bazą jest praktycznie niereużywalny jeśli go wsadzisz do kontrolera, bo kontroler jest w najwyższej warstwie projektu
  • Odpowiedz
@Kris10: > Przecież implementowanie interfejsu i dziedziczenie ma zupełnie dwa różne cele
Całkowicie się z tym zagadzam, o tym własnie pisałem że to są dwie różne sprawy. A to że dziedziczenie konkretnych implementacji jest zazwyczaj złe (nie zawawsze ale przeważnie) to jest znany fakt i wszędzie gdzie materiały traktują o prawdziwym OOP tam dziedziczenie jest przedstawiana w niekorzystnym świetle bo prowadzi do niekorzystnych powiązań między typami. Zazwyczaj można wyczytać że zamiast dziedziczenia powinniśmy stosować kompozycje ale tak naprawdę to prawdziwie OO alternatywą dla dziedziczenia jest dekorator.

kontroler powinien tylko służyć do kontrolowania przepływu obsługi requestu użytkownika, a nie też posiadać logikę związaną z rozmową z bazą danych

kontroler nie ma tej logiki napisałem że specjalnie na porzeby tego ficzera został stworzony wrapujący IFeatureDataStorage który udostępnia metody i zwraca dane zrozumiałem dla tego ficzera a co tam pod spodem jest to jest kompletnie niewidziane przez kontroler. IFeatureDataStorage to jest taki model wyłącznie skrojony pod ten ficzer i działa jak wartwa rozdzielająca faktyczny storage od ficzera. IFeatureDataStorage zwraca i przyjmuje dane znane ficzerowi.
Wieć podsumowując kontroler nie zna tej logiki, pytanie tylko czy powinien ten skrojony pod siebie model zawierać w sobie czy implementować
  • Odpowiedz
@LeopoldStuff: w swoich wywodach miałem przed oczami interfejsy z javy, które mogą mieć implementacje, i przez co można po nich "dziedziczyć" w celu dodania jakiejś funkcjonalności do klasy pochodnej/implementacyjnej

nie bardzo rozumiem co tu masz na myśli jedno i drugie wymaga odpowiednich implementacji po stronie ViewModelu/Kontrolera. Pierwsza musi zebrać wszsytkie dane i wywołać odpowiednio IFeatureDataStorage a druga musi też zebrać wszystkie dane tyle że udostępnić je w postaci zaimplementowanej metody. W pierwszym wypadku tworzymy zależność bo przekazujemy do środka IFeatureDataStorage. A w drugim mamy jedną zależność mniej bo nie przechowujemy IFeatureDataStorage, ale za to sam ViewModel/Kontroler musi zaimplemnetować IFeatureDataStorage


@LeopoldStuff: tak, błąd z mojej strony. Pomyliły mi się przypadki: nie chcesz dodać logiki do twojej klasy, tylko chcesz, żeby twoja klasa
  • Odpowiedz
@Saly:

Co jak np. do twojego interfejsu dojdzie metoda, której nie chcesz używać w danym kontrolerze? Pusta implementacja?


tak, to już jest konkretny argument przeciw rozwiązaniu 2
  • Odpowiedz