D R S T R A N G L E R
& M R H Y P E
S T R A N G L E R P A T T E R N W P R A K T Y C E
Michał Kurzeja
CTO @ Accesto
@michalKurzeja
michal@accesto.com
O C Z Y M ?
• Skąd bierze się Legacy?
• Dlaczego warto się go pozbyć?
• Jak dobrze podejść do tematu, skąd czerpać wiedzę?
• Jak nie zrobić sobie krzywdy?
• Przykłady
O C Z Y M N I E ?
• Jak testować
• Jak refaktoryzować kod
• Przepis krok-po-kroku
Złe praktyki
„Mr Hype”
Dobre praktyki
„Dr Strangler”
L E G A C Y C O D E
L E G A C Y ! = K O D
O D Z I E D Z I C Z O N Y
O C Z E K I W A N I A
R Z E C Z Y W I S T O S Ć
J A K O Ś Ć M A L E J E Z C Z A S E M
- B R A K „ B O Y S C O U T ” R U L E
0
17.5
35
52.5
70
87.5
2010 2011 2012 2013
E F E K T ? P R O B L E M Y :
• Skomplikowany kod
• Utrudnione testowe
• Utrudniony deployment
• Niechęć programistów
• Blokada w rozwoju
J A K P R Z E K O N A Ć B I Z N E S ?
• Spowolniony rozwój
• konkurencja nie śpi
• większe koszty
• Utrudniona rekrutacja, większa fluktuacja kadr
• Dużo błędów, zirytowani klienci
• Możliwa katastrofa…
2 0 1 2 , K N I G H T C A P I T A L G R O U P
$460 mln strat w 45 minut
J A K I E M A M Y W Y J Ś C I A ?
P R Z E P I S A Ć O D Z E R A ?
O D 9 0 % R Y N K U
D O U P A D K U
U P A D E K N E T S C A P E
W Y P R Z E D Z O N Y P R Z E Z I E !
O L A Ć ?
R E F A K T O R Y Z O W A Ć ?
Przepisać od zeraOlać
Refaktoryzować UDUSIĆ
S T R A N G L E R P A T T E R N
G A T E W A Y / F A C A D E
G A T E W A Y - N A J P R O Ś C I E J
server {
listen 80;
server_name domain.com;
location /profile {
proxy_pass http://10.0.3.10:80;
}
location /news {
proxy_pass http://10.0.3.10:80;
}
proxy_pass http://10.0.3.20:80;
}
G A T E W A Y - D O S T Ę P N E
R O Z W I Ą Z A N I A
• API - Open Source
• Tyk
• Kong
• API - Płatne
• AWS API Gateway
• WWW
• HaProxy
• Nginx/Apache/…
Z A C Z Y N A M Y O D C A T C H
A L L
W S P Ó L N A B A Z A D A N Y C H
D I S T R I B U T E D S H I T
O S O B N E B A Z Y D A N Y C H
• Synchronizacja cykliczna
• Zdarzenia (wymaga zmian w Legacy)
• DB Triggers
• Transaction log (Binlog -> Kafka)
A P I
B O U N D A R I E S
ANTI-CORRUPTION LAYER
A C L
L E G A C Y I N A B O X
W P R A K T Y C E
D A W N O D A W N O T E M U
• Lider w swojej branży
• Projekt od 2010, przejęliśmy w 2016
• Klienci: banki, partie - nikt kto akceptuje downtime ;)
B R A K F R O N T - C O N T R O L L E R A
„ U R O C Z E ” W E R S J O N O W A N I E
„ M A G I C Z N A ” S T R U K T U R A
„ K U L O O D P O R N A ”
Tu było $_SERVER[SERVER_NAME]
„ C Z Y T E L N Y ” K O D
Generalnie….
K I L K A S I W Y C H W Ł O S Ó W
P Ó Ź N I E J
• Monorepo
• Apache jako fasada
• Anti-Corruption Layer -> API
• JSON Web Token
• Konfiguracja przez zmienne środowiskowe
• 100% Automatyzacja deploymentu
• Biznes zachwycony
• Programiści żyją
W P A D K I
C O M O Ż N A B Y Ł O Z R O B I Ć L E P I E J
F E A T U R E T O G G L E
O D P O C Z Ą T K U J W T
L E P S Z Y A C L
P R O B L E M Y
Z A L E T Y
• Mniejsze ryzyko, mniejszy stres, szybkie release
• Natychmiastowe efekty
• Zadowolony klient i programiści
P O D E J Ś C I E D R U G I E -
A C L ** T R O C H Ę W A R I A C J A
M O D E R N A C L L E G A C Y
b.com/VaughnVernon/IDDD_Samples/tree/master/iddd_collaboration/src/main/java/com/saasovation/collaboration/port/ada
M O D E R N A C L L E G A C Y
APIREPO
class Currency
{
private $isoCode;
private $default;
private $ratio;
}
M O D E R N - C U R R E N C Y M O D E L
interface CurrencyRepository
{
public function findAll();
public function getDefault();
public function find(string $isoCode);
public function save(Currency $currency);
}
M O D E R N - C U R R E N C Y
R E P O S I T O R Y
class Internal_CurrencyController extends Internal_Controller_InternalController
{
public function listcurrenciesAction()
{
$this->checkIp();
$this->getResponse()->setHeader('Content-type', 'application/json');
$mCurrency = new Default_Model_Currency();
/** @var Zend_Db_Table_Rowset $currencies */
$currencies = $mCurrency->fetchAll('status = "active"');
$this->getResponse()
->setBody(json_encode($currencies->toArray()))
->setHttpResponseCode(200);
}
}
L E G A C Y - C U R R E N C Y F A C A D E
interface CurrencyAdapter
{
public function findAll(): array;
}
A C L - C U R R E N C Y A P I
I N T E R F A C E
class LegacyCurrencyAdapter implements CurrencyAdapter
{
public function findAll(): array
{
$response = $this->client->request('GET', 'listCurrencies');
$currencies = json_decode((string) $response->getBody(), true);
return array_map(function ($row) {
$currency = $this->currencyTranslator->createFromArray($row);
if ($exCurrency = $this->currRepo->find($currency->isoCode())) {
$currency->setRatio($exCurrency->getRatio());
$currency->setDefault($exCurrency->getDefault());
}
return $currency;
}, $currencies);
}
}
A C L - C U R R E N C Y A P I
class LegacyCurrencyTranslator implements CurrencyTranslator
{
public function createFromArray(array $data)
{
$default = filter_var($data['default'], FILTER_VALIDATE_BOOLEAN);
$ratio = filter_var($data['value'], FILTER_VALIDATE_FLOAT);
return new Currency($data['code'], $ratio, $default);
}
}
A C L - C U R R E N C Y T R A N S L A T O R
J A K N I E R O B I Ć
R O U T I N G W L E G A C Y
B R A K A N T I - C O R R U P T I O N L A Y E R
L E P I E J N A J P I E R W
P L A N O W A Ć , P O T E M
K O D Z I Ć
GETTING STARTED WITH DDD WHEN SURROUNDED
BY LEGACY SYSTEMS
E R I C E V A N S
P I S Z C I E S O F T W A R E
Ł A T W Y D O U D U S Z E N I A
Michał Kurzeja
CTO @ Accesto
@michalKurzeja
michal@accesto.com
Dzięki!
Dr Strangler and Mr Hype - Strangler pattern w praktyce

