Slovník pojmů

Rozhraní v programování

Rozhraní popisuje, co objekt umí, ne jak to uvnitř provádí. Díky tomu lze spolupracující část systému vyměnit, testovat nebo provozovat jiným způsobem bez změny jejího konzumenta.

Stručná definice

Kontrakt odděluje schopnost od jedné konkrétní třídy.

Interface deklaruje veřejné metody a jejich kompatibilní signatury; implementující třída doplní vlastní chování. Jedna třída může implementovat více rozhraní a více tříd může poskytovat stejný kontrakt. Volající pak typuje závislost rozhraním, pokud mu stačí popsaná schopnost.

Rozhraní v programovacím jazyce není totéž co uživatelské rozhraní ani HTTP API. Všechny tři pojmy vyjadřují hranici komunikace, ale PHP interface je konkrétní jazykový kontrakt mezi třídami. Vedle metod může PHP rozhraní deklarovat také konstanty a v současném PHP i požadavky na veřejně přístupné vlastnosti.

Použití

Kde kontrakt skutečně snižuje vazbu

Rozhraní je užitečné tam, kde má více implementací stejný význam pro konzumenta, nikoli jako povinný doplněk každé třídy.

  • dopravci, kteří vytvoří štítek zásilky společným způsobem
  • skladové brány pro lokální systém i vzdálené API
  • úložiště, cache nebo fronta vyměnitelná podle prostředí
  • test double nahrazující pomalou nebo placenou externí službu
  • aplikační port mezi doménovou logikou a infrastrukturou

Praktický příklad

Založení zásilky přes společný kontrakt

Checkout nemusí vědět, jestli dopravce komunikuje přes REST API, SOAP nebo lokální knihovnu. Požaduje pouze schopnost vytvořit štítek. Implementaci zvolí konfigurace aplikace; test může použít jednoduchý fake bez sítě.

PHP

interface ShippingLabelProvider
{
    public function create(Shipment $shipment): ShippingLabel;
}

final class CreateShipment
{
    public function __construct(private ShippingLabelProvider $labels)
    {
    }

    public function handle(Shipment $shipment): ShippingLabel
    {
        return $this->labels->create($shipment);
    }
}

Jak to funguje

Od potřebné schopnosti ke konkrétnímu adaptéru

Rozhraní stojí mezi částí aplikace, která práci potřebuje, a částí, která ji technicky provede.

  1. Pojmenování kontraktu Rozhraní vyjadřuje jednu smysluplnou schopnost, například vytvoření štítku.
  2. Implementace Třída dodrží metody a jejich signatury, ale volí vlastní technické provedení.
  3. Předání závislosti Aplikační služba dostane kontrakt přes konstruktor nebo DI container.
  4. Volání Konzument pracuje jen s metodami rozhraní, ne s detaily dopravce.
  5. Výměna a test Implementaci lze nahradit jiným adaptérem nebo testovacím fakem při zachování významu kontraktu.

Hlavní části a pojmy

Rozhraní popisuje veřejné chování, ne celý objekt.

Dobře navržený kontrakt je úzký, stabilní a mluví jazykem konkrétního problému.

Implementace

Klíčové slovo implements zavazuje třídu doplnit požadované veřejné metody s kompatibilní signaturou.

Polymorfismus

Různé objekty lze používat zaměnitelně, pokud pro konzumenta dodržují stejný význam kontraktu.

Více rozhraní

Třída může implementovat více samostatných schopností. To je jiné než vícenásobná dědičnost tříd, kterou PHP nepodporuje.

Rozhraní a abstraktní třída

Abstraktní třída může sdílet částečnou implementaci a stav. Rozhraní se soustředí na veřejný kontrakt a nevnucuje dědičnou větev.

Kontrakt a API

V obou případech jde o dohodu mezi stranami. PHP interface ale běžně není veřejné HTTP API pro jiné systémy.

Vztah k architektuře

Rozhraní pomáhá na hranici, ne jako dekorace každého souboru.

