Przez lata w inżynierii oprogramowania panowały bezkonkurencyjnie zasady SOLID, definiujące dobre praktyki pisania kodu. Wraz z rozwojem i popularyzacją podejść funkcyjnych oraz systemów rozproszonych pojawiła się potrzeba większej elastyczności - dlatego też Dan North zdefiniował CUPID.

CUPID – co to takiego?

CUPID – podobnie jak SOLID – to akronim, zbiór pięciu zasad, które definiują przyjazny kod dla programisty (z ang. Joyful code). Zasady te skoncentrowane są na tworzeniu kodu, który będzie bardziej przejrzysty, czytelny, elastyczny – a przez to także łatwiejszy w utrzymaniu.

Akronim CUPID rozszyfrowany

  • Composable – komponowalny – kod powinien być modułowy i łatwy do ponownego wykorzystania.
  • Unix fhilosopny – filozofia unixa - każdy komponent (moduł) powinien wykonywać tylko jedną rzecz... I robić to dobrze! (nawiązanie do zasady pojedyńczej odpowiedzialności (SRP) w SOLID)
  • Predictable – przewidywalny – kod powinien działać zgodnie z oczekiwaniami i nie stanowić niespodzianek dla programisty.
  • Idiomatic – idiomatyczny – kod powinien wykorzystywać konwencje i dobre praktyki danego języka programowania.
  • Domain-based – oparty na domene – logika aplikacji powinna być zgodna z problemami, które rozwiązuje, a nie z narzędziami, które ją implementują. To nawiązanie do DDD (Domain-Driven Design), czyli ogólnie rzecz ujmując narzut biznesowy nad technologicznym.

SOLID vs CUPID

Obie koncepcje mają za główny cel poprawę jakości kodu, ale podchodzą do tematu w różny sposób. SOLID wymusza stricte podejście obiektowe w programowaniu, CUPID za to jest bardziej nastawiony na modułowość i funkcyjność. Główną doktryną SOLID jest zasada pojedynczej odpowiedzialności (SRP) wymuszająca separacje odpowiedzialności. CUPID ma lekko bardziej laickie podejście w tej kwestii - najważniejsza jest łatwość komponowania i przewidywalność działania kodu (co nie stoi tak naprawdę w opozycji do SRP). SOLID za to jest stosowany głównie w podejściu obiektowym w programowaniu – CUPID za to jest bardziej elastyczniejszy, sprawdza się zarazem w OOP jak i funkcjonalnym. Główny cel SOLID to cel technologiczny: redukcja sprzężenia i poprawa enkapsulacji. CUPID stawia sobie główne założenie, jakim jest przyjazność samego kodu oraz jego czytelność.

CUPID jest tak naprawdę swego rodzaju ewolucją SOLID, spojrzeniem bardziej z perspektywy potrzeb biznesowych aplikacji niż jeżeli samej sztuki programowania. Ta bardziej przyjazna, artystyczna dusza w rodzinie – tak parafrazując 😊.

CUPID & PHP

PHP jest językiem o dość szerokim zastosowaniu - choć cały czas jest kojarzony głównie z aplikacji webowych – to świetnie wdraża się CUPID w projekty. Zwłaszcza przy systemach bardziej rozbudowanych, rozproszonych, gdzie stosuje się inne metodyki – takie jak np. DDD właśnie, BDD czy nawet MACH.

Oto przykłady zastosowania zasad CUPID w praktyce – tylko dwie, ponieważ reszta dotyczy samego projektowania, a nie stricte kodu.

Composable (komponowalność)

Prosty przykład formatera tekstu przedstawiający modularne podejście - jest tak naprawdę wariacją wzorca projektowego strategii, kompozytu czy dekoratora oraz realizacją zasad SOLID takich jak pojedyncza odpowiedzialność (SRP) oraz otwarte / zamknięte (OCP).

interface Formatter {
    public function format(string $text): string;
}

class JsonFormatter implements Formatter {
    public function format(string $text): string {
        return json_encode(['message' => $text]);
    }
}

class TextFormatter implements Formatter {
    public function format(string $text): string {
        return strtoupper($text);
    }
}

function printMessage(Formatter $formatter, string $message) {
    echo $formatter->format($message);
}

printMessage(new JsonFormatter(), "Hello World");

W prosty sposób możemy używać / wymieniać formatery – w zależności od potrzeb. Przykład banalny, a przez to prosty do zrozumienia i zapamiętania.

Predictable (Przewidywalność)

Ważnym jest, aby kod działał wedle oczekiwań - bez udziwnień kodu (reguła KISS). Przykład równie banalny jak poprzedni – ale po co komplikować sobie życie? 😉

function add(int $a, int $b): int {
    return $a + $b;
}

echo add(2, 3); // 5

Brak efektów ubocznych działania tej metody sprawia, że kod jest czytelny i przewidywalny. Ogólnie rzecz ujmując: stosujmy metodykę, że im prościej tym lepiej - twórzmy małe, uniwersalne, proste klocki, z których budujmy złożone, rozbudowane systemy... a i jak łatwo i przyjemnie o-testować taką metodę prawda? 😊

Słowem podsumowania

CUPID jest nowoczesnym podejściem do wytwarzania dobrej jakości kodu z narzutem na jego przyjazność, elastyczność i przewidywalność. W przeciwieństwie do SOLID, CUPID sprawdza się nie tylko w paradygmacie obiektowym, ale także w programowaniu funkcyjnym czy skryptowym. Sam ten narzut nie zorientowany na technologie, a faktyczne potrzeby aplikacji sprawia, że sam kod jest bardziej czytelny oraz łatwiejszy w utrzymaniu... a i sam próg wejścia nowego programisty w projekcie jest zdecydowanie mniejszy i przyjemniejszy dla niego samego.

Czy CUPID sprowadzi SOLID do ciekawostki historycznej? Możliwe, ale wątpię - oba podejścia się uzupełniają i można je dobierać, wykorzystywać zależnie od kontekstu samego projektu.


Dla chcących dodatkowo pogłębić swoją widzę na ten temat podrzucam do przyjemnego materiału na ten temat.

Wspomnę jeszcze słowem końca: Mój ostatni projekt – ten na którym stoi ta stronka na którą właśnie patrzysz – jest wykonany z myślą, z narzutem na CUPID. Enjoy! 😊