Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Git: jak na hromadný rebase

Pokud máte v Git repozitáři víc vývojových větví, je rozhodně dobré je průběžně aktualizovat oproti masteru. V řeči Gitu jde o rebase. Aktualizované větve se pak mnohem snáze aplikují (merge) do hlavní vývojové větve. A pokud máte větví opravdu hodně, aktualizovat každou zvlášť je zdlouhavé. Pomoci může skript rebaseall.phpc, který stačí zavolat někde uvnitř repozitáře:

<?php

// zjisti seznam větví
exec('git branch', $branches);

// postupně každou rybejzuj proti masteru
foreach ($branches as $branch) {
        $branch = trim($branch, "* \r\n");
        passthru("git rebase master $branch", $errorCode);
        if ($errorCode) {
                exit;
        }
}

// a nakonec se vrať na master
passthru('git checkout master');

Je možné, že se to dá zapsat i jedním příkazem z bashe, ale já rád skriptuju v PHP a bash nemám.

clock 22. 11. 2011 pencil PHP comments Komentáře: 2


Zen Dependency Injection

Dependency Injection je technika, která řeší určité problémy, ale zároveň přináší těžkosti nové. Ty se pak snaží eliminovat DI kontejner, který od vás vyžaduje změnit pohled na objektový návrh.

Pokud vás netrápí problémy, které DI řeší, tak jeho nasazení budete vnímat jen jako zbytečnou obtíž. Třeba právě v nutnosti osvojení nového pohledu na objektový návrh.

Nicméně zdá se, že pokud vás netrápí problémy, které DI řeší, máte vážný problém. Což zjistíte, až to zjistíte.

clock 10. 10. 2011 pencil PHP comments Komentář: 1


„Mám nejhoršího klienta, stále mění zadání“

Znáte ty nářky vývojářů, že jejich klient nemá jasnou představu a neustále mění zadání zakázky? To pláčou nad vlastní neschopností. Když je slyším, nejraději bych popřál nebohému klientovi lepšího dodavatele.

Klient nemá jasné zadání, protože není odborník na webdesign. Zajímalo by mě, kolik webdesignérů se vyzná v podnikání svého klienta tak dobře, že by dokázalo vytvořit precizní zadání, kdyby se karty obrátily.

Pokud klient zadání průběžně mění, znamená to, že ho projekt zajímá a baví, že nad ním neustále přemýšlí. Je pak větší pravděpodobnost, že vznikne něco skutečně užitečného. A především: bude poptávat další a další práci.

Pokud si vývojář tyto věci uvědomí, pak pochopí, že je to právě on, kdo musí přizpůsobit svůj styl práce. Třeba zjednodušit přidání kolonky PSČ na web, ač to v původním zadání nebylo.

clock 23. 5. 2011 pencil Nette comments


Nové jmenné prostory v Nette

Společně s vydáním Nette Framework 2 beta dochází k úpravě jmenných prostorů a názvů tříd. Je jasné, že přejmenovávání nepatří mezi populární úpravy, nicméně snažil jsem se udělat vše pro to, aby přechod byl bezbolestný.

Jaké jsou vlastně důvody?

Nette Framework je dost možná prvním PHP frameworkem na světě, který používání jmenných prostorů zavedl. Kvůli prodlevám s vydáním PHP 5.3 se začaly v praxi používat docela pozdě a tudíž mají stále svou první a dnes již historickou podobu. Ta neodpovídá současnému stavu frameworku, navíc pojmenování tříd bylo často ovlivněno kompatibilitou s verzí PHP 5.2. Před vydáním nové verze frameworku je záhodno stav napravit.

Zpětná kompatibilita

Úpravy se týkají především verze frameworku pro PHP 5.3. Ve verzích pro 5.2 dochází jen k drobným změnám, a to proto, aby se zbytečně nerozevíraly nůžky mezi 5.3 a 5.2 verzemi.

Nejspíš by k tak radikálním krokům ani nedošlo, kdyby nebylo možné přechod zcela zautomatizovat. K dispozici proto máte skript, který všechny změny ve vašich zdrojových souborech udělá za vás! Najdete jej v distribučním balíku v tools/Code-Migration/class-updater.php.

