You are on page 1of 4

SOLID PRINCIPLES:

- Single Responsibility Principle:


- każda klasa/komponent powinna zajmować się jedną, osobną, inną
funkcjonalnością,
np. klasa PersistenceManager powinna posiadać tylko metody związane z
przechowywaniem danego tworu.
- klasa powinna mieć tylko jeden powód do zmiany.
- dzielimy skomplikowaną klasę na mniejsze komponenty, co pozwala na
lepsze zrozumienie kodu, zarządzanie nim i refactoring.
- Open-Closed Principle:
- każda klasa powinna być otwarta na rozszerzanie, ale zamknięta na
modyfikację.
- raz napisany i przetestowany kod powinien zostać niezmieniony (gdy
nie posiada w sobie bugów).
- gdy potrzebujemy dodać jakąś funkcjonalność, powinniśmy zrobić to jak
najbardziej generycznie, aby dało się rozszerzyć daną funkcjonalność z użyciem
mniejszych klas.
- jako przykład może posłużyć Specification, gdy nadchodzi potrzeba
wyszukiwania po 3 polach, może być już 7 możliwości, więc powinniśmy zrobić
AndSpecification
i łączyć wszystkie specyfikacje, a potem stworzyć globalny filter,
który sprawdzi, czy .every(spec => spec.isSatisfied(item))
- Liskov Substitution Principle:
- tworząc metodę dla base klasy, musi ona także działać dla
dziedziczących klas.
- jako przykład: mamy klasę Prostokąt i dziedziczącą klasę Kwadrat
(prostokąt o takich samych bokach), metoda powinna rozróżniać dwie różne figury i
zwracać poprawne wyniki.
- Interface Segregation Principle:
- ogólnie w programowaniu chodzi o rozbicie wielkich interfejsów na
małe, żeby używać tylko tę potrzebną część metod, a nie dodatkowo te, których się
nie używa.
- tutaj ma miejsce zastosowanie YAGNI (You Ain't Going to Need It)
- w JavaScript nie ma interfejsów, nadal da się stworzyć sztuczne
interfejsy za pomocą klas.
- Dependency Inversion Principle:
- high-level moduły nie powinny zależeć od low-level modułów, tylko od
abstrakcji
- np. przeglądanie drzewa genealogicznego, w high-level module będziemy
mieli dane i sposób przeszukiwania, więc zmieniając typ storage zmienimy tu też
przeszukiwanie,
a nie będziemy tego zmieniać w low-level modułach, np. Relationships

DESIGN PATTERNS:
GAMMA CATEGORIZATION:
1. Creational patterns
- zajmują się tworzeniem, konstrukcją obiektów.
- explicit (constructor) vs implicit (DI, reflection, etc.)
- wholesale (single statement) vs piecewise (step-by-step)
2. Structural patterns
- concerned with the structure (e.g. class members)
- many patterns are wrappers that mimic the underlying class' interface
- stress the importance of good API design
3. Behavioral patterns
- they are all different, no central theme
I. CREATIONAL PATTERNS
- Builder
- osobny komponent do tworzenia obiektów (step-by-step), gdy tworzenie
staje się skomplikowane i nie chcemy tego robić w konstruktorze (piecewise)
- Factory Method
- statyczna metoda tworząca obiekt, bardziej ekspresywna niż
konstruktor
- Factory (Abstract Factory)
- osobna klasa z factory methods
- encja która zajmuje się procesem tworzenia obiektu
- może być external, albo znajdować się w środku obiektu, ale wtedy
najczęściej łamie Single Responsibility / Open-Closed Principle
- Prototype
- tworzenie obiektu z istniejącego obiektu
- wymagana explicit deep kopii lub kopii przez serializację, np.
JSON.parse()
- Singleton
- komponent tworzony tylko raz, np. database repository
- konstruktor wybiera co chce zwrócić, możemy zwracać tę samą instancję
- monostate: wiele instancji, dzielone dane
- lepiej zależeć na dependencji niż na singletonie

II. STRUCTURAL PATTERNS


- Adapter
- tworzy konstrukcję, która dopasowuje już istniejący interfejs X tak,
żeby pasował do oczekiwanego interfejsu Y
- przykład to np. klasa kwadrat i klasa prostokąt i funkcja licząca
pole (różne boki, trzeba przekonwertować)
- Bridge
- mechanizm który oddziela interfejs od implementacji
- zapobiega "Cartesian product" complexity explosion
- przyda się do rozwiązań odróżniających system na których są
wywoływane, żeby nie tworzyć n * tego samego
- Composite
- można przekazywać obiekty obiektom za pomocą dziedziczenia lub
kompozycji
- mechanizm traktowania pojedynczych (skalarnych) obiektów i kompozycji
obiektów w jednolity sposób
- pozwala tworzyć złożone obiekty z kilku obiektów
- obiekty można iterować za pomocą Symbol.iterator albo yieldując this
na single obiekcie
- Decorator
- dodawanie zachowania bez zmiany klasy samej w sobie. (wspiera OCP i
SRP)
- trzyma referencję do odekorowanego obiektu
- może ale nie musi przekazywać calle do underlying obiektu
- Facade
- dostarcza prosty, łatwy do zrozumienia interfejs spinający ze sobą
logikę wielu systemów, interfejsów
- jego celem może być wyexposowanie internal kodu przez fasadę
- Flyweight
- technika optymalizacji miejsca która pozwala na użycie mniejszej
ilości pamięci poprzez trzymanie danych powiązanych ze sobą zewnętrznie.
- używa się żeby uniknąć redundancji w przechowywaniu danych, np. kilku
userów o takich samych imionach/nazwiskach
- Proxy
- tworzy obiekt który forwarduje calle do realnego obiektu podczas
wykonywania dodatkowych funkcji
- Ten zasób może być zdalny, drogi do stworzenia lub może wymagać
dodatkowej funkcjonalnością
- Rodzaje:
Value,
Property,
Protection,
Virtual Proxy

III. BEHAVIORAL PATTERNS


- CHAIN OF RESPONSIBILITY
- pozwala komponentom przetwarzać informacje/eventy w łańcuchu
- każdy element w łańcuchu odwołuje się do następnego (linked lista)
- COMMAND
- enkapsuluje detale o operacji w osobnym obiekcie
- definiuje insturkcje do zaaplikowania komendy
- może także zdefiniować instrukcje dla wycofania komendy
- można stworzyć także złożone komendy (macros)
- INTERPRETER
- komponent transformujący tekstowy input w object-oriented struktury
- używany przez interpretery, kompilery, static analysis toole
- najpierw zmienia je w osobne leksykalne tokeny (lexing) i
interpretuje sekwencje tokenów (parsing)
- MEDIATOR
- główny komponent trzymający referencję do wszystkich pozostałych
- sprawia, że pozostałe z nich nie wiedzą o sobie wzajemnie
- bierze udział w komunikacji dwustronnej z połączonymi komponentami
- posiada metody które komponent może wywołać (i wzajemnie)
- używany np. w chat roomach
- MEMENTO
- handler/token reprezentujący stan systemu. Pozwala zrollbackować do
stanu, kiedy token został wygenerowany.
- nie exposuje informacji o stanie (ale może)
- może zostać użyty do implementacji undo/redo operacji
- OBSERVER
- obiekt ktory chce być poinformowany o eventach występujących w
systemie.
- encja tworząca eventy to observable
- STATE
- zachowanie obiektu jest zależne od jego stanu
- po triggerze zmiany stanu, obiekt przechodzi z jednego stanu do
drugiego
- twór zarządzający stanem to "state machine"
- STRATEGY
- pozwala zdefiniować szkielet algorytmu z konkretnymi implementacjami
zawartymi w subklasach
- umożliwia wybór zachowania systemu podczas run-time
- robi to samo co template method, ale poprzez kompozycję
- TEMPLATE METHOD
- pozwala zdefiniować szkielet algorytmu z konkretnymi implementacjami
zawartymi w subklasach
- robi to samo co strategy, ale poprzez dziedziczenie
- VISITOR
- komponent wiedzący jak przemierzać strukturę danych stworzoną z
możliwie powiązanych typów
- rozprzestrzenia accept(Visitor v) metodę przez całą hierarchię
- tworzy visitora z visitFoo(Foo), dla każdego elementu w hierarchii
- każdy accept() po prostu wywołuje visitor.visitFoo(this)
- ITERATOR
- w JS używa się Symbol.iterator()
- dostarcza interfejs pozwalający na dostanie się do elementu
iterowalnego obiektu
- obiekty mogą stać się iterowalne przez użycie for loopa

You might also like