• Nie Znaleziono Wyników

Wzorce Projektowe, które uratowały nasze projekty

N/A
N/A
Protected

Academic year: 2022

Share "Wzorce Projektowe, które uratowały nasze projekty"

Copied!
57
0
0

Pełen tekst

(1)

Wzorce Projektowe,

które uratowały nasze

projekty

(2)

.

Adrian Piętka

EMPHIE SOLUTIONS

Mateusz Konieczny

BRAINHUB

Dawid Mazur

CLEARCODE

Łukasz Januszek

COMPLETRICS

Zbigniew Cisiński

EMPHIE SOLUTIONS

(3)

🤯 Wzorce Projektowe

(4)

Co wiesz o WZORCACH

PROJEKTOWYCH?

(5)
(6)

Co ma łazienka do

wzorców projektowych?

(7)

- akademickie tłumaczenie i przykłady:

- carBuilder.setEngine(engine) - UMLe wydają się skomplikowane

- nie do końca wiemy kiedy zastosować dany wzorzec - czasem kilka wzorców pasuje - czy to dobrze?

- czasem kilka wzorców musielibyśmy skleić razem - czy to dobrze?

- czasem nic nie pasuje!

- czasem po prostu trudno zacząć

😨 Czemu się ich na początku boimy?

(8)

- łoo Panie

- no ciężko, ciężko, ....

- ...

- od dostrzegania problemów w kodzie - szukania rozwiązań

❓ No to jak zacząć proszę Pana?

(9)

DEVENV.PL

(10)

Hej dzieci! Interesuje was przemoc?

- Problem: filtrowanie reklam po różnych parametrach, konieczna precyzja

- Problem: dane z różnych źródeł

- Błędy mogą przynieść poważne konsekwencje

(11)

Stringi, wszędzie stringi!

- Brak realnej walidacji i możliwość pomieszania pól ze względu na kiepskie nazewnictwo

- Primitive Obsession!

(12)

Jak wygląda problem?

(13)

Rozwiązanie: Value Object

DZIECI SĄ JUŻ BEZPIECZNE!

(14)

Czy aby na pewno to wszystko?

(15)

Wzorce implementujemy w całości!

https://martinfowler.com/bliki/ValueObject.html

(16)

Zróbmy trochę porządku

(17)

Brakuje tu ważnej cechy tego wzorca

Objects that are equal due to the value of their properties are called value objects. https://martinfowler.com/bliki/ValueObject.html

(18)

Rozwiązanie? Przeciążyć operator, albo...

(19)

Co dostaliśmy?

- Większa odporność na błędy

- Walidacja i logika biznesowa na właściwym miejscu - Lepsza czytelność kodu

(20)

Różni ludzie, mechaniki, postacie...

- Problem: różnorodne dane wejściowe

- Problem: wieczna kompatybilność wsteczna - Problem: bardzo uciążliwa budowa obiektu - Rozwiązanie:

Fabryka konfigurowana Strategiami Parsowania

(21)

Konstruktor jest smokiem

- Mnóstwo linijek kodu (~3k?) - Jak to testować?

- Co jak dane będą niewłaściwe?

(22)

Smoki do fabryk!

- Rozwiązanie: Fabryka (Metoda Fabryczna)

- każdy komponent jest testowalny

- fabryka odpowiada za weryfikację i konstrukcję - ale - co z dodawaniem mechanik?

(23)

Skonfiguruj ekstraktor Strategiami

- Rozwiązanie: konfiguracja parserami (Strategiami)

- kolekcja strategii, “która pasuje”

- strategie są testowalne i rejestrowalne

(24)

Zrost Fabryki ze Strategią - co dało?

- Wszystko jest łatwe do przetestowania - Nie ma śmieci konstrukcyjnych w kodzie - Łatwa rozszerzalność

- Wiadomo, gdzie jest ewentualny bug

- Innymi słowy - łatwiej, czytelniej, przyjemniej

(25)

Użytkownik musi wiedzieć co się dzieje

- powiadamiamy użytkownika o tym co się wydarzyło w systemie

- na maila

- nie będzie tego dużo - ...

(26)

No to siup SERVISik bo jak inaczej

