Refaktoryzacja kodu poprzez delegację
Bardzo często mamy do czynienia z dużymi klasami - aż zbyt dużymi. Czuć od nich negatywny kod (code smell) na kilometr. Mówiąc kolokwialnie dana klasa śmierdzi .
Zbyt dużo jest wrzucone do jednego wora, zależności oraz odpowiedzialności nie są prawidłowo i należycie rozłożone. Jest nieczytelna i jej struktura kuleje... Jak sobie z tym poradzić?
W tym artykule podam jeden ze sposobów na poradzenie sobie z takimi wielkimi i grubymi klasami .
Jak to zrobić?
Jak już wspomniałem na wstępie, odbędzie się to poprzez delegację - płynne przerzucenie z jednej klasy do drugiej. Która jest bardziej odpowiednia do uskutecznienia pewnej koncepcji/logiki w naszej aplikacji.
Przykład
Załóżmy, że mamy klasę User która posiada w sobie trzy metody publiczne tj. paymentAccept, paymentCreate, paymentGet...
<?php
class User {
public function paymentGet()
{
//
}
public function paymentCreate()
{
//
}
public function paymentAccept()
{
//
}
}
Coś, coś...
Możemy już zauważyć po tych trzech metodach, że wszystkie dotyczą płatności. Przewija się tutaj cały czas jakieś słowo kluczowe... w tym przypadku "payment".
Jest to bardzo interesujące zjawisko na które warto zwrócić uwagę, ponieważ może to być znak mówiący o tym, że coś może nam tu umykać, że coś może jest tutaj nie tak, że coś tutaj nie gra, że najpewniej powinniśmy to zrobić w inny sposób a klasa ta nie powinna być bezpośrednio odpowiedzialna za tę logikę, że poszliśmy złą drogą... A wszystko często przez to, że na pierwszy rzut oka umieszczenie takich metod jak akceptacji płatności użytkownika pasuje do klasy użytkownika... prawda? No właśnie, tu zaczyna się problem i tak powstaje taka wielka klasa.
W rzeczywistości?
Nasza klasa rośnie i rośnie... to tylko 3 metody, ale przecież będą też inne metody w tej klasie prawda? A co jakby nie było ich 3 tylko 10 (dotyczących tylko płatności)? No właśnie. Także musimy je jakoś uporządkować, w tym przypadku nawet rozdzielić zależności, bo to nie klasa użytkownika jest bezpośrednio odpowiedzialna za zarządzanie płatnościami.
Do dzieła
Otóż dzięki płynnej delegacji do innej klasy która jest do tego odpowiednia i się tym zajmie możemy tego dokonać. A jak to zrobić? W bardzo prosty sposób, wystarczy zrobić nową klasę o nazwie np. "Payment" a następnie przenieść do niej trzy wcześniej wspomniane metody. Metody które do niej należą i które powinny tam być. A w klasie User możemy zrobić metodę "payment" która zwróci nam nową instancję klasy "Payment" do której przekażemy nasz obiekt użytkownika. Wykorzystujemy tutaj dependency injection oczywiście .
Ciężko sparsować? Zatem czas na kod
<?php
class User {
public function payment()
{
return new Payment($this);
}
}
class Payment {
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function get()
{
//
}
public function accept()
{
//
}
public function create()
{
//
}
}
Co warto zauważyć
Jak widzisz pozbyliśmy się również prefixu "payment" z nazw metod. To również jest znak że jesteśmy na dobrej drodze, że idziemy we właściwym kierunku, że zrobiliśmy dobrą robotę .
Oczywiście obie klasy nie powinny i nie będą się znajdować w jednym pliku . Ale mam nadzieję że nie musiałem tego pisać.
Done!
I to by było na tyle, pozbyliśmy się trzech (potencjalnie więcej) metod z naszej klasy User zastępując je tylko jedną metodą która nas przerzuci do odpowiedniej klasy.
Poprzednio chcąc pobrać płatność napisalibyśmy;
$user->paymentGet();
Obecnie zrobimy to tak;
$user->payment()->get();
Piękno i prostota
Także jak widzisz było to bardzo proste a świetnie się sprawdziło w misji polegającej na refaktoryzacji naszego kodu, porządkowania oraz rozdzielania zależności i obowiązków. Prosta a jakże piękna i skuteczna metoda .
Jeśli tobie również podoba się ta metoda - to włącz ją do swojego workflow. A jeśli już jej używasz, to może masz jakieś spostrzeżenia? Cokolwiek? Napisz w komentarzu !
I to tyle w dzisiejszym artykule . Oby był ci pomocny i wartościowy.
Zapraszam do komentowania oraz lektury pozostałych moich artykułów.
Życzę ci dobrego dnia, bywaj !