Slovník pojmů
Objektově orientované programování
OOP není jen použití tříd ani soutěž v počtu abstrakcí. Pomáhá rozdělit odpovědnosti a spolupráci kódu, když to odpovídá problému aplikace.
Stručná definice
Stav a chování drží pohromadě v jasných odpovědnostech.
Objekt může reprezentovat objednávku, službu pro rezervaci skladu nebo hodnotu peněz. Má vlastní stav a metody, které kontrolují, jak jej lze měnit. Třída je definice; objekt je konkrétní instance vytvořená podle této definice.
OOP v PHP využívá třídy, vlastnosti, metody, konstruktory, viditelnost, rozhraní, dědičnost a kompozici. Neznamená však, že každá hodnota potřebuje samostatnou třídu nebo že dědičnost je výchozí nástroj pro sdílení kódu.
Jaký problém řeší
Udržuje spolupracující části systému srozumitelné
Objektový návrh je užitečný tam, kde pravidla, závislosti a životní cyklus nelze čitelně držet v jedné sadě funkcí.
- modelování pravidel objednávky, platby nebo skladu
- oddělení aplikační služby od konkrétního HTTP či databázového adaptéru
- výměna implementace za test double přes rozhraní
- zapouzdření validního stavu a povolených změn objektu
- čitelné předávání závislostí přes konstruktor a dependency injection
Praktický příklad
Aplikační služba závisí na kontraktu rezervace skladu
Checkout služba nepotřebuje znát implementační detail skladu. Pracuje s rozhraním; produkční implementace může volat skladové API a test použít jednoduchou náhradu. Tím se demonstruje polymorfismus a dependency injection, ne nutnost vytvářet rozhraní pro každou třídu.
Objednávka sama může chránit své lokální invarianty, například nepovolit záporné množství. Koordinace více systémů, transakce a autorizace už často patří do aplikační služby, ne do jedné entity.
interface InventoryGateway {
public function reserve(string $sku, int $quantity): void;
}
final class CheckoutService {
public function __construct(private InventoryGateway $inventory) {}
public function reserveItem(string $sku, int $quantity): void {
$this->inventory->reserve($sku, $quantity);
}
}
Jak funguje
Objekty spolupracují přes jasné kontrakty
Textový diagram: aplikační služba → rozhraní → konkrétní implementace → výsledek.
- Pojmenování odpovědnosti Nejdřív se určí, co má objekt nebo služba skutečně dělat a co už je jiná odpovědnost.
- Stav a chování Objekt udržuje svůj platný stav a poskytuje metody, které mají konkrétní význam.
- Kontrakt Rozhraní popisuje potřebnou schopnost bez vazby na jednu implementaci, pokud je taková výměna skutečně užitečná.
- Kompozice Větší chování vzniká skládáním spolupracujících objektů a služeb, často přes konstruktor.
- Test a změna Test ověřuje výsledek chování; implementaci lze podle potřeby vyměnit bez změny konzumenta kontraktu.
Důležité pojmy
Třída, objekt a kontrakt mají jiný význam.
Největší přínos OOP není ve slovníku termínů, ale v jasné odpovědnosti a změnitelnosti kódu.
Třída a objekt
Třída je definice; objekt je konkrétní instance se stavem. Nejsou to synonyma pro databázovou tabulku a řádek.
Zapouzdření
Objekt omezuje, jak lze měnit jeho stav. Volně veřejné vlastnosti bez pravidel často jen maskují datovou strukturu.
Rozhraní a polymorfismus
Rozhraní vyjadřuje kontrakt. Různé implementace mohou stejnou schopnost poskytovat odlišně, pokud dodrží jeho význam.
Kompozice a dědičnost
Kompozice skládá objekty; dědičnost vytváří silnější vztah předek–potomek. Často je bezpečnější začít kompozicí.
Neměnnost a odpovědnost
Některé hodnotové objekty se po vytvoření nemění. Objekt má mít úzkou, srozumitelnou odpovědnost, ne být místem pro všechnu logiku.
Vztah k podobným pojmům
OOP není dědičnost ani automaticky dobrá architektura.
Zaměňované pojmy řeší rozdílné vrstvy návrhu.
- Třída a objekt
- Třída popisuje podobu, objekt je konkrétní instance se stavem a chováním.
- Dědičnost a kompozice
- Dědičnost sdílí vztah předek–potomek; kompozice skládá spolupracující objekty. Nejsou vzájemně zaměnitelné.
- OOP a framework
- Framework může být objektově napsaný a poskytovat DI, ale OOP je obecnější způsob návrhu programu.
- Objekt a ORM entita
- Entita může být objekt, ale pouhé mapování tabulky nedává automaticky bohatý a správně navržený doménový model.
Výhody a omezení
Abstrakce má cenu jen tehdy, když zjednoduší změnu.
Přínosy
- jasnější rozdělení stavů, chování a závislostí
- možnost vyměnit implementaci za kontraktem
- testování spolupráce objektů bez reálné infrastruktury
- zapouzdření místních invariantů a typových kontraktů
Časté chyby
- vytvářet třídu, interface a factory pro každou drobnou hodnotu
- používat dědičnost tam, kde postačí kompozice
- nechat jeden objekt držet desítky nesouvisejících odpovědností
- považovat samotné třídy za důkaz kvalitního objektového návrhu
Kdy dává smysl
Pro pravidla a spolupráci, které potřebují jasné hranice.
OOP je praktické pro dlouhodobé PHP aplikace s doménovými pravidly, integračními hranicemi a testovatelnými službami. Neznamená, že vše musí být abstraktní; jednoduché převody, dotazy a konfigurace mohou být přímočařejší.
Vhodná míra oddělení závisí na složitosti. U menší funkce může být jedna typovaná třída čitelnější než několik vrstev; u složitého procesu naopak jasné kontrakty snižují cenu budoucích změn.
Na co myslet
Před abstrakcí hledat skutečnou změnu, kterou má chránit.
Kód je kvalitnější, když je snadné vysvětlit odpovědnost objektu i důvod jeho závislosti.
- upřednostnit kompozici před dědičností, pokud vztah předek–potomek není přirozený
- zavést rozhraní tam, kde existuje smysluplný kontrakt či výměna implementace
- nepoužívat ORM entitu bezmyšlenkovitě jako celý doménový model
- držet závislosti explicitně a typovaně v konstruktoru
- testovat pozorovatelný výsledek, ne interní volání každé malé metody
Časté otázky
OOP bez akademických zkratek
Jaký je rozdíl mezi třídou a objektem?
Třída je definice, podle které lze vytvářet objekty. Objekt je konkrétní instance se stavem a chováním.
Musím pro OOP používat dědičnost?
Ne. Dědičnost je jen jedna technika a často je vhodnější kompozice spolupracujících objektů.
Kdy použít interface?
Když vyjadřuje skutečný kontrakt, který potřebuje více konzumentů nebo zaměnitelné implementace. Ne automaticky pro každou třídu.
Je každá Doctrine entita doménový objekt?
Ne nutně. ORM entita může být užitečné mapování dat, ale doménový model vyžaduje vlastní odpovědnosti a pravidla.
Jak navrhuji aplikace v praxi
Architekturu volím podle složitosti konkrétního systému.
V PHP projektech kombinuji přímočarý kód s jasnými hranicemi služeb a závislostí tam, kde pomáhají dlouhodobé údržbě.