Parametry pro spuštění:

php class-updater.php -d /cesta/k/app [-f]

kde /cesta/k/app nahradíte za skutečnou cestu ke složce s vašimi zdrojovými soubory. Pokud neuvedete nepovinný parameter -f, skript běží v read-only režimu a jen vypíše, které soubory by změnil.

DŮLEŽITÉ UPOZORNĚNÍ: nezapomeňte si před použitím zazálohovat zdrojové kódy a po konverzi ověřit porovnáním, zda záměny proběhly v pořádku.

Skript vyžaduje pro spuštění PHP 5.3 a najdete jej jen v 5.3 balíku. Lze pomocí něj konvertovat všechny verze Nette Framework (tj. pro 5.3 i pro 5.2).

Pokud z nějakého důvodu nemůžete soubory aktualizovat, můžete využít aliasování tříd. Stačí ve své aplikaci hned po načtení frameworku načíst skript compatibility-aliases.php, který najdete opět v tools/Code-Migration. Příklad v bootstrap.php:

// načteme framework
require LIBS_DIR . '/Nette/loader.php';

// načteme aliasy
require LIBS_DIR . '/compatibility-aliases.php';

Nette\Debug::enable(); // fungují původní názvy tříd

Aliasování funguje pouze pro Nette Framework ve verzi pro PHP 5.3.

Pravidla pojmenování

Novou podobu názvů tříd jsem chtěl podřídit, jako v podstatě vše v Nette, pohodlí programátora. Jak ukázala řada diskusí, subjektivní požadavky mohou být rozporuplné. Pro někoho znamená pohodlí mít co nejkratší názvy tříd, pro jiného jsou to názvy co nejvíce popisné. Přehled myšlenek, ze kterých se vycházelo, najdete v článku Best practices pro jmenné prostory v PHP.

Nyní by všechny třídy měly mít výstižný název i bez uvedení jmenného prostoru, preferovány jsou kratší názvy a lze pěkně využít parciální namespaces:

use Nette\Http; // alias pro namespace

// dostupné jsou všechny třídy via Http:
$request = new Http\Request;
$response = new Http\Response;

Nová struktura pro 5.3

Nejlépe si novou strukturu můžete prohlédnout přímo v API dokumentaci. Důležité změny jsou tyto:

  • výjimky, které byly bez namespace, jsou nyní v prostoru Nette
  • Nette\Debug je teď Nette\Diagnostics\Debugger (což je dlouhé, zvažuje se alias např. NDebug)
  • Presenter & Control jsou ve jmenném prostoru Nette\Application\UI, routery v Nette\Application\Routers
  • z AppForm se stal Nette\Application\UI\Form
  • StringNette\Utils\Strings a ArrayToolsNette\Utils\Arrays
  • Finder, Json, Neon, Paginator a Html jsou nyní taky v Nette\Utils (třída Tools už není)
  • Nette\Mail\MailNette\Mail\Message
  • prostor Nette\Templates přejmenován na Nette\Templating
  • ITranslator je nyní v prostoru Nette\Localization
  • úložiště pro cache jsou v Nette\Caching\Storages
  • low level komponenty jsou v Nette\ComponentModel

Jak bylo vysvětleno výše, nemusíte se přechodu obávat, konverzi za vás udělá utilitka.

Nová struktura pro 5.2

Zde jsou důležité vlastně jen tyto změny:

  • DebugDebugger, StringStrings, ArrayToolsArrays, MultiRouterRouteList a DownloadResponse → FileResponse

A pak ještě několik tříd, konverzi opět udělá utilitka.

Přechod na verzi 5.3 se jmennými prostory

PHP ve verzi 5.2 je zatím stále podporováno, ale rozhodně doporučujeme aktualizovat na verzi pro PHP 5.3 se jmennými prostory. S migrací vám pomůže nový nástroj tools/Code-Migration/migrate-53.php. Příkazová řádka i všechny upozornění jsou stejné, jako v případě nástroje class-updater.php. Enjoy!