class EmailNotificationService {

public send(to: string, subject: string, content: string) { console.log('Wysyłka maila', to, subject, content);

// implementacja wysyłki }

}

// i wykorzystujemy w kilkunastu miejscach

const emailNotificationService = new EmailNotificationService();

emailNotificationService.send(

'adrian@devenv.pl',

'Nowy like w serwisie DevEnv',

'Łukasz Januszek polubił Twój profil!' );

(27)

Powiadomimy użytkownika jeszcze innym kanałem

O taki piękny z taką piękną cyferką.

- mamy już powiadomienia mailowe

- to dodajmy w naszej aplikacji... taki fajny dzwoneczek 🔔 - chwila roboty na pewno

- ...

- wszystko już jest do tych powiadomień

(28)

No to siup drugi SERVISik i wklejamy wszędzie

class AppNotificationService {

public notify(to: string, subject: string, content: string) { // implementacja notyfikacji

} }

// i wykorzystujemy w kilkunastu miejscach, // zaraz za powiadomieniami mailowymi

const appNotificationService = new AppNotificationService();

appNotificationService.send(

'adrian@devenv.pl',

'Nowy like w serwisie DevEnv',

'Łukasz Januszek polubił Twój profil!' );

(29)
(30)

Co mamy tak naprawdę ogarnąć?

Polub profil Adriana

Notyfikacja E-mail

👦

Powiadom Adriana

...

(31)

Skupiamy się na logice powiadomień

Notyfikacja E-mail

Jak powiadomić Adriana?

...

Powiadom Adriana

(32)

OBSERWUJEMY czy wysyłamy jakieś powiadomienia

SUBJECT OBSERVER

Powiadom!

Implementacja powiadamiacza Lista powiadamiaczy

Czyli co się ma stać.

(33)

Observer - Powiadamiacze

class NotificationSystem {

public update(notification: UserNotification) : void {

throw Error('Please, implements notification behavior.');

} }

class AppNotification extends NotificationSystem {

public update(notification: UserNotification) : void { console.log('Notifikacje aplikacji', notification);

} }

class EmailNotification extends NotificationSystem {

public update(notification: UserNotification) : void { console.log('Notifikacje mailowe', notification);

} }

📢

(34)

Subject - Grupujemy powiadamiaczy

class UserNotification {

private systems: NotificationSystem[] = [];

public from: User;

public to: User;

public message: string;

public register(system: NotificationSystem) { this.systems.push(system);

}

public notify(from: User, to: User, message: string) { this.from = from;

this.to = to;

this.message = message;

this.systems.forEach(s => s.update(this));

} }

🔔 ✉

📢

(35)

Wysyłamy powiadomienia użytkownikowi

class User { constructor(

public readonly username: string, public readonly email: string ) { }

}

const notification = new UserNotification();

notification.register(new AppNotification());

notification.register(new EmailNotification());

notification.notify(

new User('adrian.pietka', 'adrian@devenv.pl'),

new User('lukasz.januszek', 'nie.mam@zadnego.maila.pl'), 'Polajkował Twój profil!'

);

(36)

State Design Pattern

interface Player { currentState: State click()

play();

pause();

next();

updateIcon(state: State);

onChange: PlayerEvent;

}

(37)

State Design Pattern

enum State { Idle, Loading, Error, Playing,

Paused };

(38)

State Design Pattern

(39)

State Design Pattern

class WebPlayer implements Player { click() {

switch (state) {

case State.Idle:

this.currentState = State.Loading;

this.updateIcon(State.Loading);

this.play();

break;

case State.Loading:

break;

case State.Error:

break;

case State.Playing:

break;

case State.Paused:

break;

} }

}

(40)

switch (state) {

case State.Idle:

this.currentState = State.Loading this.updateIcon(State.Loading) this.play()

break;

case State.Loading:

//do nothing break;

case State.Error:

this.currentState = State.Loading this.updateIcon(State.Loading) this.play()

break;

case State.Playing:

this.currentState = State.Paused this.updateIcon(State.Paused) this.pause()

break;

case State.Paused:

this.currentState = State.Playing this.updateIcon(State.Playing) this.play()

break;

}

State Design Pattern

onChange?

doubleClick()?

przyciski prev i next?

(41)

State Design Pattern

click()

click() click() click() click() click()

currentState

PlayerState

(42)

State Design Pattern

click()

click() click() click() click() click()

currentState

PlayerState

click() {

this.currentState.click();

}

(43)

State Design Pattern

click()

player: Player;

click() click() click() click() click()

(44)

State Design Pattern

click() click() click() click() click() switch (state) {

case State.Idle:

this.currentState = State.Loading;

this.updateIcon(State.Loading);

this.play();

break;

(45)

State Design Pattern

abstract class PlayerState { player: Player;

constructor(player: Player) { this.player = player;

}

abstract click(): void;

}

class IdlePlayerState extends PlayerState class LoadingPlayerState extends PlayerState [...]

(46)

State Design Pattern

class IdlePlayerState extends PlayerState { constructor(player: Player) {

super(player) }

click(): void {

player.currentState = LoadingPlayerState(player: player) player.updateIcon(State.Loading)

player.play() }

}

(47)

Problem - Slack with extra steps

- wiele różnego typu kanałów

- Feed, Channels, DMs, Threads, ...

- posiadających różne elementy

- Messages, Notifications, Integrations, …

- z różnymi akcjami

- Emoji, Start Thread, Delete Message, Add Images, …

- wymagania:

- różne konfiguracje

- które łatwo (i szybko) zmienić

(48)

Różne strategie renderowania

- Messages, Notifications, Integrations, … - różne sposoby zrobienia tej samej rzeczy

Notification Message

Integration

render()

Message (Search)

(49)

Wybór odpowiedniej strategii

- łańcuch odpowiedzialności (Chain of responsibility)

- jako łańcuch strategii

- na podstawie kontekstu [typ] wybierany jest handler - łańcuch może się zmieniać (elementy, kolejność, ...)

(50)

Komponenty z akcjami

- każda konwersacja wspiera różne akcje

- Command - hermetyzacja operacji do obiektów

- prosty kontekst -> itemId

(51)

Trzeba to jakoś zbudować

- Builder

- wiele konfiguracji konstrukcji - oddzielenie budowy od logiki

- biznesowej

- szczegółów budowy

- deklaratywny kod

- mówię co, a nie jak - krótki

- odporne na zmiany

(52)

Kompozycja potrzeb

- różne strategie renderowania - Strategy

- wybór odpowiedniej strategii - Chain of Responsibility - komponenty z reużywalnymi akcjami - Command - złożenie tego do kupy - Builder

- dekompozycja wymagań

- jeden problem -> jedno rozwiązanie (np. wzorzec)

- SRP

- kod nie jest kruchy

(53)

- komunikacja

- sprawdzony schemat rozwiązania - strukturyzują kod

- niwelują niedoskonałości

✅ Jaka jest ich wartość dodana?

(54)

Podsumowanie

- wzorce odpowiadają na potrzeby

- wzorce szybko się psują (zmienia się wymaganie biznesowe, a wzorzec zostaje :))

- kompozycja wzorców jest OK (tak długo jak każdy posiada swoją odrębną odpowiedzialność)

- z głową - czasem jeden if jest łatwiejszy do ogarnięcia i zarządzania niż dekorowana fabryka strategii

(55)

READY4DEV.PL

(56)

DEVENV.PL/SLACK

DOŁĄCZ

(57)

CODING-DOJO-SILESIA.PL

Cytaty

Powiązane dokumenty

static void sort(Object[] a, int fromIndex, int toIndex) Sorts the specified range of the specified array of objects into ascending order, according to the natural ordering

b) wyświetlić za pomocą funkcji alert() tekst „oleg” z tego napisu (dwoma sposobami),. c) wyświetlić za pomocą funkcji alert() napis „kolacja” powstały z wyjściowego

Zadanie 2.(5 pkt.) Zmodyfikować skrypt z zadania 2 z zestawu 11 w ten sposób, że zamiast podawania danych przy pomocy funkcji prompt() będziemy wpisywać je do pól

Funkcja szuka pierwszego wystąpienia łańcucha sub w podanym łańcuchu s Zwraca wskaźnik na znalezioną pozycję wystąpienia lub adres NULL. „ string

A novel strategy to enhance string stability of autonomous vehicles with sensor delay and actuator lag is proposed based on a model predictive control framework.. To com- pensate

In reviewing the three language-teacher-affiliated sociocultural theories, the psychological premises found in literature on the subject of individual differences,

Slo va v sou kromých do pi sech, 111 let české ho sou kro mé ho do pi su v kor pu so vém zpra cování a Sou kromá ko res pon dence ja ko lingvis tický pra men odpovídají na

First the static state due to gravity is studied in chapter 5, and the in-plane transversal motion of the string due to a parametrical and a transversal excitation at one of the ends