Lekce 8 - Nejčastější chyby Swift nováčků - Umíš pojmenovat proměnné?
V předešlém cvičení, Řešené úlohy k 7. lekci Swift, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním Swift tutoriálu si ukážeme první tzv. dobré praktiky pro programování ve Swift. Nejen nováčci je často porušují a zanáší tak do svých programů zbytečné chyby, možná je děláš také?
Slovo senior programátora
Gratuluji ke zdolání prvních lekcí Základních konstrukcí jazyka Swift!
Materiál pro dnešní lekci jsem sestavil na základě 20letých zkušeností s programováním. Jako šéfredaktorovi a lektorovi mi rukama prošly stovky, možná tisíce zdrojových kódů vytvořených komunitou. Nebylo těžké si všimnout, že většina z nich, ačkoli funguje, obsahuje zbytečné chyby, které se navíc stále dokola opakují. Chyby kupodivu často dělali jak nováčci, tak zkušenější programátoři a i já jsem je dělal, když jsem začínal.
Došel jsem k tomu, že základním a mylným předpokladem je:
✗ Program je správně, pokud funguje.
Programy a domy
Pokud stavíme dům, že se nám líbí a nefouká do něj neznamená, že je správně. Dům totiž musí mít promyšlenou architekturu a pokud nemá základy, za pár let se nám začne sesouvat.
Programování je často přirovnáváno ke stavebnictví právě z ohledu na architekturu, zde ovšem tu softwarovou. Vysvětleme si proč.
Lidský mozek dokáže najednou pracovat jen s určitým omezeným množstvím informací. Zjednodušeně můžeme říci, že pokud je program nepřehledně napsaný, od určité chvíle by musel programátor udržet v hlavě více věcí, než člověk vůbec dokáže. Přidávání dalších funkcí do takového programu pak vždy způsobí, že v aplikaci vznikne chyba. V praxi to dopadá tak, že hobby projekt autora "přestane bavit" nebo komerční projekt zkrachuje, protože je "už moc složitý".
Uveďme si ještě jiný příklad - Když bude naše domácnost uspořádaná tak, že bude kladivo v lékárničce, která bude umístěna ve sklepě, asi těžko v ní budeme schopní efektivně fungovat. Ačkoli tento příklad zní absurdně, jeho alternativy v podobě programů vznikají denně.
Kdy je program správně?
To je snadné. Program je správně, pokud:
- funguje,
- dodržuje dobré praktiky a
- je otestovaný.
Všimněte si, že funkcionalita z pohledu uživatele programu představuje jen 1/3 kritérií kvality programu. Podobně, jako funkčnost domu z pohledu bydlícího představuje asi jen zlomek jeho reálné kvality z hlediska stavařiny.
Právě o porušování dobrých praktik a kvalitě kódu se dnes budeme bavit. Záleží nám na tom, abyste byli opravdu dobří, proto těchto lekcí naleznete napříč našimi kurzy ještě několik.
Jak správně pojmenovávat proměnné?
Říká se, že 10% času něco programujeme a 90% času pro to vymýšlíme název Jedná se samozřejmě o nadsázku, nicméně vtip naráží na nutnost strávit určitý čas nad vymýšlením názvů proměnných. To aby každý včetně nás vracejících se po pár měsících k vlastnímu kódu, pochopil, k čemu ona proměnná slouží. Obecně se dá spolehnout na jednoduché pravidlo:
Proměnné vždy pojmenováváme podle toho, co obsahují, nikoli podle toho, k čemu v programu slouží.
Porovnejme následující 2 kódy:
✗ Špatně
let vypis, text2 : String var pole = [Int]() let foo, bar, x, vypocet : Int
✓ Správně
let nazev, jmeno : String var odpovedi = [Int]() let i, j, bonus, celkovyBonus : Int
Oba kódy vytvářejí proměnné pro jednoduchý konzolový kvíz. U
prvního příkladu není vůbec jasné, co některé proměnné obsahují,
např. pojmenovat proměnnou pole
má asi stejnou vypovídací
hodnotu, jako bychom ji pojmenovali promenna
.
Častá chyba je, že chceme např. uložit výsledek
nějakého výpočtu a proměnnou pojmenujeme
vypocet
. Výpočet s proměnnou ovšem vůbec nesouvisí, to je
nějaká akce (děj), proměnná obsahuje vždy
hodnotu (výsledek děje). Tou je zde v případě kvízu
celkovyBonus
. Podobně je v prvním kódu pojmenovaná proměnná
vypis
, protože ji někde vypisujeme. Z druhého kódu ale reálně
vidíme, že obsahuje název kvízu.
Ruku na srdce - kdo z vás by pochopil, že kód vlevo je program na kvízy?
Také nikdy nepojmenováváme proměnné pomocna
nebo pom
apod.
Pozor na "Czechglish" a diakritiku
Ve zdrojovém kódu je na naší úrovni začátečníků jedno, jakým jazykem budeme pojmenovávat proměnné (pokud tedy nepošleme Angličanovi kód v češtině).
Proměnné v jednom projektu pojmenováváme jedním jazykem a pokud česky, tak bez diakritiky!
Opět si ukažme příklady:
✗ Špatně
let zpráva = "Čau!" let count : Int
✓ Správně
let zprava = "Čau!" let pocet : Int
Nebo:
let message = "Čau!" let count : Int
V identifikátorech (např. v názvech proměnných) nikdy nepoužíváme háčky a čárky. V hodnotách v nich uložených je to již samozřejmě v pořádku.
Přestože moderní jazyky podporují kódování UTF-8 i v identifikátorech, lze velmi snadno na háček nebo čárku zapomenout a používáme pak jinou proměnnou! Navíc soubor se zdrojovým kódem může zpracovávat aplikace, která jej nepodporuje, a typicky se to i časem stane (např. je občas problém zobrazit diakritiku v příloze mailovým klientem apod.).
Víceslovné proměnné
Dnešní aplikace jsou stále složitější. Často se stane, že by jedno
slovo nestačilo k popisu toho, co je v proměnné uloženo. Pak je výhodné
použít více slov. Krátké identifikátory z 80. let tak v současných
business aplikacích střídají i poměrně dlouhé názvy jako
userObjectOutputStreamFactory
a podobně.
Takto dlouhý název má ovšem smysl jen ve složité
aplikaci, kde je několik podobných proměnných a proto musíme přidat
další slovo. Nebudeme tedy v Hello world aplikaci vytvářet proměnnou
textSPozdravemHelloWorld
, ale stačí nám tam jen
pozdrav
, pokud tam jiný není
Oddělení slov
Kvůli čitelnosti slova v takovém názvu proměnné musíme nějak oddělit:
- Více slov oddělujeme podle konvence daného programovacího jazyka, ta je
ve Swift tzv.
camelCase
(česky velbloudí notace, kdy každé další slovo má velké písmeno a název pak vypadá jako hrby). V jiných jazycích se může používat např. podtržítko jakosnake_case
a další notace. - Vyhneme se pokud možno číslování proměnných a už vůbec nepíšeme
čísla slovy, ne
pozdrav2
anipozdravDve
. "Dvě" totiž nic neříká o tom, co pozdrav obsahuje.
Ukažme si to na příkladech:
✗ Špatně
let zprava1 : String let zpravaDve : String
Zde není jasné co je uloženo:
let prijato : String // text, bajty, zprava, objednavka, ...? let odeslano : String
A zde je název nečitelný:
let prijatazprava : String let odeslanazprava : String
✓ Správně
let prijataZprava : String let odeslanaZprava : String
Nepoužíváme zkratky
Tuto podkapitolu započněme citací:
Všichni si lámali hlavu, k čemu je ten sloupec
DATNAR
. Až se jednou zjistilo, že je to prej datum narození.
Tato špatná praktika je vlastně opakem víceslovných názvů
proměnných. Nevymýšlíme nesmyslné zkratky, například z názvu
pz
nikdo nepozná, že myslíme prijataZprava
.
Pomůcka může být:
Pokud se na kód podívá někdo jiný než my, měl by přesně vědět, co v které proměnné je.
✗ Špatně
let zp : String let pz : String
✓ Správně
let zprava : String let pocetZprav : String
Jak jsme slibovali, k tématu dobrých praktik se ještě několikrát vrátíme v podobných, spíše odpočinkových lekcích
V příští lekci, Textové řetězce ve Swift podruhé - Práce se znaky, na vás čeká překvapení