Jak napisać czytelny i zrozumiały kod?

Cześć! 😊

Czy zdarzyło Ci się kiedyś wrócić do swojego kodu po kilku tygodniach i nie mieć pojęcia, co autor miał na myśli? A może odziedziczyłeś projekt po kimś i musiałeś spędzić kilka dni na analizowaniu jego „tajemniczych" funkcji? Jeśli tak, to ten artykuł jest dla Ciebie. Dziś opowiem Ci, jak pisać kod, który będzie czytelny, zrozumiały i utrzymywalny. Zaczynajmy!

  1. Trzymaj się zasad SOLID

Zasady SOLID to fundament dobrze zaprojektowanego kodu obiektowego. Oto szybkie przypomnienie:

  • S (Single Responsibility Principle) - jedna klasa powinna mieć tylko jedno zadanie.

  • O (Open/Closed Principle) - kod powinien być otwarty na rozbudowę, ale zamknięty na modyfikacje.

  • L (Liskov Substitution Principle) - podklasy powinny być w stanie zastępować klasy bazowe bez zmiany ich zachowania.

  • I (Interface Segregation Principle) - interfejsy powinny być konkretne, a nie przeładowane zbędnymi metodami.

  • D (Dependency Inversion Principle) - zależności powinny być odwrócone, czyli moduły wyższego poziomu nie powinny zależeć od modułów niższego poziomu, ale od abstrakcji.

Przykład:

interface Logger
{
    public function log(string $message): void;
}

class FileLogger implements Logger
{
    public function log(string $message): void
    {
        file_put_contents('log.txt', $message . PHP_EOL, FILE_APPEND);
    }
}

class UserService
{
    public function __construct(private Logger $logger)
    {
        $this->logger = $logger;
    }

    public function registerUser(string $name, string $email)
    {
        // logika rejestracji
        $this->logger->log("User $name registered successfully.");
    }
}
💡
Tutaj mamy przykład Dependency Inversion PrincipleUserService nie zależy bezpośrednio od FileLogger, lecz od abstrakcji Logger.
  1. Pisz czysty kod

Robert C. Martin (Uncle Bob) napisał książkę „Czysty Kod" i polecam ją każdemu programiście. Kilka zasad, które warto stosować:

  • Nazwy powinny być opisowegetUserById() jest lepsze niż getData().

  • Funkcje powinny robić tylko jedną rzecz.

  • Unikaj „magicznych liczb" – zamiast if ($status == 1), lepiej zastosuj
    if ($status === Status::ACTIVE).

  • Komentuj tylko to, co naprawdę wymaga wyjaśnienia – dobry kod nie potrzebuje komentarzy!

Przykład:

final class OrderProcessor
{
    public function process(Order $order): void 
    {
        if ($order->getStatus() !== OrderStatus::PENDING) {
            throw new Exception("Order cannot be processed.");
        }

        $order->setStatus(OrderStatus::PROCESSED);
        $this->sendConfirmationEmail($order->getUser());
    }

    private function sendConfirmationEmail(User $user): void 
    {
        echo "Sending email to " . $user->getEmail();
    }
}
💡
Tutaj klasa OrderProcessor ma jasno określoną odpowiedzialność i używa czytelnych nazw metod oraz stałych zamiast „magicznych liczb".
  1. Stosuj Domain-Driven Design (DDD)

DDD to podejście, które pomaga tworzyć kod bliski logice biznesowej, a nie tylko technicznym implementacjom. Zamiast operować na surowych tablicach i prostych klasach, warto wprowadzić:

  • Encje – reprezentujące konkretne obiekty w domenie.

  • Value Objects – obiekty reprezentujące wartości (np. Money, Email).

  • Agregaty – grupy obiektów, które zmieniamy jako całość.

  • Repozytoria – klasy do obsługi operacji na bazie danych.

Przykład:

readonly class Email
{
    public function __construct(private string $email)
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException("Invalid email address");
        }
        $this->email = $email;
    }

    public function getEmail(): string
    {
        return $this->email;
    }
}
💡
To podejście pozwala uniknąć błędów – nie można stworzyć obiektu Email z niepoprawnym adresem.
  1. Wykorzystuj wzorce projektowe

Wzorce projektowe pomagają rozwiązywać powtarzalne problemy w elegancki sposób. Oto kilka przydatnych wzorców:

  • Singleton – używany np. do połączenia z bazą danych.

  • Factory Method – tworzy obiekty w kontrolowany sposób.

  • Repository – abstrahuje dostęp do bazy danych.

  • Strategy – pozwala zmieniać algorytmy bez zmiany kodu.

Przykład Factory Method w PHP:

class UserFactory 
{
    public static function create(string $name, string $email): User 
    {
        return new User($name, new Email($email));
    }
}
💡
Dzięki temu tworzymy użytkownika w jednym miejscu, zamiast powtarzać kod w wielu miejscach.

Podsumowanie

Czytelny i zrozumiały kod to nie magia – to stosowanie sprawdzonych zasad: SOLID, czystego kodu, DDD i wzorców projektowych. Twój przyszły „Ja" (lub inny programista) na pewno Ci za to podziękuje! Zacznij wprowadzać te zasady już dziś, a Twoje projekty staną się bardziej przejrzyste i łatwiejsze w utrzymaniu.

A Ty? Masz swoje ulubione zasady pisania czytelnego kodu? Podziel się w komentarzach! 😊

0
Subscribe to my newsletter

Read articles from Andrzej Kostrzewa directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Andrzej Kostrzewa
Andrzej Kostrzewa