clock 19. 4. 2011 pencil Nette comments Komentáře: 6


Best practices pro jmenné prostory v PHP

Pár dobře míněných tipů, jak navrhnout strukturu jmenných prostorů (namespaces) a názvy tříd v PHP 5.3.

Ačkoliv jmenné prostory jsou asi nejznámější novinkou PHP verze 5.3, za tolik klíčové je nepovažuji. Respektive na seznamu přání, co bych rád v PHP viděl, by se mezi první desítku dostaly jen s odřenými oddělovači. Praxe totiž ukazuje, že jmenným konfliktům spolehlivě předejde použití 1–2 písmenného prefixu, stejně tak jsem se nikdy nedopustil názvů tříd jako Zend_Service_DeveloperGarden_Response_ConferenceCall_AddConferenceTemplateParticipantResponseType (97 znaků, zajímalo by mě, jak s tím dodržují pravidlo o max. délce řádků 80 znaků :-) ). Avšak PHP kráčí ve šlépějích Javy a tak tu máme namespaces. Jak s nimi naložit?

Přínos jmenných prostorů

Asi nejsložitější otázka, na kterou si musíte odpovědět, zní: čemu prospěje přejmenovat třídu:

  • sfFormSymfony\Component\Form\Form

Otázka je osvědčeným závdavkem k nekonečným flame wars. Z hlediska pohodlí programátora, intuitivnosti a zapamatovatelnosti je vhodnější původní stručné a výstižné sfForm. Odpovídá totiž tomu, jak třídu programátoři označí hovorově, tj. „formulář v symfony“. Nový a delší název je zase správný z jiných hledisek, u nichž si ovšem nejsem jist, jestli je běžný uživatel ocení.

Může se tedy stát, že jmenné prostory budou jednou částí programátorské obce vnímány jako skvělá věc, pro kterou je třeba něco obětovat ve „vyšším zájmu“ (srovnej s XHTML), a druhou částí jako něco, co z dobře uchopitelných frameworků udělalo těžkopádné obludy (a tak jsme se na ně těšili).

Jak jmenné prostory rozvrhnout?

Syntaktickou stránku použití popisuje dokumentace, objevit správné vzory však chce praxi, na kterou zatím nebylo dost času. Prostory v PHP mají svá specifika daná celou řadu faktorů, proto není ideální 100% kopírovat konvence používané třeba v Javě nebo .NET. Dá se z nich však dobře vycházet.

Více si řekneme u jednotlivých pravidel pro pojmenování.

1) třída má mít výstižný název i bez uvedení NS

Název každé třídy i bez jmenného prostoru musí vystihovat její podstatu. Nevhodné by bylo přejmenovat třídu ArrayIteratorSpl\Iterators\Array, protože pod názvem Array by člověk neočekával iterátor (pomiňme, že třídu nelze nazvat klíčovým slovem). A pozor, ani z názvu Spl\Iterators\Array nemusí být zřejmé, že jde o iterátor, protože nelze sázet na to, že namespace Spl\Iterators obsahuje pouze iterátory. Mohou tam být třeba i nějaké pomocné třídy.

Pár příkladů:

  • nevhodné: Nette\Application\Responses\Download – nelze dovodit, že Download je odpověď
  • nevhodné: Zend\Validator\Date – předpokládali byste, že Date je validátor, nikoliv datum?
  • nevhodné: Zend\Controller\Request\Http – předpokládali byste, že Http je požadavek?

Proto krom specializace tříd je vhodné v názvu ponechat i obecnost:

  • lepší: Nette\Application\Responses\DownloadResponse
  • lepší: Zend\Validator\DateValidator
  • lepší: Zend\Controller\Request\HttpRequest

Ideální je, pokud existuje jednoslovný a přitom výstižný název. Ten lze vymyslet hlavně u tříd, které reprezentují něco z reálného světa:

  • nejlepší: Nette\Forms\Controls\Button – dvouslovné ButtonControl netřeba (avšak HiddenControl na Hidden zkrátit nelze)

2) jmenný prostor má mít výstižný název