Dr Strangler and Mr Hype - Strangler pattern w praktyce

  • 1.
    D R ST R A N G L E R & M R H Y P E S T R A N G L E R P A T T E R N W P R A K T Y C E
  • 2.
    Michał Kurzeja CTO @Accesto @michalKurzeja michal@accesto.com
  • 4.
    O C ZY M ? • Skąd bierze się Legacy? • Dlaczego warto się go pozbyć? • Jak dobrze podejść do tematu, skąd czerpać wiedzę? • Jak nie zrobić sobie krzywdy? • Przykłady
  • 5.
    O C ZY M N I E ? • Jak testować • Jak refaktoryzować kod • Przepis krok-po-kroku
  • 6.
    Złe praktyki „Mr Hype” Dobrepraktyki „Dr Strangler”
  • 7.
    L E GA C Y C O D E
  • 9.
    L E GA C Y ! = K O D O D Z I E D Z I C Z O N Y
  • 10.
    O C ZE K I W A N I A
  • 11.
    R Z EC Z Y W I S T O S Ć
  • 12.
    J A KO Ś Ć M A L E J E Z C Z A S E M - B R A K „ B O Y S C O U T ” R U L E 0 17.5 35 52.5 70 87.5 2010 2011 2012 2013
  • 13.
    E F EK T ? P R O B L E M Y : • Skomplikowany kod • Utrudnione testowe • Utrudniony deployment • Niechęć programistów • Blokada w rozwoju
  • 14.
    J A KP R Z E K O N A Ć B I Z N E S ? • Spowolniony rozwój • konkurencja nie śpi • większe koszty • Utrudniona rekrutacja, większa fluktuacja kadr • Dużo błędów, zirytowani klienci • Możliwa katastrofa…
  • 15.
    2 0 12 , K N I G H T C A P I T A L G R O U P $460 mln strat w 45 minut
  • 16.
    J A KI E M A M Y W Y J Ś C I A ?
  • 17.
    P R ZE P I S A Ć O D Z E R A ?
  • 18.
    O D 90 % R Y N K U D O U P A D K U U P A D E K N E T S C A P E W Y P R Z E D Z O N Y P R Z E Z I E !
  • 19.
    O L AĆ ?
  • 20.
    R E FA K T O R Y Z O W A Ć ?
  • 21.
  • 22.
    S T RA N G L E R P A T T E R N
  • 29.
    G A TE W A Y / F A C A D E
  • 30.
    G A TE W A Y - N A J P R O Ś C I E J server { listen 80; server_name domain.com; location /profile { proxy_pass http://10.0.3.10:80; } location /news { proxy_pass http://10.0.3.10:80; } proxy_pass http://10.0.3.20:80; }
  • 31.
    G A TE W A Y - D O S T Ę P N E R O Z W I Ą Z A N I A • API - Open Source • Tyk • Kong • API - Płatne • AWS API Gateway • WWW • HaProxy • Nginx/Apache/…
  • 32.
    Z A CZ Y N A M Y O D C A T C H A L L
  • 34.
    W S PÓ L N A B A Z A D A N Y C H
  • 35.
    D I ST R I B U T E D S H I T
  • 36.
    O S OB N E B A Z Y D A N Y C H • Synchronizacja cykliczna • Zdarzenia (wymaga zmian w Legacy) • DB Triggers • Transaction log (Binlog -> Kafka)
  • 37.
  • 39.
    B O UN D A R I E S
  • 40.
  • 41.
  • 48.
    L E GA C Y I N A B O X
  • 51.
    W P RA K T Y C E
  • 52.
    D A WN O D A W N O T E M U • Lider w swojej branży • Projekt od 2010, przejęliśmy w 2016 • Klienci: banki, partie - nikt kto akceptuje downtime ;)
  • 53.
    B R AK F R O N T - C O N T R O L L E R A
  • 54.
    „ U RO C Z E ” W E R S J O N O W A N I E
  • 55.
    „ M AG I C Z N A ” S T R U K T U R A
  • 56.
    „ K UL O O D P O R N A ” Tu było $_SERVER[SERVER_NAME]
  • 57.
    „ C ZY T E L N Y ” K O D
  • 58.
  • 59.
    K I LK A S I W Y C H W Ł O S Ó W P Ó Ź N I E J
  • 60.
    • Monorepo • Apachejako fasada • Anti-Corruption Layer -> API • JSON Web Token • Konfiguracja przez zmienne środowiskowe
  • 62.
    • 100% Automatyzacjadeploymentu • Biznes zachwycony • Programiści żyją
  • 63.
    W P AD K I C O M O Ż N A B Y Ł O Z R O B I Ć L E P I E J
  • 64.
    F E AT U R E T O G G L E
  • 65.
    O D PO C Z Ą T K U J W T
  • 66.
    L E PS Z Y A C L
  • 67.
    P R OB L E M Y
  • 68.
    Z A LE T Y • Mniejsze ryzyko, mniejszy stres, szybkie release • Natychmiastowe efekty • Zadowolony klient i programiści
  • 69.
    P O DE J Ś C I E D R U G I E - A C L ** T R O C H Ę W A R I A C J A
  • 70.
    M O DE R N A C L L E G A C Y b.com/VaughnVernon/IDDD_Samples/tree/master/iddd_collaboration/src/main/java/com/saasovation/collaboration/port/ada
  • 71.
    M O DE R N A C L L E G A C Y APIREPO
  • 72.
    class Currency { private $isoCode; private$default; private $ratio; } M O D E R N - C U R R E N C Y M O D E L
  • 73.
    interface CurrencyRepository { public functionfindAll(); public function getDefault(); public function find(string $isoCode); public function save(Currency $currency); } M O D E R N - C U R R E N C Y R E P O S I T O R Y
  • 74.
    class Internal_CurrencyController extendsInternal_Controller_InternalController { public function listcurrenciesAction() { $this->checkIp(); $this->getResponse()->setHeader('Content-type', 'application/json'); $mCurrency = new Default_Model_Currency(); /** @var Zend_Db_Table_Rowset $currencies */ $currencies = $mCurrency->fetchAll('status = "active"'); $this->getResponse() ->setBody(json_encode($currencies->toArray())) ->setHttpResponseCode(200); } } L E G A C Y - C U R R E N C Y F A C A D E
  • 75.
    interface CurrencyAdapter { public functionfindAll(): array; } A C L - C U R R E N C Y A P I I N T E R F A C E
  • 76.
    class LegacyCurrencyAdapter implementsCurrencyAdapter { public function findAll(): array { $response = $this->client->request('GET', 'listCurrencies'); $currencies = json_decode((string) $response->getBody(), true); return array_map(function ($row) { $currency = $this->currencyTranslator->createFromArray($row); if ($exCurrency = $this->currRepo->find($currency->isoCode())) { $currency->setRatio($exCurrency->getRatio()); $currency->setDefault($exCurrency->getDefault()); } return $currency; }, $currencies); } } A C L - C U R R E N C Y A P I
  • 77.
    class LegacyCurrencyTranslator implementsCurrencyTranslator { public function createFromArray(array $data) { $default = filter_var($data['default'], FILTER_VALIDATE_BOOLEAN); $ratio = filter_var($data['value'], FILTER_VALIDATE_FLOAT); return new Currency($data['code'], $ratio, $default); } } A C L - C U R R E N C Y T R A N S L A T O R
  • 78.
    J A KN I E R O B I Ć
  • 79.
    R O UT I N G W L E G A C Y
  • 80.
    B R AK A N T I - C O R R U P T I O N L A Y E R
  • 81.
    L E PI E J N A J P I E R W P L A N O W A Ć , P O T E M K O D Z I Ć
  • 82.
    GETTING STARTED WITHDDD WHEN SURROUNDED BY LEGACY SYSTEMS E R I C E V A N S
  • 84.
    P I SZ C I E S O F T W A R E Ł A T W Y D O U D U S Z E N I A
  • 85.
    Michał Kurzeja CTO @Accesto @michalKurzeja michal@accesto.com Dzięki!