W naszej aplikacji Rails dodajemy powiadomienia. Niektóre z nich to blocking
: Zatrzymują postęp dodawanego zasobu, ponieważ brakuje niektórych informacji o tym zasobie.
Inne powiadomienia są prostymi powiadomieniami i zawierają jedynie informacje.
Dzisiaj rozmawiałem z innym programistą w naszym zespole. Utworzyłem następującą strukturę dziedziczenia:
Wolałby jednak, abym po prostu dodał blocking
jako metodę zwracającą wartość logiczną w każdym powiadomieniu i określił listę podklas, które blokują wewnątrz nadrzędnej klasy Powiadomienia.
Różnica między tymi podejściami nie jest bardzo duża; w moim podejściu nie trzeba określać tej listy, utrzymując klasę root czystszą. Z drugiej strony, specjalna logika, która dzieje się Notification::Blocking
teraz, również nie jest bardzo duża.
Jaka abstrakcja jest bardziej odpowiednia dla tego problemu?
Odpowiedzi:
Chcesz uniknąć wiedzy klas podstawowych o klasach pochodnych. Wprowadza ścisłe sprzężenie i jest bólem konserwacyjnym, ponieważ musisz pamiętać o dodawaniu do listy za każdym razem, gdy tworzysz nową klasę pochodną.
Zapobiegnie to również możliwości umieszczenia klasy Notification w pakiecie / zestawie wielokrotnego użytku, jeśli chcesz użyć tej klasy w wielu projektach.
Jeśli naprawdę chcesz użyć jednej klasy bazowej, innym sposobem na rozwiązanie tego jest dodanie wirtualnej właściwości lub metody IsBlocking w podstawowej klasie powiadomień. Klasy pochodne mogą następnie zastąpić to, aby zwrócić wartość prawda lub fałsz. Miałbyś rozwiązanie jednej klasy bez wiedzy klasy podstawowej o klasach pochodnych.
źródło
Wygląda to bardzo osobliwie i jest szczególnym zapachem kodu.
Podałbym podklasy, jeśli masz różnice w zachowaniu między klasami i chcesz traktować wszystkie te powiadomienia w ten sam sposób (tj. Używając polimorfizmu ).
źródło
W przeciwieństwie do istniejących odpowiedzi, sugerowałbym, że właściwość boolean jest najlepszą opcją, jeśli tryb, który ma być użyty, wymaga dynamicznej zmiany (np. Za pomocą pliku konfiguracyjnego, który podaje listę typów, które mają być blokowane a które nie są).
To powiedziawszy, lepszym projektem nawet w tej sytuacji może być użycie obiektu Decorator.
źródło
Powiedziałbym, że zależy to od tego, ile jeszcze wyjątkowych jest w blokowaniu powiadomień, chociaż moją pierwszą myślą jest użycie „obu”:
W ten sposób możesz użyć
n.Blocking
lubn is BlockingNotification
(wszystko w pseudokodzie), chociaż jeśli chcesz pozwolić klasie na implementację wartości kontekstowejBlocking
, ponieważ będziesz musiał sprawdzać tę wartość za każdym razem,BlockingNotification
klasa staje się mniej przydatne.W każdym razie zgadzam się z innymi odpowiedziami, że nie chcesz, aby implementacja klasy podstawowej
Blocking
musiała wiedzieć o klasach pochodnych.źródło
Zamiast tworzyć dwie klasy podstawowe i wiele wystąpień każdej z nich, utwórz jedną klasę powiadomień z wartością logiczną, aby wskazać, czy powiadomienie blokuje i wszelkie inne informacje potrzebne do przekazania powiadomienia użytkownikowi.
Pozwala to na użycie jednego zestawu kodu do przetwarzania i prezentacji powiadomień oraz zmniejsza złożoność kodu.
źródło