Pochopitelně i samotný název jmenného prostoru musí být výstižný a výhodou je název kratší, bez zbytečností. Takovou zbytečností se mi zdá např. Component v Symfony\Component\Routing, protože bez něj by název nijak neutrpěl.

V některých situacích je třeba se rozhodnout mezi jednotným a množným číslem (Zend\Validator vs Zend\Validators), což je podobně nerozhodný problém, jako při volbě jednotných a množných čísel u databázových tabulek.

3) rozlište jmenné prostory a třídy

Pojmenovat třídu stejně jako jmenný prostor (tj. mít třídy Nette\Application a Nette\Application\Request) je technicky možné, mohlo by to však programátory mást a lépe se bude tomu vyhnout. Myslete i na to, jak dobře se bude výsledný kód číst nebo jak budete API někomu vysvětlovat.

4) omezte zbytečné duplicity (+ parciální namespace)

Ideální je, pokud název třídy a název prostoru neobsahují duplicitně stejnou informaci.

  • místo Nette\Http\HttpRequest raději Nette\Http\Request
  • místo Symfony\Component\Security\Authentication\AuthenticationTrustResolver raději třídu TrustResolver

Třída Nette\Http\Request neodporuje pravidlu č. 1 o výstižném názvu třídy i bez uvedení jmenného prostoru, naopak nám dovoluje elegantně využít parciální namespace:

use Nette\Http; // alias pro namespace

// dostupné jsou všechny třídy via Http:
$request = new Http\Request;
$response = new Http\Response;
// a navíc Http\Response je srozumitelnější než samotné Response

Pokud jmenné prostory chápeme jako balíčky, což je obvyklé, vede to k nešťastnému duplikování posledního slova:

  • Zend\Form\Form
  • Symfony\Component\Finder\Finder
  • Nette\Application\Application

Jmenné prostory také doslova svádí sdružovat třídy (např. různé implementace téhož rozhraní apod.) do vlastních prostorů, což opět vytváří duplicity:

  • Nette\Caching\Storages\FileStorage – tj. všechny úložiště v samostatném prostoru Storages
  • Zend\Form\Exception\BadMethodCallException – všechny výjimky do Exception
  • Symfony\Component\Validator\Exception – opět všechny výjimky do Exception

Sdružující namespaces prodlužují název a vytváří v něm duplicity, protože obecnost často není možné z názvu tříd odstranit (1. pravidlo). Jejich výhodou může být lepší orientace ve vygenerované API dokumentaci (téhož by však šlo dosáhnout i jinak) a snazší dostupnost při použití plnohodnotných IDE s napovídáním. Každopádně je doporučuji používat jen s rozvahou. Například pro vyčlenění výjimek se moc nehodí.

5) nezaměnitelnost tříd z více prostorů

Dle bodu 1) má mít třída výstižný název, což ale neznamená, že má být i jednoznačný v rámci celé aplikace. Obvykle stačí, aby byl jednoznačný v rámci jmenného prostoru. Pokud se však v kódu často používají vedle sebe dvě třídy z různých prostorů, nebo pokud mají mezi sebou jinou podstatnou souvislost, neměly by mít stejný název. Jinými slovy, nemělo by být nutné používat AS v klauzuli USE.

6) jednosměrné závislosti

Zvažte, jaké závislosti mají mezi sebou mít třídy z jednotlivých jmenných prostorů. Snažím se dodržovat:

  • pokud má třída ze jmenného prostoru A\B závislost na třídě ze jmenného prostoru A\C, neměla by žádná třída z A\C mít závislost na A\B
  • třídy ze jmenného prostoru A\B by neměly mít závislost na třídě z prostoru A\B\C (tohle berte s rezervou)

p.s.: neberte prosím tento článek jako dogma, jde jen o zachycení aktuálních myšlenek

clock 19. 4. 2011 pencil PHP comments Komentáře: 7


phpFashion © 2004, 2012 David Grudlo webu

Pokud není uvedeno jinak, podléhá obsah těchto stránek licenci Creative Commons BY-NC-ND Creative Commons License BY-NC-ND

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.