{"id":30417,"date":"2022-03-02T08:08:00","date_gmt":"2022-03-02T07:08:00","guid":{"rendered":"https:\/\/nearshore-it.eu\/artykuly\/refaktoryzacja-kodu-php-z-rector\/"},"modified":"2024-11-07T13:15:50","modified_gmt":"2024-11-07T12:15:50","slug":"refaktoryzacja-kodu-php-z-rector","status":"publish","type":"post","link":"https:\/\/nearshore-it.eu\/pl\/artykuly\/refaktoryzacja-kodu-php-z-rector\/","title":{"rendered":"Zapomnij o legacy code, czyli refaktoryzacja kodu PHP z wykorzystaniem Rector"},"content":{"rendered":"\n<div class=\"table-of-contents\">\n    <p class=\"title\"><\/p>\n    <ol>\n                    <li><a href=\"#Legacy-code-co-to-takiego\">1.  Legacy code \u2013 co to takiego?<\/a><\/li>\n                    <li><a href=\"#Legacy-code-co-zrobi\u0107-z-takim-kodem\">2.  Legacy code \u2013 co zrobi\u0107 z takim kodem?<\/a><\/li>\n                    <li><a href=\"#Refactoring-kodu-narz\u0119dzia\">3.  Refactoring kodu \u2013 narz\u0119dzia<\/a><\/li>\n                    <li><a href=\"#Rector-PHP-pogromca-legacy-code\">4.  Rector PHP \u2013 pogromca legacy code?<\/a><\/li>\n                    <li><a href=\"#Refaktoryzacja-jakie-mamy-mo\u017cliwo\u015bci-w-takim-przypadku\">5.  Refaktoryzacja \u2013 jakie mamy mo\u017cliwo\u015bci w takim przypadku?<\/a><\/li>\n                    <li><a href=\"#Zmiana-architektury-kodu\">6.  Zmiana architektury kodu<\/a><\/li>\n                    <li><a href=\"#Dlaczego-Rector-a-nie-IDE\">7.  Dlaczego Rector, a nie IDE?<\/a><\/li>\n                    <li><a href=\"#Rector-konfiguracja\">8.  Rector \u2013 konfiguracja<\/a><\/li>\n                    <li><a href=\"#podsumowanie\">9.  Rector a kod legacy \u2013 podsumowanie<\/a><\/li>\n            <\/ol>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"Legacy-code-co-to-takiego\">Legacy code \u2013 co to takiego?<\/h2>\n\n\n\n<p>Zanim przejd\u0119 do opisania mo\u017cliwo\u015bci Rectora, chcia\u0142bym w kilku zdaniach nakre\u015bli\u0107, czym jest legacy code i jakie s\u0105 najcz\u0119\u015bciej wybierane sposoby radzenia sobie z tym\u017ce problemem. W sieci trafimy na wiele definicji legacy code. W dos\u0142ownym t\u0142umaczeniu legacy code oznacza nic innego, jak <strong>\u201ekod dziedziczony\u201d, <\/strong>czyli kod, kt\u00f3ry de facto otrzymujemy w spadku po innych programistach, na przyk\u0142ad w momencie do\u0142\u0105czenia do nowego projektu. Taki kod budzi l\u0119ki i obawy \u2013 kod dzia\u0142a, lecz nie znamy jego zawi\u0142ej logiki. Szczeg\u00f3lny postrach sieje trudny do zrozumienia i okie\u0142znania spaghetti code. Legacy code to r\u00f3wnie\u017c <strong>kod, kt\u00f3ry\u2026 piszemy w danej chwili,<\/strong> ale nie zosta\u0142 jeszcze pokryty testami, zatem nie jest przygotowany na zmiany w przysz\u0142o\u015bci. Wed\u0142ug mnie ka\u017cda z powy\u017cszych definicji opisuje istot\u0119 problemu.<\/p>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/jpro_2022.03.02_graphic1.png\" alt=\"kod legacy to te\u017c kod pisany pod now\u0105 funkcjonalno\u015b\u0107\" class=\"wp-image-63366\" title=\"\"><\/figure>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Legacy-code-co-zrobi\u0107-z-takim-kodem\">Legacy code \u2013 co zrobi\u0107 z takim kodem?<\/h2>\n\n\n\n<p>W pracy z legacy code mamy do wyboru podej\u015bcia, kt\u00f3re<strong> albo minimalizuj\u0105 jego wyst\u0105pienie, albo usuwaj\u0105 taki kod ca\u0142kowicie.<\/strong> Mo\u017cemy zatem zastosowa\u0107 takie rozwi\u0105zania jak refactoring kodu lub ca\u0142kowicie go przepisa\u0107. Refactoring kodu dotyczy optymalizacji jego ma\u0142ych fragment\u00f3w, bez zmiany podstawowej funkcjonalno\u015bci, drugie podej\u015bcie wymaga przepisania ca\u0142ego kodu aplikacji na nowo, z uwzgl\u0119dnieniem aktualnych standard\u00f3w.<\/p>\n\n\n\n<p><strong>Przeczytaj tak\u017ce:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/clean-architecture\/\" target=\"_blank\" rel=\"noreferrer noopener\">Clean Architecture<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/testy-bdd-czy-naprawde-sa-potrzebne\/\" target=\"_blank\" rel=\"noreferrer noopener\">Behavior-Driven Development<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/nearshore-it.eu\/pl\/artykuly\/test-driven-development-na-co-dzien\/\" target=\"_blank\" rel=\"noreferrer noopener\">Test-Driven Development<\/a><\/li>\n<\/ul>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Refactoring-kodu-narz\u0119dzia\">Refactoring kodu \u2013 narz\u0119dzia<\/h2>\n\n\n\n<p>Jak ju\u017c wspomnia\u0142em we wst\u0119pie, mamy obecnie wiele narz\u0119dzi umo\u017cliwiaj\u0105cych walk\u0119 z d\u0142ugiem technologicznym w kodzie PHP. W\u015br\u00f3d narz\u0119dzi do refaktoryzacji mo\u017cna wymieni\u0107 takie jak:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHP_CodeSniffer,<\/li>\n\n\n\n<li>PHP CS Fixer,<\/li>\n\n\n\n<li>PHP-Parser,<\/li>\n\n\n\n<li>PHPStan,<\/li>\n\n\n\n<li>Psalm,<\/li>\n\n\n\n<li>Rector.<\/li>\n<\/ul>\n\n\n\n<p>Kt\u00f3re z narz\u0119dzi wybra\u0107? Wszystko zale\u017cy od tego, czego zesp\u00f3\u0142 programist\u00f3w potrzebuje w danym momencie oraz tego, czy narz\u0119dzie spe\u0142nia nasze oczekiwania. Jednym z decyduj\u0105cych czynnik\u00f3w b\u0119dzie te\u017c znajomo\u015b\u0107 danego narz\u0119dzia przez cz\u0142onk\u00f3w zespo\u0142u developerskiego. Jedne z powy\u017cszych narz\u0119dzi przeprowadzaj\u0105 analiz\u0119 statyczn\u0105 kodu, drugie modyfikuj\u0105 go zgodnie z aktualnymi standardami, a jeszcze inne umo\u017cliwiaj\u0105 obie te rzeczy \u2013 tak jak w\u0142a\u015bnie Rector.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Rector-PHP-pogromca-legacy-code\">Rector PHP \u2013 pogromca legacy code?<\/h2>\n\n\n\n<p>Rector pojawi\u0142 si\u0119 w 2017 roku, a inicjatorem jego powstania by\u0142 Tomasa Votruba. Rector to program CLI (Command Line Interface) na licencji open source, oparty na &nbsp;komponentach <\/p>\n\n\n\n<p>Symfony. To narz\u0119dzie, kt\u00f3re poza analiz\u0105 statyczn\u0105 kodu dokonuje te\u017c jego zmiany. Podstawowe zastosowania Rectora to sprawna i szybka aktualizacja i refaktoryzacja kodu, a tak\u017ce zmiana architektury aplikacji.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Refaktoryzacja-jakie-mamy-mo\u017cliwo\u015bci-w-takim-przypadku\">Refaktoryzacja \u2013 jakie mamy mo\u017cliwo\u015bci w takim przypadku?<\/h2>\n\n\n\n<p>W przypadku aktualizacji i refaktoryzacji mo\u017cemy tutaj wymieni\u0107 takie mo\u017cliwo\u015bci jak:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>migracja z PHP 5.3 do PHP 8.1, &nbsp;<\/li>\n\n\n\n<li>migracja z Symfony 2.8 do Symfony 4.4, &nbsp;<\/li>\n\n\n\n<li>usuwanie tzw. martwego kodu (ang. <em>dead code, <\/em>czyli kodu, kt\u00f3ry nigdy nie b\u0119dzie wykorzystany),<\/li>\n\n\n\n<li>zmiana nazw klas, metod, parametr\u00f3w.<br><\/li>\n<\/ul>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/nearshore-it.eu\/wp-content\/uploads\/2024\/09\/jpro_2022.03.02_graphic2.png\" alt=\"dobra wiadomo\u015b\u0107 - mo\u017cna opanowa\u0107 kod legacy \" class=\"wp-image-63374\" title=\"\"><\/figure>\n<\/div>\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Zmiana-architektury-kodu\">Zmiana architektury kodu<\/h2>\n\n\n\n<p>Co do zmian architektury, zmiana fasady w Laravel na DI czy przeniesienie aplikacji z TYPO3 na Symfony. Oczywi\u015bcie wsp\u00f3\u0142czesne IDE umo\u017cliwiaj\u0105 refaktoryzacj\u0119 kodu, jednak mog\u0105 dzia\u0142a\u0107 wolno i by\u0107 skomplikowane w obs\u0142udze. W przypadku wykorzystywania wyra\u017ce\u0144 regularnych do wyszukiwania fragment\u00f3w kodu mog\u0105 znajdowa\u0107 nie wszystkie wyst\u0105pienia lub wr\u0119cz przeciwnie \u2013 wyszukiwa\u0107 znacznie wi\u0119cej. Kopiowanie i wklejanie przez programist\u0119 tak\u017ce mo\u017ce by\u0107 obarczone pewnym b\u0142\u0119dem wynikaj\u0105cym ze zm\u0119czenia czy rozkojarzenia.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Dlaczego-Rector-a-nie-IDE\">Dlaczego Rector, a nie IDE?<\/h2>\n\n\n\n<p>Rector nie zrobi nic, na co nie pozwoli programista! Opiera si\u0119 na regu\u0142ach (to zdefiniowane, pojedyncze \u201eprzepisy\u201d, kt\u00f3re dokonuj\u0105 pojedynczej zmiany w kodzie), zgrupowanych w zestawy regu\u0142 wykonuj\u0105cych zmiany o zbli\u017conej charakterystyce. <\/p>\n\n\n\n<p><span style=\"text-decoration: underline;\">Pojedyncze regu\u0142y:<\/span><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ArrayKeyFirstLastRector,<\/li>\n\n\n\n<li>IsCountableRector,<\/li>\n\n\n\n<li>JsonThrowOnErrorRector.<\/li>\n<\/ul>\n\n\n\n<p><span style=\"text-decoration: underline;\">Zestawy regu\u0142:<\/span><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PSR4, &nbsp;&nbsp;&nbsp;<\/li>\n\n\n\n<li>Php70,<\/li>\n\n\n\n<li>Php71,&nbsp;TypeDeclaration,<\/li>\n\n\n\n<li>DowngradePhp71.<\/li>\n<\/ul>\n\n\n\n<p>W momencie pisania artyku\u0142u Rector udost\u0119pnia\u0142 oko\u0142o <strong>660 regu\u0142, zebranych w ponad 48 zestaw\u00f3w.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"Rector-konfiguracja\">Rector \u2013 konfiguracja<\/h2>\n\n\n\n<p>Zasada dzia\u0142ania Rectora jest bardzo prosta \u2013 zaczynamy od zainstalowania narz\u0119dzia i jego konfiguracji. Rector w pierwszej kolejno\u015bci wyszukuje wszystkie pliki wskazane przez programist\u0119, nast\u0119pnie, analizuj\u0105c ka\u017cdy z nich z osobna,<strong> buduje dla nich AST <\/strong>(Abstract Syntax Tree), tzw. drzewo abstrakcji sk\u0142adniowej. Do ka\u017cdego takiego drzewa stosuje zdefiniowane przez programist\u0119 w pliku konfiguracyjnym regu\u0142y. Gdy ca\u0142y proces zostanie przeprowadzony, w konsoli otrzymujemy raport dotycz\u0105cy naniesionych zmian. Warto wspomnie\u0107, \u017ce <strong>Rector nie opiera si\u0119 wy\u0142\u0105cznie na domy\u015blnych regu\u0142ach \u2013 narz\u0119dzie umo\u017cliwia tworzenie w\u0142asnych, bardziej wyspecjalizowanych.&nbsp;<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/** @var SplFileInfo[] $fileInfos *\/\nforeach ($fileInfos as $fileInfo)  {\n    \/\/ 1 file => nodes\n    \/** @var Parser $phpParser *\/\n    $nodes = $phpParser->parse(file_get_contents($fileInfo->getRealPath()));\n    \/\/ nodes => 1 node\n    foreach ($nodes as $node) { \/\/ rather traverse all of them\n        \/** @var PhpRectorInterface[] $rectors *\/\n        foreach ($rectors as $rector)  {\n            foreach ($rector->getNodeTypes() as $nodeType)  {\n                if (is_a($node, $nodeType, true))  {\n                    $rector->refactor($node);\n                }\n            }\n        }\n    }\n}\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">return static function (\n    ContainerConfigurator $containerConfigurator\n): void {\n    \/\/ get parameters\n    $parameters = $containerConfigurator->parameters();\n    $parameters->set(Option::PATHS, [\n        __DIR__ . '\/src'\n    ]);\n    \/\/ Define what rule sets will be applied\n    $containerConfigurator->import(SetList::CODE_QUALITY);\n};\nChangeArrayPushToArrayAssignRector\nclass SomeClass\n  {\n      public function run()\n      {\n          $items = [];\n-         array_push($items, $item);\n+         $items[] = $item;\n      }\n  }<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">CombinedAssignRector\n-$value = $value + 5;\n+$value += 5;\nDateTimeToDateTimeInterfaceRector\nclass SomeClass {\n-    public function methodWithDateTime(DateTime $dateTime)\n+    \/**\n+     * @param DateTime|DateTimeImmutable $dateTime\n+     *\/\n+    public function methodWithDateTime(\n         DateTimeInterface $dateTime\n     ){\n         return true;\n     }\n}\nSimplifyArraySearchRector\n-array_search(\"searching\", $array) !== false;\n+in_array(\"searching\", $array);\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"podsumowanie\">Kod legacy \u2013 podsumowanie<\/h2>\n\n\n\n<p>Pracy z legacy code nie spos\u00f3b unikn\u0105\u0107, pr\u0119dzej czy p\u00f3\u017aniej ka\u017cdy programista spotka si\u0119 z nim w projekcie. Dobrze jest zna\u0107 mo\u017cliwo\u015bci, jakie w zakresie refaktoryzacji kodu daj\u0105 dost\u0119pne narz\u0119dzia, takie jak Rector. Mam nadziej\u0119, \u017ce przekona\u0142em was do poznania jego mo\u017cliwo\u015bci \u2013 a je\u015bli chcecie dowiedzie\u0107 si\u0119 wi\u0119cej, zach\u0119cam do obejrzenia mojego wyst\u0105pienia na DrupalCamp Poland 2021:<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Rector - nigdy wi\u0119cej legacy code - Marek Karmelski - DrupalCamp Poland 2021\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/Cg03e_M5Mw0?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Praca z kodem otrzymanym \u201ew spadku&#8221; lub z kodem jeszcze nieprzetestowanym mo\u017ce rodzi\u0107 wiele obaw. Nie zawsze pozbycie si\u0119 takiego kodu jest mo\u017cliwe, cz\u0119sto w pewnym momencie potrzebna jest refaktoryzacja za pomoc\u0105 odpowiednich narz\u0119dzi. Ju\u017c od ponad 15 lat programi\u015bci PHP mog\u0105 wykorzystywa\u0107 rozwi\u0105zania, kt\u00f3re u\u0142atwiaj\u0105 walk\u0119 z legacy code w codziennej pracy. Ale czym w\u0142a\u015bciwie jest legacy code i jak z nim pracowa\u0107? Jak pozby\u0107 si\u0119 d\u0142ugu technologicznego? W niniejszym artykule chcia\u0142bym przybli\u017cy\u0107 wam narz\u0119dzie, jakim jest Rector.<\/p>\n","protected":false},"author":113,"featured_media":30426,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"iawp_total_views":112,"footnotes":""},"categories":[1,582],"tags":[573],"offering":[514],"class_list":["post-30417","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artykuly","category-technologie","tag-php-pl","offering-ams"],"acf":[],"_links":{"self":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30417","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/users\/113"}],"replies":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/comments?post=30417"}],"version-history":[{"count":7,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30417\/revisions"}],"predecessor-version":[{"id":33827,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/posts\/30417\/revisions\/33827"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media\/30426"}],"wp:attachment":[{"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/media?parent=30417"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/categories?post=30417"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/tags?post=30417"},{"taxonomy":"offering","embeddable":true,"href":"https:\/\/nearshore-it.eu\/pl\/wp-json\/wp\/v2\/offering?post=30417"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}