O tym jak w bezpieczny sposób pozbyć się legacy w projekcie - nie narażając biznesu, ani zdrowia psychicznego programistów. Strangler Pattern z praktycznego punktu widzenia - co zadziałało, a gdzie popełniliśmy błędy.
Źródła:
Whitepaper Evansa: http://domainlanguage.com/wp-content/uploads/2016/04/GettingStartedWithDDDWhenSurroundedByLegacySystemsV1.pdf
Case Studies: https://paulhammant.com/2013/07/14/legacy-application-strangulation-case-studies/
Implementacja z książki Vernona: https://github.com/VaughnVernon/IDDD_Samples/tree/master/iddd_collaboration/src/main/java/com/saasovation/collaboration/port/adapter/service
4. 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
5. O C Z Y M N I E ?
• Jak testować
• Jak refaktoryzować kod
• Przepis krok-po-kroku
12. 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
13. 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
14. 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…
15. 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
30. 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;
}
31. 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/…
52. 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 ;)
73. 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
74. 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
76. 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
77. 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