Nejužitečnější bývá tam, kde se mění technický detail nebo kde se vyplatí nezávisle ověřit spolupráci.

Dependency Injection
Konzument může záviset na kontraktu a konkrétní implementaci obdrží při sestavení aplikace.
Test double
Fake nebo stub dodá předvídatelný výsledek; mock ověřuje vybranou spolupráci, pokud je její volání podstatné.
Port a adaptér
Aplikační vrstva může definovat port jako rozhraní a infrastruktura k němu dodat adaptér.
Veřejná knihovna
Stabilní interface je závazek vůči uživatelům knihovny, proto se jeho změna zvažuje pečlivěji než interní třída.

Výhody a omezení

Interface snižuje vazbu, ale nezlepší špatně zvolený kontrakt.

Přínosy

  • konzument nezná konkrétní technické provedení
  • výměna implementace může mít malý dopad na zbytek kódu
  • test se snadněji izoluje od externí infrastruktury
  • kontrakt zpřesňuje očekávané schopnosti objektu

Časté chyby

  • interface pro každou interní třídu bez druhého konzumenta či alternativy
  • příliš široký kontrakt se směsí nesouvisejících metod
  • rozhraní kopírující technický detail místo obchodní potřeby
  • představa, že interface sám zajistí dobrou architekturu nebo testy

Kdy dává smysl

Používat, když kontrakt odpovídá skutečné variabilitě.

Rozhraní má dobrý důvod například u dopravců, platebních bran, úložišť a integračních klientů, kde může aplikace používat více implementací stejné schopnosti. Užitečné je také tehdy, když aplikační vrstva nemá znát detail databáze nebo sítě.

Jedna interní třída bez plánované výměny často interface nepotřebuje. Nejprve je vhodné pojmenovat konkrétní potřebu; abstrakci lze přidat ve chvíli, kdy rozhraní chrání reálnou hranici, ne jen hypotetickou budoucnost.

Na co myslet

Kontrakt má být malý, významový a ověřitelný.

Při změně rozhraní je dobré myslet na všechny implementace i na význam výsledku, ne pouze na shodu názvů metod.

  • typovat závislost nejmenším kontraktem, který konzument skutečně potřebuje
  • držet stejné názvy parametrů u implementace, zejména při použití pojmenovaných argumentů
  • nepřidávat metodu jen proto, že ji potřebuje jedna nesouvisející implementace
  • testovat pozorovatelný význam kontraktu napříč implementacemi
  • nenahrazovat rozhraním přímou a jednodušší spolupráci bez důvodu

Časté otázky

Rozhraní neboli interface v PHP

Jaký je rozdíl mezi rozhraním a třídou?

Třída dodává konkrétní stav a chování. Rozhraní především předepisuje veřejný kontrakt, který musí implementující třída dodržet.

Musí mít každá třída vlastní interface?

Ne. Smysl má při skutečném kontraktu, více implementacích nebo jasné architektonické hranici. Pro jednu interní třídu bez takové potřeby jen přidává údržbu.

Může třída implementovat více rozhraní?

Ano. PHP umožňuje implementovat více rozhraní; třída pak musí splnit kontrakty všech jejich veřejných metod.

Je interface totéž co dependency injection?

Ne. Rozhraní popisuje kontrakt. Dependency injection je způsob, jak objekt dostane závislost zvenčí; může jí být interface i konkrétní třída.

Jak navrhuji aplikace v praxi

Kontrakty zavádím tam, kde zjednoduší změnu nebo oddělí infrastrukturu.

U složitějších PHP aplikací rozlišuji aplikační rozhodnutí od databáze, HTTP a externích služeb; rozsah oddělení vždy volím podle konkrétního problému.

Zavolejte mi

Zavolám vám následující pracovní den mezi 9:00 a 17:00.

Můžete mi také zavolat rovnou.

+420 605 181 728

Nechte mi telefonní číslo a pošlete žádost o zpětné zavolání.

Odesláním souhlasíte se zpracováním údajů pro vyřízení žádosti.