SlideShare a Scribd company logo
1 of 71
WZORCE
PROJEKTOW
E W
PRAKTYCE
▸Marek Keżel
▸Kierownik projektu autorskiego systemu ERP do
zarządzania produkcją mebli tapicerowanych
▸Programista PHP, JS, Python
▸Linux, CCNA R&S, CCNA Sec
O MNIE
AGENDA
▸Czym jest wzorzec projektowy ?
▸Singleton - nikt go nie lubi
▸Simple Factory - tworzyć, prosto
▸Adapter - dopasowywać
▸Facade - upraszczać
▸Observer - powiadamiać
▸Dependency Injection - wstrzykiwać zależności
CZYM JEST
WZORZEC
PROJEKTO
WY ?
In software engineering, a software
design pattern is a general, reusable
solution to a commonly occurring problem
within a given context in software design.
It is not a finished design that can be
transformed directly into source or
machine code. Rather, it is a description
or template for how to solve a problem
that can be used in many different
situations. Wikipedia
CZYM JEST WZORZEC PROJEKTOWY
▸Ogólnym rozwiązaniem często spotykanego problemu
projektowego.
▸Szablonem rozwiązania problemu
▸Sformalizowanym elementem najlepszych praktyk
programistycznych
CZYM NIE JEST WZORZEC
PROJEKTOWY
▸Gotową implementacją rozwiązania problemu którą możemy
skopiować do naszego projektu
▸Szablonem rozwiązania w konkretnym języku*
UWAGA!
▸Stosowanie wzorców projektowych “na siłę” jest anty
wzorcem.
▸Jeżeli jest problem z dobraniem wzorca może lepiej
odpuścić sobie stosowanie jakiekolwiek w tym kontekście.
▸Kod bez wzorców projektowych będzie działał*
WZORCE
PROJEKTO
WE WG
“BANDY
CZWORGA”
WZORCE PROJEKTOWE WG BANDY
CZWORGA - KREACYJNE
▸Abstract Factory
▸Builder
▸Factory Method
▸Prototype
▸Singleton
WZORCE PROJEKTOWE WG BANDY
CZWORGA - STRUKTURALNE
▸Adapter
▸Bridge
▸Composite
▸Decorator
▸Facade
▸Flyweight
▸Proxy
WZORCE PROJEKTOWE WG BANDY
CZWORGA - CZYNNOŚCIOWE
▸Chain of Responsibility
▸Command
▸Interpreter
▸Iterator
▸Mediator
▸Memento
▸Observer
▸State
▸Strategy
▸Template Method
▸Visitor
SINGLETON
In software engineering, the singleton
pattern is a software design pattern that
restricts the instantiation of a class to one
"single" instance. This is useful when
exactly one object is needed to
coordinate actions across the system.
Wikipedia
W CZYM MOŻE POMÓC?
▸Jedna instancja klasy podczas działania aplikacji
▸Globalny dostęp do w/w instancji*
▸Ulepszona wersja zmiennej globalnej
<?php
class Logger
{
protected static $instance;
private function __construct() {}
private function __clone() {}
private function __wakeup() {}
public static function getInstance()
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
public function info($message, $category)
{
//zapisać do bazy danych
}
}
PRZYKŁADOWA
IMPLEMENTACJA
<?php
class Trello
{
protected static $instance;
private function __construct() {}
private function __clone() {}
private function __wakeup() {}
public static function getInstance()
{
if (is_null(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
public function dodajKarte($lista, $parametry)
{
//połączyć się z trello i dodać kartę do listy
}
}
PRZYKŁADOWA
IMPLEMENTACJA
JAKIE MA WADY ? ANTYWZORZEC ?
▸Silne wiązania między kodem wykorzystującym singletona a
nim samym poprzez dostęp globalny (wiązanie z
kontekstem)
▸Ukrywanie zależności
▸Naruszenie zasad SOLID: Dependency Inversion Principle,
Single Responsibility Principle
▸Testowanie, jak podmienić singletona na potrzeby testów.
▸Testy mogą zacząć być zależne od siebie. Jeżeli jeden test
zmieni stan obiektu drugi może pracować na zmienionym już
stanie a nie na początkowym.
<?php
class Zgloszenie extends ActiveRecord
{
public function create()
{
if ($this->save()) {
Logger::getInstance()->info('Dodano zlgoszenie', __METHOD__);
$this->wyslijPowiadomienie();
return true;
}
return false;
}
public function wyslijPowiadomienie()
{
Trello::getInstance()->dodajKarte('zgloszenia', [
'zrodlo' => $this->zlodlo,
'temat' => $this->temat,
'tresc' => $this->tresc,
]);
}
}
PRZYKŁADOWEUŻYCIE
CO ZROBIĆ JEŻELI POTRZEBNA JEST TYLKO JEDNA
INSTANCJA KLASY W APLIKACJI ?
▸Czy na pewno potrzebna jest tylko jedna instancja?
▸Użyć Dependency Injection
▸Użyć Service Locator*
▸Użyć świadomie singletona z pełną świadomością jego
konsekwencji
<?php
class Zgloszenie extends ActiveRecord
{
protected $logger;
protected $trello;
public function __construct(LoggerInterface $logger, TrelloInterface $trello)
{
$this->logger = $logger;
$this->trello = $trello;
}
public function create()
{
if ($this->save()) {
$this->logger->info('Dodano zlgoszenie', __METHOD__);
$this->wyslijPowiadomienie();
return true;
}
return false;
}
public function wyslijPowiadomienie()
{
$this->trello->dodajKarte('zgloszenia', [
'zrodlo' => $this->zlodlo,
'temat' => $this->temat,
'tresc' => $this->tresc,
]);
}
}
PRZYKŁADOWEUŻYCIE-
ZAMIASTSINGLETONA-DI
<?php
$container = new yiidiContainer;
$container->setSingleton('LoggerInterface', 'Logger');
$container->setSingleton('TrelloInterface', 'Trello');
$zgloszenie = $container->get('Zgloszenie');
PRZYKŁADOWEUŻYCIE-
ZAMIASTSINGLETONA-DI
DOSTEP GLOBALNY PRZYKŁADY
▸Yii2 - logger, komponenty, DI (Yii::error(), Yii::$app->user)
▸Laravel - helpery, facady (config(), view(), Cache::get())
SIMPLE
FACTORY
In object-oriented programming (OOP), a
factory is an object for creating other
objects – formally a factory is a function
or method that returns objects of a
varying prototype or class from some
method call, which is assumed to be
"new".
Wikipedia
W CZYM MOŻE POMÓC?
▸Tworzenie obiektów z rodziny klas ze wspólnym interfejsem
na podstawie parametru
▸Enkapsulacja procesu tworzenia obiektów - nie pokazujemy
logiki procesu tworzenia
▸Uniknięcie warunkowych procesów tworzenia obiektów
▸Centralna lokalizacja tworzenia obiektów - łatwo
zareagujemy np na zmiany wymaganych parametrów
konstruktora
▸DRY
<?php
class ArtykulConverterFactory
{
public function createConverter(int $typ): ArtykulConverterInterface
{
switch ($typ) {
case ZamowieniePozycje::TYP_LOZKO:
return new LozkoConverter();
case ZamowieniePozycje::TYP_SZAFKA:
return new SzafkaConverter();
case ZamowieniePozycje::TYP_PUFA:
return new PufaConverter();
default:
throw new IndeksException("Błędny typ artykułu");
}
}
}
PRZYKŁADOWA
IMPLEMENTACJA
class IndeksFacade
{
protected $typ;
protected $konwerterFactory;
protected $service;
public function __construct(
int $typ,
ArtykulConverterFactoryInterface $konwerterFactory,
IndeksServiceInterface $service)
{
$this->typ = $typ;
$this->konwerterFactory = $konwerterFactory;
$this->service = $service;
}
public function utworzZKreatora($konfiguracjaZKreatora): Indeks
{
$konfiguracja = $this->getKonwerter()->zKreatora($konfiguracjaZKreatora);
return $this->service->utworz($konfiguracja);
}
public function utworzZPozycji(AbstractPozycja $pozycja): Indeks
{
$konfiguracja = $this->getKonwerter()->zPozycji($pozycja);
return $this->service->utworz($konfiguracja);
}
public function getKonwerter(): ArtykulConverterInterface
{
return $this->konwerterFactory->createConverter($this->typ);
}
}
PRZYKŁADOWEUŻYCIE
JAKIE MA WADY ?
▸Większa złożoność kodu
▸Większa ilość klas
▸Wersja simple factory łamię zasadę Open Close Principle
(SOLID).
<?php
class ArtykulConverterFactory
{
public function createConverter(int $typ): ArtykulConverterInterface
{
$mapa = Yii::$app->params['mapaArtykulow'];
if (!array_key_exists($typ, $mapa)) {
throw new IndeksException("Błędny typ artykułu");
}
$converterFQN = $mapa[$typ] . 'Converter';
return new $converterFQN;
}
}
PRZYKŁADOWA
IMPLEMENTACJA
ADAPTER
In software engineering, the adapter
pattern is a software design pattern (also
known as wrapper, an alternative naming
shared with the decorator pattern) that
allows the interface of an existing class to
be used as another interface. It is often
used to make existing classes work with
others without modifying their source
code.
Wikipedia
W CZYM MOŻE POMÓC?
▸Dopasowanie dwóch niekompatybilnych interfejsów
▸Przykrycie zewnętrznego kodu własnym interfejsem w celu
jeszcze większego rozluźnienia zależności
▸Praca ze starym kodem i przystosowanie go do nowego
interfejsu
UWAGA!
▸Dwa typy Adaptera: klasowy oraz obiektowy
▸Adapter dwukierunkowy - każda z klas może pełnić funkcję
zarówno klienta jak adaptowanej klasy
▸Kod kliencki nie wie czy pracuje z klasą docelową
bezpośrednio czy za pośrednictwem adaptera z klasą z
niekompatybilnym interfejsem
<?php
use TrelloClient;
$client = new Client();
$client->authenticate(
Yii::$app->params['trello_api_key'],
Yii::$app->params['trello_token'],
Client::AUTH_URL_CLIENT_ID);
$client->cards()->create(
array_merge($parametry, ['idList' => $listaID])
);
WYWOŁANIEBEZPOŚREDNIE
KODUBIBLIOTEKI
<?php
class Trello extends Component implements TrelloInterface
{
public $apiKey;
public $token;
/** @var Client $client */
protected $client;
public function __construct(Client $client, $config = [])
{
$this->client = $client;
parent::__construct($config);
}
public function init()
{
parent::init();
$this->polacz();
}
public function dodajKarteDoListy(string $listaID, array $parametry)
{
return $this->client->cards()->create(
array_merge($parametry, ['idList' => $listaID])
);
}
protected function polacz()
{
$this->client->authenticate($this->apiKey, $this->token, Client::AUTH_URL_CLIENT_ID);
}
}
PRZYKŁADOWA
IMPLEMENTACJA
Yii::createObject(Trello::class)->dodajKarteDoListy($listaID, $parametry);
PRZYKŁADOWEUŻYCIE
JAKIE MA WADY ?
▸Większe skomplikowanie kodu
▸Zbyt częste tworzenie adapterów nawet jeśli nie jest to
wymagane
FACADE
The facade pattern is a software-design
pattern commonly used in object-oriented
programming. Analogous to a facade in
architecture, a facade is an object that
serves as a front-facing interface masking
more complex underlying or structural
code.
Wikipedia
W CZYM MOŻE POMÓC?
▸Ułatwienie korzystania z rozbudowanego, skomplikowanego
interfejsu biblioteki, komponentu
▸Podział na warstwy
▸Czytelniejszy kod klienta
▸Niezależny rozwój złożonego systemu schowanego za
fasadą - klient ma stały interfejs fasady.
$konwerter = (new ArtykulConverterFactory())->createConverter($typArtykulu);
$konfiguracja = $konwerter->zKreatora($konfiguracjaZKreatora);
$service = new IndeksService($this->typ, new IndeksArtykulModelFactory());
$indeks = $this->service->utworz($konfiguracja);
……
$konwerter = (new ArtykulConverterFactory())->createConverter($pozycja->typ);
$konfiguracja = $konwerter->zZamowieniePozycje($pozycja);
$service = new IndeksService($this->typ, new IndeksArtykulModelFactory());
$indeks = $this->service->utworz($konfiguracja);
PRZYKŁADOWYPROCES
GENEROWANIAINDEKSUARTYKULU
class IndeksFacade
{
protected $typ;
protected $konwerterFactory;
protected $service;
public function __construct(
int $typ,
ArtykulConverterFactoryInterface $konwerterFactory,
IndeksServiceInterface $service)
{
$this->typ = $typ;
$this->konwerterFactory = $konwerterFactory;
$this->service = $service;
}
public function utworzZKreatora($konfiguracjaZKreatora): Indeks
{
$konfiguracja = $this->getKonwerter()->zKreatora($konfiguracjaZKreatora);
return $this->service->utworz($konfiguracja);
}
public function utworzZPozycji(AbstractPozycja $pozycja): Indeks
{
$konfiguracja = $this->getKonwerter()->zPozycji($pozycja);
return $this->service->utworz($konfiguracja);
}
public function getKonwerter(): ArtykulConverterInterface
{
return $this->konwerterFactory->createConverter($this->typ);
}
}
PRZYKŁADOWA
IMPLEMENTACJA
Yii::createObject(IndeksFacade::class, [$typ])->utworzZKreatora($konfiguracjaZKreatora);
Yii::createObject(IndeksFacade::class, [$typ])->utworzZPozycji($pozycja);
PRZYKŁADOWEUŻYCIE
LARAVEL FASADY
▸IlluminateSupportFacadesRoute::get()
▸IlluminateSupportFacadesView::make()
▸IlluminateSupportFacadesValidator::make()
▸…
JAKIE MA WADY ?
▸Może się stać klasą-bogiem - posiadać silne powiązanie z
bardzo dużą ilością innych klas aplikacji
OBSERVER
The observer pattern is a software design
pattern in which an object, called the
subject, maintains a list of its dependents,
called observers, and notifies them
automatically of any state changes,
usually by calling one of their methods.
Wikipedia
W CZYM MOŻE POMÓC?
▸Powiadomienie zainteresowanych obiektów o zmianie stanu
innego obiektu
▸Implementacja powiadomień (events)
class ObserverA implements SplObserver
{
public function update(SplSubject $subject)
{
echo 'Aktualizacja ' . __CLASS__ . PHP_EOL;
}
}
class ObserverB implements SplObserver
{
public function update(SplSubject $subject)
{
echo 'Aktualizacja ' . __CLASS__ . PHP_EOL;
}
}
class Subject implements SplSubject
{
protected $observers = [];
public function attach(SplObserver $observer)
{
$this->observers[spl_object_hash($observer)] = $observer;
}
public function detach(SplObserver $observer)
{
unset($this->observers[spl_object_hash($observer)]);
}
public function notify()
{
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
}
PRZYKŁADOWA
IMPLEMENTACJA
$subject = new Subject();
$observerA = new ObserverA();
$observerB = new ObserverB();
$subject->attach($observerA);
$subject->attach($observerB);
$subject->notify();
// Aktualizacja ObserverA
// Aktualizacja ObserverB
PRZYKŁADOWEUŻYCIE
<?php
class TrelloNotyfikatorHandler implements NotyfikatorHandlerInterface
{
public function wyslij(MessageEvent $event) {
Yii::createObject(Trello::class)
->dodajKarteDoListy('zgloszenia', $event->message);
}
}
class Zgloszenie extends ActiveRecord
{
const NOWE_ZGLOSZENIE_EVENT = 'noweZgloszenie';
public function create()
{
if ($this->save()) {
$this->trigger(self::NOWE_ZGLOSZENIE_EVENT, new MessageEvent([
'message' => 'Nowe zgłoszenie o treści: ' . $this->tresc
]));
return true;
}
return false;
}
}
PRZYKŁADOWA
IMPLEMENTACJA-YII2
class ZgloszenieController extends yiiwebController
{
protected $notyfikator;
public function __construct($id, $module, $config = [], NotyfikatorHandlerInterface $notyfikator)
{
$this->notyfikator = $notyfikator;
parent::__construct($id, $module, $config);
}
public function actionCreate()
{
$model = new Zgloszenie();
$model->on(Zgloszenie::NOWE_ZGLOSZENIE_EVENT, [
$this->notyfikator,
'wyslij'
]);
$model->create();
}
}
PRZYKŁADOWEUŻYCIE-YII2
<?php
return [
Watek::class . '@' . Watek::EVENT_NOWY_WATEK_DO_ADMINA => [
TrelloNotyfikatorHandler::class,
EmailNotyfikatorHandler::class,
PushNotyfikatorHandler::class,
],
Zlecenie::class . '@' . Zlecenie::EVENT_AFTER_INSERT => [
NoweZlecenieHandler::class,
],
Zlecenie::class . '@' . Zlecenie::EVENT_AFTER_PRZYJECIE => [
PrzyjecieZleceniaHandler::class,
],
];
…
yiibaseEvent::on(Watek::class, Watek::EVENT_NOWY_WATEK_DO_ADMINA, [
TrelloNotyfikatorHandler::class,
'handle'
]);
DEFINICJAOBSERWATORÓW
NAPOZIOMIEKLAS
$foo = new Foo();
// this handler is a global function
$foo->on(Foo::EVENT_HELLO, 'function_name');
// this handler is an object method
$foo->on(Foo::EVENT_HELLO, [$object, 'methodName']);
// this handler is a static class method
$foo->on(Foo::EVENT_HELLO, ['appcomponentsBar', 'methodName']);
// this handler is an anonymous function
$foo->on(Foo::EVENT_HELLO, function ($event) {
// event handling logic
});
YII2EVENTSDOKUMENTACJA-PRZYKŁAD
REJESTRACJIOBSERWATORÓW
JAKIE MA WADY ?
▸Obserwatorzy nie znają innych obserwatorów
▸Kolejność powiadamiania jest niezależna
DEPENDEN
CY
INJECTION
In software engineering, dependency
injection is a technique whereby one
object supplies the dependencies of
another object. A "dependency" is an
object that can be used, for example as a
service. Instead of a client specifying
which service it will use, something tells
the client what service to use.
Wikipedia
W CZYM MOŻE POMÓC?
▸Usunięcie sztywnych odwołań z kodu klas
▸Rozluźnienie powiązań miedzy klasami.
▸SOLID: Dependency Inversion Principle
▸Oddzielenie procesu tworzenia obiektu od jego użycia
▸Ułatwienie testowanie kodu, podmiana zależności
▸Konfiguracja interfejsów programu za pomocą plików
konfiguracyjnych
UWAGA!
▸Dependency Injection jest jednym ze sposób implementacji
Inversion of Control poprzez wstrzykiwanie zależności z poziomu:
konstruktora, settera lub metody
▸IoC jest paradygmatem programowania polegającym na odwróceniu
kontroli. Zamiast samemu kontrolować kod frameworka, oddajemy
kontrolę naszego kodu dla tego właśnie frameworka (w tym
przypadku kontrolę nad tworzeniem obiektów)
▸Dependency Injection Container jest biblioteką dostarczają
funkcjonalność DI, która implementuje np. Tworzenie map
zależności między interfejsami a ich konkretnymi implementacjami,
odczytywanie zależności poprzez użycie Refleksji
IMPLEMENTACJE W PHP
▸Symfony Dependency Injection Component
▸Laravel Service Container
▸Yii2 Dependency Injection Container
▸PHP-DI (php-di.org)
<?php
class MadService extends BaseObject
{
protected $api;
public function __construct($config = [])
{
$this->api = new MadApi();
parent::__construct($config);
}
public function zamowieniaDoDostawcow()
{
return $this->api->zamowieniaDoDostawcow();
}
}
PRZYKŁADOWA
IMPLEMENTACJA
<?php
class MadService extends BaseObject
{
protected $api;
public function __construct(MadApiInterface $api, $config = [])
{
$this->api = $api;
parent::__construct($config);
}
public function zamowieniaDoDostawcow()
{
return $this->api->zamowieniaDoDostawcow();
}
}
PRZYKŁADOWA
IMPLEMENTACJA
<?php
interface MadApiInterface
{
public function zamowieniaDoDostawcow(): array;
}
PRZYKŁADOWA
IMPLEMENTACJA
<?php
class MadApi implements MadApiInterface
{
const SOAP_SERVER_LOGIN = ‘’;
protected $client;
public function zamowieniaDoDostawcow(): array
{
$result = $this->client->ZdDocListGet([
'ZdDocListGetData' => [
'ClientCode' => self::SOAP_SERVER_LOGIN,
],
]);
if ($result->ArrayZdDocListGetResult->Status !== 1) {
return [
'status' => 'error',
'massage' => $result->ArrayZdDocListGetResult->ErrorMessage,
];
}
return [
'status' => 'success',
'massage' => $result->ArrayZdDocListGetResult->ZdDocListGetResult,
];
}
}
PRZYKŁADOWA
IMPLEMENTACJA
<?php
class MadApiStub implements MadApiInterface
{
public function zamowieniaDoDostawcow(): array
{
Yii::debug('Pobieram dane z API MAD', __METHOD__);
return [
'status' => 'success',
'massage' => [],
];
}
}
PRZYKŁADOWA
IMPLEMENTACJA
<?php
//config-prod
$config['container']['definitions'] = [
'componentsMadApiInterface' => 'interfacesMadApi'
];
//config-dev
$config['container']['definitions'] = [
'componentsMadApiInterface' => 'interfacesMadApiStub'
];
class MadZamowienia extends yiiwebController
{
public function actionIndex()
{
/** @var MadService $mad */
$mad = Yii::createObject(MadService::class);
$zamowienia = $mad->zamowieniaDoDostawcow();
…
}
}
PRZYKŁADOWEUŻYCIE-YII2
<?php
//config-prod
return [
MadApiInterface::class => DIcreate(MadApi::class)
];
//config-dev
return [
MadApiInterface::class => DIcreate(MadApiStub::class)
];
//definicja kontenera np w bootstrapie aplikacji i integracja z frameworkiem
$container = (new DIContainerBuilder())
->addDefinitions('config.php')
->build();
class MadZamowienia extends Controller
{
public function actionIndex()
{
/** @var MadService $mad */
$mad = $container->get('MadService');
$zamowienia = $mad->zamowieniaDoDostawcow();
…
}
}
PRZYKŁADOWEUŻYCIE-PHP-
DI
JAKIE MA WADY ?
▸Ciężej zrozumieć jak działa klasa i skąd bierze zależności -
w szczególności dla młodych developerów
▸Obiekty są tworzone na początku działania aplikacji -
możliwe problemy z wydajnością*
ŹRÓDŁA, LITERATURA
▸https://wikipedia.org
▸https://stackoverflow.com/
▸Design Patterns: Elements of Reusable Object-Oriented
Software. The "Gang of Four": Erich Gamma, Richard
Helm, Ralph Johnson, John Vlissides
▸PHP Objects, Patterns and Practise, 5th Edition. Matt
Zandstra
▸Clean Code. Martin Robert C.
DZĘKUJE
SMJS

More Related Content

What's hot

Introduction to Java 8
Introduction to Java 8Introduction to Java 8
Introduction to Java 8Knoldus Inc.
 
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20Phil Wilkins
 
Tutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHPTutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHPAndrew Rota
 
Network programming in Java
Network programming in JavaNetwork programming in Java
Network programming in JavaTushar B Kute
 
Method Overloading in Java
Method Overloading in JavaMethod Overloading in Java
Method Overloading in JavaSonya Akter Rupa
 
Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...
Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...
Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...Edureka!
 
Java Programming - Polymorphism
Java Programming - PolymorphismJava Programming - Polymorphism
Java Programming - PolymorphismOum Saokosal
 
12 multi-threading
12 multi-threading12 multi-threading
12 multi-threadingAPU
 
Chapter 02: Classes Objects and Methods Java by Tushar B Kute
Chapter 02: Classes Objects and Methods Java by Tushar B KuteChapter 02: Classes Objects and Methods Java by Tushar B Kute
Chapter 02: Classes Objects and Methods Java by Tushar B KuteTushar B Kute
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesRay Toal
 

What's hot (20)

Graphql usage
Graphql usageGraphql usage
Graphql usage
 
Using Mockito
Using MockitoUsing Mockito
Using Mockito
 
Introduction to Java 8
Introduction to Java 8Introduction to Java 8
Introduction to Java 8
 
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
gRPC, GraphQL, REST - Which API Tech to use - API Conference Berlin oct 20
 
Parallel streams in java 8
Parallel streams in java 8Parallel streams in java 8
Parallel streams in java 8
 
Tutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHPTutorial: Building a GraphQL API in PHP
Tutorial: Building a GraphQL API in PHP
 
Test
TestTest
Test
 
Network programming in Java
Network programming in JavaNetwork programming in Java
Network programming in Java
 
Eloquent ORM
Eloquent ORMEloquent ORM
Eloquent ORM
 
Method Overloading in Java
Method Overloading in JavaMethod Overloading in Java
Method Overloading in Java
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
JDBC
JDBCJDBC
JDBC
 
Java Applet
Java AppletJava Applet
Java Applet
 
Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...
Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...
Lambda Expressions in Java | Java Lambda Tutorial | Java Certification Traini...
 
Java IO
Java IOJava IO
Java IO
 
Java 8 streams
Java 8 streamsJava 8 streams
Java 8 streams
 
Java Programming - Polymorphism
Java Programming - PolymorphismJava Programming - Polymorphism
Java Programming - Polymorphism
 
12 multi-threading
12 multi-threading12 multi-threading
12 multi-threading
 
Chapter 02: Classes Objects and Methods Java by Tushar B Kute
Chapter 02: Classes Objects and Methods Java by Tushar B KuteChapter 02: Classes Objects and Methods Java by Tushar B Kute
Chapter 02: Classes Objects and Methods Java by Tushar B Kute
 
Modeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based GamesModeling Patterns for JavaScript Browser-Based Games
Modeling Patterns for JavaScript Browser-Based Games
 

Similar to Wzorce projektowe w praktyce

Automatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHPAutomatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHPLaravel Poland MeetUp
 
Testy API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciTesty API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciThe Software House
 
Patronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 WarsztatyPatronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 Warsztatyintive
 
Using Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationUsing Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationMariusz Koprowski
 
Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Bartlomiej Zass
 
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)Codesushi.co (CODESUSHI LLC)
 
xD bug - Jak debugować PHP-owe aplikacje (Xdebug)
xD bug - Jak debugować PHP-owe aplikacje (Xdebug) xD bug - Jak debugować PHP-owe aplikacje (Xdebug)
xD bug - Jak debugować PHP-owe aplikacje (Xdebug) Laravel Poland MeetUp
 
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarkaThymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarkaMaciej Ziarko
 
Xdebug – debugowanie i profilowanie aplikacji PHP
Xdebug – debugowanie i profilowanie aplikacji PHPXdebug – debugowanie i profilowanie aplikacji PHP
Xdebug – debugowanie i profilowanie aplikacji PHP3camp
 
Metaprogramowanie w JS
Metaprogramowanie w JSMetaprogramowanie w JS
Metaprogramowanie w JSDawid Rusnak
 
ITAD PolSl 2014 - Nowości w .NET 2015
ITAD PolSl 2014 - Nowości w .NET 2015ITAD PolSl 2014 - Nowości w .NET 2015
ITAD PolSl 2014 - Nowości w .NET 2015Michał Dudak
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Cloudskraqa
 
Czym jest złożoność ?
Czym jest złożoność ?Czym jest złożoność ?
Czym jest złożoność ?GOG.com dev team
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariowaćJakub Marchwicki
 
Devbox - wirtualne środowisko pracy
Devbox - wirtualne środowisko pracyDevbox - wirtualne środowisko pracy
Devbox - wirtualne środowisko pracyMarek Bleschke
 
#3 Frontend Meetup - RequireJS
#3 Frontend Meetup - RequireJS#3 Frontend Meetup - RequireJS
#3 Frontend Meetup - RequireJSMaciej Grajcarek
 
WordUp Trójmiasto - Sage 9 w praktyce
WordUp Trójmiasto - Sage 9 w praktyceWordUp Trójmiasto - Sage 9 w praktyce
WordUp Trójmiasto - Sage 9 w praktyceDawid Urbański
 
Ganymede - nowoczesne technologie w grach przeglądarkowych i mobilnych
Ganymede - nowoczesne technologie w grach przeglądarkowych i mobilnychGanymede - nowoczesne technologie w grach przeglądarkowych i mobilnych
Ganymede - nowoczesne technologie w grach przeglądarkowych i mobilnychSKN Shader
 

Similar to Wzorce projektowe w praktyce (20)

Automatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHPAutomatyzacja utrzymania jakości w środowisku PHP
Automatyzacja utrzymania jakości w środowisku PHP
 
Testy API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięciTesty API: połączenie z bazą danych czy implementacja w pamięci
Testy API: połączenie z bazą danych czy implementacja w pamięci
 
Patronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 WarsztatyPatronage 2016 Windows 10 Warsztaty
Patronage 2016 Windows 10 Warsztaty
 
Using Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentationUsing Red Gate SQL Doc for database documentation
Using Red Gate SQL Doc for database documentation
 
Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)
 
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
Warsztaty: Podstawy PHP - część 2 - omówienie składni języka PHP (wersja 7)
 
xD bug - Jak debugować PHP-owe aplikacje (Xdebug)
xD bug - Jak debugować PHP-owe aplikacje (Xdebug) xD bug - Jak debugować PHP-owe aplikacje (Xdebug)
xD bug - Jak debugować PHP-owe aplikacje (Xdebug)
 
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarkaThymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
Thymeleaf - szablony, które bez przetworzenia zrozumie twoja przeglądarka
 
Xdebug – debugowanie i profilowanie aplikacji PHP
Xdebug – debugowanie i profilowanie aplikacji PHPXdebug – debugowanie i profilowanie aplikacji PHP
Xdebug – debugowanie i profilowanie aplikacji PHP
 
Metaprogramowanie w JS
Metaprogramowanie w JSMetaprogramowanie w JS
Metaprogramowanie w JS
 
ITAD PolSl 2014 - Nowości w .NET 2015
ITAD PolSl 2014 - Nowości w .NET 2015ITAD PolSl 2014 - Nowości w .NET 2015
ITAD PolSl 2014 - Nowości w .NET 2015
 
Michał Dec - Quality in Clouds
Michał Dec - Quality in CloudsMichał Dec - Quality in Clouds
Michał Dec - Quality in Clouds
 
Czym jest złożoność ?
Czym jest złożoność ?Czym jest złożoność ?
Czym jest złożoność ?
 
[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować[PL] Jak programować aby nie zwariować
[PL] Jak programować aby nie zwariować
 
Devbox - wirtualne środowisko pracy
Devbox - wirtualne środowisko pracyDevbox - wirtualne środowisko pracy
Devbox - wirtualne środowisko pracy
 
Behat
BehatBehat
Behat
 
Refaktoryzacja
RefaktoryzacjaRefaktoryzacja
Refaktoryzacja
 
#3 Frontend Meetup - RequireJS
#3 Frontend Meetup - RequireJS#3 Frontend Meetup - RequireJS
#3 Frontend Meetup - RequireJS
 
WordUp Trójmiasto - Sage 9 w praktyce
WordUp Trójmiasto - Sage 9 w praktyceWordUp Trójmiasto - Sage 9 w praktyce
WordUp Trójmiasto - Sage 9 w praktyce
 
Ganymede - nowoczesne technologie w grach przeglądarkowych i mobilnych
Ganymede - nowoczesne technologie w grach przeglądarkowych i mobilnychGanymede - nowoczesne technologie w grach przeglądarkowych i mobilnych
Ganymede - nowoczesne technologie w grach przeglądarkowych i mobilnych
 

More from PHPstokPHPstok

Jak ograniczyć używanie tablic w PHP.pptx
Jak ograniczyć używanie tablic w PHP.pptxJak ograniczyć używanie tablic w PHP.pptx
Jak ograniczyć używanie tablic w PHP.pptxPHPstokPHPstok
 
Blaski i cienie pracy Project Managera.pptx
Blaski i cienie pracy Project Managera.pptxBlaski i cienie pracy Project Managera.pptx
Blaski i cienie pracy Project Managera.pptxPHPstokPHPstok
 
Zarządzanie złożonością
Zarządzanie złożonościąZarządzanie złożonością
Zarządzanie złożonościąPHPstokPHPstok
 
Najczęstsze błędy początkujących programistów PHP
Najczęstsze błędy początkujących programistów PHPNajczęstsze błędy początkujących programistów PHP
Najczęstsze błędy początkujących programistów PHPPHPstokPHPstok
 
Bezpieczeństwo aplikacji webowych
Bezpieczeństwo aplikacji webowychBezpieczeństwo aplikacji webowych
Bezpieczeństwo aplikacji webowychPHPstokPHPstok
 
Sztuka samodoskonalenia programisty
Sztuka samodoskonalenia programistySztuka samodoskonalenia programisty
Sztuka samodoskonalenia programistyPHPstokPHPstok
 
Testy jednostkowe - PHPUnit
Testy jednostkowe - PHPUnitTesty jednostkowe - PHPUnit
Testy jednostkowe - PHPUnitPHPstokPHPstok
 
PSR czyli dobre praktyki programistyczne
PSR czyli dobre praktyki programistycznePSR czyli dobre praktyki programistyczne
PSR czyli dobre praktyki programistycznePHPstokPHPstok
 

More from PHPstokPHPstok (13)

Jak ograniczyć używanie tablic w PHP.pptx
Jak ograniczyć używanie tablic w PHP.pptxJak ograniczyć używanie tablic w PHP.pptx
Jak ograniczyć używanie tablic w PHP.pptx
 
Blaski i cienie pracy Project Managera.pptx
Blaski i cienie pracy Project Managera.pptxBlaski i cienie pracy Project Managera.pptx
Blaski i cienie pracy Project Managera.pptx
 
PHP 8.1
PHP 8.1PHP 8.1
PHP 8.1
 
Zarządzanie złożonością
Zarządzanie złożonościąZarządzanie złożonością
Zarządzanie złożonością
 
Clean Code
Clean CodeClean Code
Clean Code
 
Testy mutacyjne
Testy mutacyjneTesty mutacyjne
Testy mutacyjne
 
Najczęstsze błędy początkujących programistów PHP
Najczęstsze błędy początkujących programistów PHPNajczęstsze błędy początkujących programistów PHP
Najczęstsze błędy początkujących programistów PHP
 
Bezpieczeństwo aplikacji webowych
Bezpieczeństwo aplikacji webowychBezpieczeństwo aplikacji webowych
Bezpieczeństwo aplikacji webowych
 
Sztuka samodoskonalenia programisty
Sztuka samodoskonalenia programistySztuka samodoskonalenia programisty
Sztuka samodoskonalenia programisty
 
Testy jednostkowe - PHPUnit
Testy jednostkowe - PHPUnitTesty jednostkowe - PHPUnit
Testy jednostkowe - PHPUnit
 
Docker
DockerDocker
Docker
 
SOLID
SOLIDSOLID
SOLID
 
PSR czyli dobre praktyki programistyczne
PSR czyli dobre praktyki programistycznePSR czyli dobre praktyki programistyczne
PSR czyli dobre praktyki programistyczne
 

Wzorce projektowe w praktyce

  • 2. ▸Marek Keżel ▸Kierownik projektu autorskiego systemu ERP do zarządzania produkcją mebli tapicerowanych ▸Programista PHP, JS, Python ▸Linux, CCNA R&S, CCNA Sec O MNIE
  • 3. AGENDA ▸Czym jest wzorzec projektowy ? ▸Singleton - nikt go nie lubi ▸Simple Factory - tworzyć, prosto ▸Adapter - dopasowywać ▸Facade - upraszczać ▸Observer - powiadamiać ▸Dependency Injection - wstrzykiwać zależności
  • 5. In software engineering, a software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design. It is not a finished design that can be transformed directly into source or machine code. Rather, it is a description or template for how to solve a problem that can be used in many different situations. Wikipedia
  • 6. CZYM JEST WZORZEC PROJEKTOWY ▸Ogólnym rozwiązaniem często spotykanego problemu projektowego. ▸Szablonem rozwiązania problemu ▸Sformalizowanym elementem najlepszych praktyk programistycznych
  • 7. CZYM NIE JEST WZORZEC PROJEKTOWY ▸Gotową implementacją rozwiązania problemu którą możemy skopiować do naszego projektu ▸Szablonem rozwiązania w konkretnym języku*
  • 8. UWAGA! ▸Stosowanie wzorców projektowych “na siłę” jest anty wzorcem. ▸Jeżeli jest problem z dobraniem wzorca może lepiej odpuścić sobie stosowanie jakiekolwiek w tym kontekście. ▸Kod bez wzorców projektowych będzie działał*
  • 10. WZORCE PROJEKTOWE WG BANDY CZWORGA - KREACYJNE ▸Abstract Factory ▸Builder ▸Factory Method ▸Prototype ▸Singleton
  • 11. WZORCE PROJEKTOWE WG BANDY CZWORGA - STRUKTURALNE ▸Adapter ▸Bridge ▸Composite ▸Decorator ▸Facade ▸Flyweight ▸Proxy
  • 12. WZORCE PROJEKTOWE WG BANDY CZWORGA - CZYNNOŚCIOWE ▸Chain of Responsibility ▸Command ▸Interpreter ▸Iterator ▸Mediator ▸Memento ▸Observer ▸State ▸Strategy ▸Template Method ▸Visitor
  • 14. In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one "single" instance. This is useful when exactly one object is needed to coordinate actions across the system. Wikipedia
  • 15. W CZYM MOŻE POMÓC? ▸Jedna instancja klasy podczas działania aplikacji ▸Globalny dostęp do w/w instancji* ▸Ulepszona wersja zmiennej globalnej
  • 16. <?php class Logger { protected static $instance; private function __construct() {} private function __clone() {} private function __wakeup() {} public static function getInstance() { if (is_null(static::$instance)) { static::$instance = new static; } return static::$instance; } public function info($message, $category) { //zapisać do bazy danych } } PRZYKŁADOWA IMPLEMENTACJA
  • 17. <?php class Trello { protected static $instance; private function __construct() {} private function __clone() {} private function __wakeup() {} public static function getInstance() { if (is_null(static::$instance)) { static::$instance = new static; } return static::$instance; } public function dodajKarte($lista, $parametry) { //połączyć się z trello i dodać kartę do listy } } PRZYKŁADOWA IMPLEMENTACJA
  • 18. JAKIE MA WADY ? ANTYWZORZEC ? ▸Silne wiązania między kodem wykorzystującym singletona a nim samym poprzez dostęp globalny (wiązanie z kontekstem) ▸Ukrywanie zależności ▸Naruszenie zasad SOLID: Dependency Inversion Principle, Single Responsibility Principle ▸Testowanie, jak podmienić singletona na potrzeby testów. ▸Testy mogą zacząć być zależne od siebie. Jeżeli jeden test zmieni stan obiektu drugi może pracować na zmienionym już stanie a nie na początkowym.
  • 19. <?php class Zgloszenie extends ActiveRecord { public function create() { if ($this->save()) { Logger::getInstance()->info('Dodano zlgoszenie', __METHOD__); $this->wyslijPowiadomienie(); return true; } return false; } public function wyslijPowiadomienie() { Trello::getInstance()->dodajKarte('zgloszenia', [ 'zrodlo' => $this->zlodlo, 'temat' => $this->temat, 'tresc' => $this->tresc, ]); } } PRZYKŁADOWEUŻYCIE
  • 20. CO ZROBIĆ JEŻELI POTRZEBNA JEST TYLKO JEDNA INSTANCJA KLASY W APLIKACJI ? ▸Czy na pewno potrzebna jest tylko jedna instancja? ▸Użyć Dependency Injection ▸Użyć Service Locator* ▸Użyć świadomie singletona z pełną świadomością jego konsekwencji
  • 21. <?php class Zgloszenie extends ActiveRecord { protected $logger; protected $trello; public function __construct(LoggerInterface $logger, TrelloInterface $trello) { $this->logger = $logger; $this->trello = $trello; } public function create() { if ($this->save()) { $this->logger->info('Dodano zlgoszenie', __METHOD__); $this->wyslijPowiadomienie(); return true; } return false; } public function wyslijPowiadomienie() { $this->trello->dodajKarte('zgloszenia', [ 'zrodlo' => $this->zlodlo, 'temat' => $this->temat, 'tresc' => $this->tresc, ]); } } PRZYKŁADOWEUŻYCIE- ZAMIASTSINGLETONA-DI
  • 22. <?php $container = new yiidiContainer; $container->setSingleton('LoggerInterface', 'Logger'); $container->setSingleton('TrelloInterface', 'Trello'); $zgloszenie = $container->get('Zgloszenie'); PRZYKŁADOWEUŻYCIE- ZAMIASTSINGLETONA-DI
  • 23. DOSTEP GLOBALNY PRZYKŁADY ▸Yii2 - logger, komponenty, DI (Yii::error(), Yii::$app->user) ▸Laravel - helpery, facady (config(), view(), Cache::get())
  • 25. In object-oriented programming (OOP), a factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be "new". Wikipedia
  • 26. W CZYM MOŻE POMÓC? ▸Tworzenie obiektów z rodziny klas ze wspólnym interfejsem na podstawie parametru ▸Enkapsulacja procesu tworzenia obiektów - nie pokazujemy logiki procesu tworzenia ▸Uniknięcie warunkowych procesów tworzenia obiektów ▸Centralna lokalizacja tworzenia obiektów - łatwo zareagujemy np na zmiany wymaganych parametrów konstruktora ▸DRY
  • 27. <?php class ArtykulConverterFactory { public function createConverter(int $typ): ArtykulConverterInterface { switch ($typ) { case ZamowieniePozycje::TYP_LOZKO: return new LozkoConverter(); case ZamowieniePozycje::TYP_SZAFKA: return new SzafkaConverter(); case ZamowieniePozycje::TYP_PUFA: return new PufaConverter(); default: throw new IndeksException("Błędny typ artykułu"); } } } PRZYKŁADOWA IMPLEMENTACJA
  • 28. class IndeksFacade { protected $typ; protected $konwerterFactory; protected $service; public function __construct( int $typ, ArtykulConverterFactoryInterface $konwerterFactory, IndeksServiceInterface $service) { $this->typ = $typ; $this->konwerterFactory = $konwerterFactory; $this->service = $service; } public function utworzZKreatora($konfiguracjaZKreatora): Indeks { $konfiguracja = $this->getKonwerter()->zKreatora($konfiguracjaZKreatora); return $this->service->utworz($konfiguracja); } public function utworzZPozycji(AbstractPozycja $pozycja): Indeks { $konfiguracja = $this->getKonwerter()->zPozycji($pozycja); return $this->service->utworz($konfiguracja); } public function getKonwerter(): ArtykulConverterInterface { return $this->konwerterFactory->createConverter($this->typ); } } PRZYKŁADOWEUŻYCIE
  • 29. JAKIE MA WADY ? ▸Większa złożoność kodu ▸Większa ilość klas ▸Wersja simple factory łamię zasadę Open Close Principle (SOLID).
  • 30. <?php class ArtykulConverterFactory { public function createConverter(int $typ): ArtykulConverterInterface { $mapa = Yii::$app->params['mapaArtykulow']; if (!array_key_exists($typ, $mapa)) { throw new IndeksException("Błędny typ artykułu"); } $converterFQN = $mapa[$typ] . 'Converter'; return new $converterFQN; } } PRZYKŁADOWA IMPLEMENTACJA
  • 32. In software engineering, the adapter pattern is a software design pattern (also known as wrapper, an alternative naming shared with the decorator pattern) that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code. Wikipedia
  • 33. W CZYM MOŻE POMÓC? ▸Dopasowanie dwóch niekompatybilnych interfejsów ▸Przykrycie zewnętrznego kodu własnym interfejsem w celu jeszcze większego rozluźnienia zależności ▸Praca ze starym kodem i przystosowanie go do nowego interfejsu
  • 34. UWAGA! ▸Dwa typy Adaptera: klasowy oraz obiektowy ▸Adapter dwukierunkowy - każda z klas może pełnić funkcję zarówno klienta jak adaptowanej klasy ▸Kod kliencki nie wie czy pracuje z klasą docelową bezpośrednio czy za pośrednictwem adaptera z klasą z niekompatybilnym interfejsem
  • 35. <?php use TrelloClient; $client = new Client(); $client->authenticate( Yii::$app->params['trello_api_key'], Yii::$app->params['trello_token'], Client::AUTH_URL_CLIENT_ID); $client->cards()->create( array_merge($parametry, ['idList' => $listaID]) ); WYWOŁANIEBEZPOŚREDNIE KODUBIBLIOTEKI
  • 36. <?php class Trello extends Component implements TrelloInterface { public $apiKey; public $token; /** @var Client $client */ protected $client; public function __construct(Client $client, $config = []) { $this->client = $client; parent::__construct($config); } public function init() { parent::init(); $this->polacz(); } public function dodajKarteDoListy(string $listaID, array $parametry) { return $this->client->cards()->create( array_merge($parametry, ['idList' => $listaID]) ); } protected function polacz() { $this->client->authenticate($this->apiKey, $this->token, Client::AUTH_URL_CLIENT_ID); } } PRZYKŁADOWA IMPLEMENTACJA
  • 38. JAKIE MA WADY ? ▸Większe skomplikowanie kodu ▸Zbyt częste tworzenie adapterów nawet jeśli nie jest to wymagane
  • 40. The facade pattern is a software-design pattern commonly used in object-oriented programming. Analogous to a facade in architecture, a facade is an object that serves as a front-facing interface masking more complex underlying or structural code. Wikipedia
  • 41. W CZYM MOŻE POMÓC? ▸Ułatwienie korzystania z rozbudowanego, skomplikowanego interfejsu biblioteki, komponentu ▸Podział na warstwy ▸Czytelniejszy kod klienta ▸Niezależny rozwój złożonego systemu schowanego za fasadą - klient ma stały interfejs fasady.
  • 42. $konwerter = (new ArtykulConverterFactory())->createConverter($typArtykulu); $konfiguracja = $konwerter->zKreatora($konfiguracjaZKreatora); $service = new IndeksService($this->typ, new IndeksArtykulModelFactory()); $indeks = $this->service->utworz($konfiguracja); …… $konwerter = (new ArtykulConverterFactory())->createConverter($pozycja->typ); $konfiguracja = $konwerter->zZamowieniePozycje($pozycja); $service = new IndeksService($this->typ, new IndeksArtykulModelFactory()); $indeks = $this->service->utworz($konfiguracja); PRZYKŁADOWYPROCES GENEROWANIAINDEKSUARTYKULU
  • 43. class IndeksFacade { protected $typ; protected $konwerterFactory; protected $service; public function __construct( int $typ, ArtykulConverterFactoryInterface $konwerterFactory, IndeksServiceInterface $service) { $this->typ = $typ; $this->konwerterFactory = $konwerterFactory; $this->service = $service; } public function utworzZKreatora($konfiguracjaZKreatora): Indeks { $konfiguracja = $this->getKonwerter()->zKreatora($konfiguracjaZKreatora); return $this->service->utworz($konfiguracja); } public function utworzZPozycji(AbstractPozycja $pozycja): Indeks { $konfiguracja = $this->getKonwerter()->zPozycji($pozycja); return $this->service->utworz($konfiguracja); } public function getKonwerter(): ArtykulConverterInterface { return $this->konwerterFactory->createConverter($this->typ); } } PRZYKŁADOWA IMPLEMENTACJA
  • 46. JAKIE MA WADY ? ▸Może się stać klasą-bogiem - posiadać silne powiązanie z bardzo dużą ilością innych klas aplikacji
  • 48. The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. Wikipedia
  • 49. W CZYM MOŻE POMÓC? ▸Powiadomienie zainteresowanych obiektów o zmianie stanu innego obiektu ▸Implementacja powiadomień (events)
  • 50. class ObserverA implements SplObserver { public function update(SplSubject $subject) { echo 'Aktualizacja ' . __CLASS__ . PHP_EOL; } } class ObserverB implements SplObserver { public function update(SplSubject $subject) { echo 'Aktualizacja ' . __CLASS__ . PHP_EOL; } } class Subject implements SplSubject { protected $observers = []; public function attach(SplObserver $observer) { $this->observers[spl_object_hash($observer)] = $observer; } public function detach(SplObserver $observer) { unset($this->observers[spl_object_hash($observer)]); } public function notify() { foreach ($this->observers as $observer) { $observer->update($this); } } } PRZYKŁADOWA IMPLEMENTACJA
  • 51. $subject = new Subject(); $observerA = new ObserverA(); $observerB = new ObserverB(); $subject->attach($observerA); $subject->attach($observerB); $subject->notify(); // Aktualizacja ObserverA // Aktualizacja ObserverB PRZYKŁADOWEUŻYCIE
  • 52. <?php class TrelloNotyfikatorHandler implements NotyfikatorHandlerInterface { public function wyslij(MessageEvent $event) { Yii::createObject(Trello::class) ->dodajKarteDoListy('zgloszenia', $event->message); } } class Zgloszenie extends ActiveRecord { const NOWE_ZGLOSZENIE_EVENT = 'noweZgloszenie'; public function create() { if ($this->save()) { $this->trigger(self::NOWE_ZGLOSZENIE_EVENT, new MessageEvent([ 'message' => 'Nowe zgłoszenie o treści: ' . $this->tresc ])); return true; } return false; } } PRZYKŁADOWA IMPLEMENTACJA-YII2
  • 53. class ZgloszenieController extends yiiwebController { protected $notyfikator; public function __construct($id, $module, $config = [], NotyfikatorHandlerInterface $notyfikator) { $this->notyfikator = $notyfikator; parent::__construct($id, $module, $config); } public function actionCreate() { $model = new Zgloszenie(); $model->on(Zgloszenie::NOWE_ZGLOSZENIE_EVENT, [ $this->notyfikator, 'wyslij' ]); $model->create(); } } PRZYKŁADOWEUŻYCIE-YII2
  • 54. <?php return [ Watek::class . '@' . Watek::EVENT_NOWY_WATEK_DO_ADMINA => [ TrelloNotyfikatorHandler::class, EmailNotyfikatorHandler::class, PushNotyfikatorHandler::class, ], Zlecenie::class . '@' . Zlecenie::EVENT_AFTER_INSERT => [ NoweZlecenieHandler::class, ], Zlecenie::class . '@' . Zlecenie::EVENT_AFTER_PRZYJECIE => [ PrzyjecieZleceniaHandler::class, ], ]; … yiibaseEvent::on(Watek::class, Watek::EVENT_NOWY_WATEK_DO_ADMINA, [ TrelloNotyfikatorHandler::class, 'handle' ]); DEFINICJAOBSERWATORÓW NAPOZIOMIEKLAS
  • 55. $foo = new Foo(); // this handler is a global function $foo->on(Foo::EVENT_HELLO, 'function_name'); // this handler is an object method $foo->on(Foo::EVENT_HELLO, [$object, 'methodName']); // this handler is a static class method $foo->on(Foo::EVENT_HELLO, ['appcomponentsBar', 'methodName']); // this handler is an anonymous function $foo->on(Foo::EVENT_HELLO, function ($event) { // event handling logic }); YII2EVENTSDOKUMENTACJA-PRZYKŁAD REJESTRACJIOBSERWATORÓW
  • 56. JAKIE MA WADY ? ▸Obserwatorzy nie znają innych obserwatorów ▸Kolejność powiadamiania jest niezależna
  • 58. In software engineering, dependency injection is a technique whereby one object supplies the dependencies of another object. A "dependency" is an object that can be used, for example as a service. Instead of a client specifying which service it will use, something tells the client what service to use. Wikipedia
  • 59. W CZYM MOŻE POMÓC? ▸Usunięcie sztywnych odwołań z kodu klas ▸Rozluźnienie powiązań miedzy klasami. ▸SOLID: Dependency Inversion Principle ▸Oddzielenie procesu tworzenia obiektu od jego użycia ▸Ułatwienie testowanie kodu, podmiana zależności ▸Konfiguracja interfejsów programu za pomocą plików konfiguracyjnych
  • 60. UWAGA! ▸Dependency Injection jest jednym ze sposób implementacji Inversion of Control poprzez wstrzykiwanie zależności z poziomu: konstruktora, settera lub metody ▸IoC jest paradygmatem programowania polegającym na odwróceniu kontroli. Zamiast samemu kontrolować kod frameworka, oddajemy kontrolę naszego kodu dla tego właśnie frameworka (w tym przypadku kontrolę nad tworzeniem obiektów) ▸Dependency Injection Container jest biblioteką dostarczają funkcjonalność DI, która implementuje np. Tworzenie map zależności między interfejsami a ich konkretnymi implementacjami, odczytywanie zależności poprzez użycie Refleksji
  • 61. IMPLEMENTACJE W PHP ▸Symfony Dependency Injection Component ▸Laravel Service Container ▸Yii2 Dependency Injection Container ▸PHP-DI (php-di.org)
  • 62. <?php class MadService extends BaseObject { protected $api; public function __construct($config = []) { $this->api = new MadApi(); parent::__construct($config); } public function zamowieniaDoDostawcow() { return $this->api->zamowieniaDoDostawcow(); } } PRZYKŁADOWA IMPLEMENTACJA
  • 63. <?php class MadService extends BaseObject { protected $api; public function __construct(MadApiInterface $api, $config = []) { $this->api = $api; parent::__construct($config); } public function zamowieniaDoDostawcow() { return $this->api->zamowieniaDoDostawcow(); } } PRZYKŁADOWA IMPLEMENTACJA
  • 64. <?php interface MadApiInterface { public function zamowieniaDoDostawcow(): array; } PRZYKŁADOWA IMPLEMENTACJA
  • 65. <?php class MadApi implements MadApiInterface { const SOAP_SERVER_LOGIN = ‘’; protected $client; public function zamowieniaDoDostawcow(): array { $result = $this->client->ZdDocListGet([ 'ZdDocListGetData' => [ 'ClientCode' => self::SOAP_SERVER_LOGIN, ], ]); if ($result->ArrayZdDocListGetResult->Status !== 1) { return [ 'status' => 'error', 'massage' => $result->ArrayZdDocListGetResult->ErrorMessage, ]; } return [ 'status' => 'success', 'massage' => $result->ArrayZdDocListGetResult->ZdDocListGetResult, ]; } } PRZYKŁADOWA IMPLEMENTACJA
  • 66. <?php class MadApiStub implements MadApiInterface { public function zamowieniaDoDostawcow(): array { Yii::debug('Pobieram dane z API MAD', __METHOD__); return [ 'status' => 'success', 'massage' => [], ]; } } PRZYKŁADOWA IMPLEMENTACJA
  • 67. <?php //config-prod $config['container']['definitions'] = [ 'componentsMadApiInterface' => 'interfacesMadApi' ]; //config-dev $config['container']['definitions'] = [ 'componentsMadApiInterface' => 'interfacesMadApiStub' ]; class MadZamowienia extends yiiwebController { public function actionIndex() { /** @var MadService $mad */ $mad = Yii::createObject(MadService::class); $zamowienia = $mad->zamowieniaDoDostawcow(); … } } PRZYKŁADOWEUŻYCIE-YII2
  • 68. <?php //config-prod return [ MadApiInterface::class => DIcreate(MadApi::class) ]; //config-dev return [ MadApiInterface::class => DIcreate(MadApiStub::class) ]; //definicja kontenera np w bootstrapie aplikacji i integracja z frameworkiem $container = (new DIContainerBuilder()) ->addDefinitions('config.php') ->build(); class MadZamowienia extends Controller { public function actionIndex() { /** @var MadService $mad */ $mad = $container->get('MadService'); $zamowienia = $mad->zamowieniaDoDostawcow(); … } } PRZYKŁADOWEUŻYCIE-PHP- DI
  • 69. JAKIE MA WADY ? ▸Ciężej zrozumieć jak działa klasa i skąd bierze zależności - w szczególności dla młodych developerów ▸Obiekty są tworzone na początku działania aplikacji - możliwe problemy z wydajnością*
  • 70. ŹRÓDŁA, LITERATURA ▸https://wikipedia.org ▸https://stackoverflow.com/ ▸Design Patterns: Elements of Reusable Object-Oriented Software. The "Gang of Four": Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides ▸PHP Objects, Patterns and Practise, 5th Edition. Matt Zandstra ▸Clean Code. Martin Robert C.

Editor's Notes

  1. Zanim przejdę dalej chciałbym odnieść się do prezentacji koleżanki. Senior developer rozwija się między innymi poprzez dzielenie się więdzą. Ja ten wykład potraktuję jako sprawdzian czy się nadaje do tego.
  2. Wybrałem te wzorce (oprócz Singletona) ponieważ najczęściej są spotykane w mojej pracy oraz są bardzo popularne w PHPie wg danych z internetu Temat wzorców zostanie zaprezentowany w sposób praktyczny z mojego punktu widzenia Nie będzie definicji stricte akademickich i UMLi Treść tego wykładu kieruje do programistów którzy chcą zacząć swoją przygodę z wzorcami lub ją zaczęli ale mają problemy z ich stosowaniem Wzorce otaczają nas praktycznie na każdym kroku. Jeżeli używamy jakiegolwiek topowego frameworka w PHP to używamy tam świadomie bądź mniej zaimplementowanych wzorców projektowych (Yii2, Laravel, Symfony) !!! Nie mów tego Pominąłem świadomie jeden bardzo ważny wzorzec Strategy ponieważ uważam że powinno się go omówić bardzo dokładnie przez potrzeba o wile więcej czasu
  3. 30 sekund
  4. Wzorzec wg GoF składa się z czterech elementów: nazwy wzorca, problemu, rozwiązania, konsekwencji Dobre praktyki jak SOLID KISS DRY idą w parze właśnie z wzorcami projektowymi
  5. Implementacje wzorców różnią się w stosunku do różnych języków programowania.
  6. Na koniec wykładu pokażę Wam controller z naszego projektu a propo braku dobrych praktyk :) Tak samo jak bez innych dobrych praktyk tylko jak łatwo będzie go utrzymywać, testować to już inna kwestia
  7. Wzorce projektowe tzw Bandy Czworga ogólnie są uważana za podstawę dla wszystkich innych wzorców. Dla tego moją prezentacją w pewnej części opieram właśnie o ich definicje Wzorce projektowe zostały spopularyzowane w 1995 (copyright) przez Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson oraz John Vlissides) dzięki książce Wzorce projektowe: Elementy oprogramowania obiektowego wielokrotnego użytku Wzorce zostały zdefiniowane i opisane na podstawie języków silnie typowany, zorientowanych obiektowo (C++, Java, C#…) Słowa krytyki Wzorce projektowe rozwiązują słabości języka programowania więc dla czego nie zmienić właśnie języka ? Peter Norvig - powiedział że 16 z 23 wzorców (skupionych na C++) mogą zostać wyeliminowane poprzez zmianę języka
  8. Definiują proces tworzenia nowych obiektów oraz ich konfiguracji
  9. Definiują struktury powiązanych ze sobą obiektów
  10. Definiują zachowanie i odpowiedzialność współpracujących ze sobą wzorców
  11. Zanim przejdziemy dalej chciałbym powiedzieć, że na prawdę miałem problemy z znalezieniem własnych przykładów ponieważ praktycznie nie stosuję tego wzorca a korzystam z niego z dostarczonych bibliotek / frameworków
  12. Konstruktor - blokujemy możliwość tworzenia instancji w tradycyjny sposób Clone - blokujemy możliwość klonowania obiektu Wakeup - blokujemy możliwość powstania nowej instancji podczas deserializacji obiektu
  13. Single Responsibility Principle - klasa ma mieć jeden powód do zmiany i tylko jeden Dependency Inversion Principle - Moduły wyższego poziomu nie powinny zależeć od modułów niższego poziomu a od abstrakcji. Klasy mają być zależne od abstrakcji nie od konkretów
  14. Logger odwołuje się do bazy w testach mamy problem Trello odwołuje się do serwerów trello podczas prac developerskich możemy tworzyć niechciane karty Jak wykonać test jednostkowy metody create() w izolowanym środowisku MOKI
  15. 3) Yii::error(), Yii::info() Service locator również powoduje dostęp globalny ale umożliwia podmianę implementacji metody getta do komponentów
  16. 3) Yii::error(), Yii::info()
  17. Simple factory nie jest wymieniony w zestawieniu GoF Oficjalnymi wzorcami wytwórców są: Factory Method oraz Abstract Factory Część developerów uważa, że nie jest to wzorzec projektowy
  18. Enkapsulacja (hermetyzacją) Ograniczanie bezpośredniego dostępu do danych i logiki obiektów Wiązanie danych z metodami (funkcjami) operującymi na tych danych
  19. Konwertują różne struktury przechowywania parametrów artykułów na jeden wspólny. Każdy artykuł ma unikalny zestaw parametrów oraz wykonuje różne akcje aby zwrócić pożądany parametr w danym formacie.
  20. Open Close Principle - Klasa powinna być otwarta na rozszerzenia lecz zamknięta na modyfikacje Kiedy mamy nowy typ np. Artykułu musimy edytować kod i dodać nową opcję do switch’a
  21. Adapter obiektowy wykorzystuje kompozycje. Klasowy wykorzystuje dziedziczenie is-a a obiektowy kompozycje has-a
  22. $client jest obiektem adaptowanym do interfejsu TrelloInterface
  23. Obserwatorzy mogą obserwować ale nie muszą
  24. SPL - Standard PHP Library Podczas powiadamiania obserwatorzy otrzymują także referencję do obiektu obserwowanego. Jeden obserwator może obserwować kilka innych obiektów, a jeden obiekt obserwowany może być obserwowany przez kilku obserwatorów. Deklarujemy klasy obserwatorów (observer, listener) Deklarujemy klasę obserwowaną (subject) Implementujemy metody dodawania usuwania i powiadamiania obserwatorów z poziomu klasy obserwowanej
  25. TrelloNotifikatorHandler to jest nasz obserwator Zgloszenie jest obiektem obserwowanym Metoda trigger == notify z SPL Różnica w implementacji: metoda notify z SPLSubject przekazywała do każdego wywołania update obserwatora referencję do swojej instancji (obserwowanego obiektu) Yii2 do obserwatorów przekazuje obiekt Event który posiada referencje do obiektu obserwowanego (w tym przypadku Zgłoszenie) w parametrze sender. Klasa Event została rozszrzona o parametr message aby był wspólny dla calej rodziny klas Notyfikatorów
  26. Metoda modelu ON == attach (detach == Yii OFF)
  27. Rejestrowanie obserwatorów na poziomie klas a nie obiektów
  28. Tylko jeden sposób jest najbardziej zbliżony do oryginalnego sposobu dołączania obserwatorów do obserwowanego obiektu.
  29. Dependency Inversion Principle: klasy wyższego poziomu nie powinny zależeć od klas niższego poziomu tylko od abstrakcji
  30. PHP DI od wersji 6 tworzy zależności i przechowuje ich jedne instancje tak jak singleton Get zwraca singletona, make - tworzy go za każdym razem
  31. Mozna tak skonfigurować Di aby tworzyło wszystkie zależności przed ich zapotrzebowaniem EAGER LAZY - na żądanie