Tento blog je sice určen pro mírně pokročilé, ale můžou na něj zabrousit i naprostí začátečníci nezkušení nejen v PHP, ale v programování vůbec. Postupně proto zveřejním několik velmi jednoduchých tipů, které můžou začátečníkům pomoci. Ale upřímně řečeno, některé z nich by si měli vzít k srdci i ostřílení mazáci. Některé z těchto rad naleznete v trochu jiném podání i v mé knize, stejně jako spoustu dalších.
Máte kousek kódu, který dělá skoro přesně to, co potřebujete, tak ho zkopírujete jinam, trochu upravíte a je hotovo. Podle mě to je jedna z největších chyb, kterou můžete udělat. Pro údržbu a rozšiřování kódu je to hotová katastrofa – když později chcete něco opravit nebo vylepšit, tak to musíte udělat na mnoha místech. Obvykle nemůžete použít ani náhradu textu, protože kód je na různých místech různě upraven. Zkopírovaný kód je také velmi náchylný k chybám – řekněme, že chcete použít přesně ten stejný kód, jenom potřebujete vyměnit název proměnné. Uděláte to na dvou místech, ale třetího si nevšimnete. Tuhle chybu je obvykle těžké odhalit, obzvlášť pokud zkopírovaný kód použijete ve stejné funkci, kde původní proměnná pořád existuje.
Správné řešení je obvykle kód zobecnit, vyčlenit ho do funkce nebo metody a tu zavolat ze všech míst, kde je potřeba. Často je také vhodné použít jinou abstrakci. Např. místo takovéhoto kódu:
<?php $result = $db->query($query); if ($result === false) { trigger_error($db->error, E_USER_ERROR); return false; } foreach ($result as $row) { // zpracování řádek } ?>
… je lepší chyby vyházet jako výjimky rovnou v metodě query()
a dál si jich nevšímat:
<?php foreach ($db->query($query) as $row) { // zpracování řádek } ?>
Pro základní obraty je také vhodné používat makra v editoru. Já mám nadefinovaných kolem 300 maker, z nichž některé používám neustále a některá jsem si nadefinoval třeba jenom dočasně. Např. mám jednoduché makro, které před označený text vloží if () {
, označený text odsadí, za něj vloží }
a kurzor umístí do ()
. Nebo mám trochu složitější, které vloží tento kód:
<?php foreach (glob("*") as $filename) { $file = file_get_contents($filename); } ?>
Používám to často v jednoúčelových skriptech, kde žádnou abstrakci nemám k dispozici a nevyplatí se ji dělat. Nebo mám makro, které vloží tohle (value přijímá jako parametr):
<?php private $value; public function setValue($value) { $this->value = $value; return $this; } protected function getValue() { return $this->value; } ?>
Kurzor se umístí za setValue(
, takže nezapomenu doplnit typehint (ten by makro mohlo přijímat v druhém parametru, když bych ho chtěl dát třeba i do dokumentačního komentáře). Možná změním viditelnost metod, možná některou z nich smažu nebo ze setteru udělám konstruktor. Pointa je v tom, že je rychlejší a bezpečnější smazat vygenerovaný kód, než ho kopírovat odjinud a upravovat. V některých projektech samozřejmě opět můžete použít jinou abstrakci, takže dané metody vůbec nebudete potřebovat.
Zkopírování jedné řádky může být v pořádku, třeba pokud vytváříte prvky pole ve formátu self::TYPE_ => '',
. Ale často i zkopírování jediné hodnoty může způsobit velký problém. Vezměme si tenhle kód:
<?php $offset = 0; $limit = 1000; do { $results = getData($limit, $offset); // zpracování výsledků $offset += 1000; } while (count($results) == $limit); ?>
Co se stane, když se časem rozhodneme limit zvýšit, abychom skript zrychlili, nebo naopak snížit, abychom ušetřili paměť? Pokud zároveň nezměníme i $offset += 1000
, tak v prvním případě některé záznamy přeskočíme a v druhém případě je zpracujeme víckrát. Opět si toho vůbec nemusíme všimnout. Správné řešení je kód změnit na $offset += $limit
nebo $offset += count($results)
, čímž si tyto problémy v budoucnu ušetříme.
Diskuse je zrušena z důvodu spamu.