Z názvů rozhraní mizí prefixy I
V Nette se rozhraní pojmenovávaly s písmenem I
na začátku
(např. IRequest
). Před pár lety započal nesmírně pomalý a
dlouhodobý proces, který tiše při zachování zpětné kompatibility
začíná rozhraní prefixů zbavovat. Jak přesně to probíhá a proč?
Konvence kolem nás
Nette používalo konvenci prefixovat rozhraní písmenem I
od
svého počátku. Názvy abstraktních tříd nikdy nijak neodlišovalo.
U jiných frameworků (např. Symfony, CakePHP, Zend nebo PSR) se můžete
setkat s odlišnou konvencí, a to používáním koncovky
Interface
(např. Psr\Cache\CacheItemInterface
)
společně s předponou Abstract
pro abstraktní třídy (např.
Psr\Log\AbstractLogger
). A nakonec tu máme knihovny (např.
Laravel nebo systémová knihovna PHP), které rozhraní ani abstraktní třídy
nijak neodlišují (např. rozhraní Throwable
nebo
Iterator
, abstraktní třída FilterIterator
).
Kdybychom se podívali mimo PHP svět, prefix I
používá
třeba C#, naopak v Javě nebo TypeScriptu se jména neodlišují.
Zhruba před deseti lety, v době, kdy vznikla knihovna Nette DI, srdce všech moderních a čistě navržených aplikací nad Nette, jsem si plně uvědomil, že odlišování rozhraní a abstraktních tříd, ať už prefixem nebo koncovkou, je obrovská chyba. V té době už ale framework slavil 5 let existence a nebylo možné názvy rozhraní měnit, aniž by to způsobilo kolosální BC break. Pro zachování konzistence jsem u Nette používal prefixy dál, ale u všech ostatních projektů od toho upustil. (Nette bylo v té době ještě monolit, ale např. Nette Tester byl samostatný projekt a v něm už prefix u rozhraní nenajdete).
Nicméně stále jsem hledal cestu, jak by bylo možné prefix I
bezbolestně opustit. Odlišování názvů rozhraní vnímám jako natolik
podstatný přešlap, že mi stálo za to vynaložit velké úsilí do jeho
nápravy. Zejména proto, že framework berou programátoři za vzor čistého
návrhu.
Důvodům se věnuje samostatný článek Předpony a přípony do názvů rozhraní nepatří.
Jak dát Íčku sbohem?
Po několika letech se mi podařilo najít způsob, jak dát I
pryč. Tiše a s plným zachováním kompatibility. Šlo o proces
naplánovaný na mnoho let dopředu, který odstartoval s vydáním
Nette 3.1.
Obvykle stačilo jednoduše původní rozhraní přejmenovat (např.
Nette\Mail\IMailer
na Mailer
) a zároveň vytvořit
alias (IMailer
), aby fungovaly obě verze. Společně s tím jsem
do zdrojového souboru přidal „skrytý“ kód, který vnímá pouze IDE a
Composer. Díky němu funguje autoloading i pro alias a přiměje editor, aby
jej v kódu přeškrtával jakožto deprecated s poznámkou, že se
má používat verze bez prefixu. Takže veškerý dosavadní kód funguje beze
změny a programátor je přitom veden, aby preferoval novou variantu.
V některých případech jsem rozhraní nepřejmenovával, protože bylo
v plánu je změnit (např. nové Nette\Security\UserStorage
se
liší od starého Nette\Security\IUserStorage
a v rámci
přechodu lze obě používat současně), nebo protože chystám jiné
řešení (např. Tracy\IBarPanel
bude nahrazen novým
rozšířením pro Tracy).
V některých případech odstranění prefixu nebylo možné, protože
název byl už obsazený. To je třeba případ
Nette\Security\IIdentity
a Identity
. Tady je potřeba,
aby se nejprve zaužívalo SimpleIdentity
jako nástupce
Identity
, a název se uvolnil. Taková věc se musí rozložit na
několik major verzí a tedy mnoho let, aby proběhla opravdu bezbolestně. Ale
není kam spěchat.
V Nette 4 tak zůstanou prefixované už jen
Nette\Http\IRequest
a IResponse
, jako připomínka
někdejší doby. A dále Nette\ComponentModel\IComponent
a
IContainer
, u kterých si však nejsem jistý, jestli je jejich
existence vůbec užitečná. Aliasy budou samozřejmě fungovat dál.
Komentáře
Tolik snahy o znepřehlednění kódu v tak krátkém čase se opravdu jen tak nevidí…
Chcete-li odeslat komentář, přihlaste se