Richard Šerý
4.2.2014

Druhá obtížná věc



„There are only two hard things in computer science: cache invalidation and naming things.“ Phil Karlton

Také máte občas pocit, že vám kód přerůstá přes hlavu? Snažíte se dlouhé hodiny najít chybu a pak zjistíte, že ji máte celou dobu před očima? Nevím, jestli se těmto situacím dá vyhnout, ale hodně mi pomohlo, když jsem přestal kašlat na názvy proměnných.

Naming-Things-2

Abych uvedl věci pravou míru – programuju skoro výhradně v JavaScriptu, což pro spoustu lidí není opravdové programování. Vzhledem k dynamické povaze JS je však snadné udělat kód zcela nečitelný a pokud si chce člověk uchovat zdravý rozum, je potřeba programovat mnohem disciplinovaněji než například v Javě. Zvlášť implicitní typové konverze dokáží člověku pěkně zavařit, pokud si nedá pozor.

Kolega nedávo našel a spravil chybu, která dělala potíže dlouhé týdny a stále unikala odhalení. Zjistil, že metoda „getValidJSON“ nevrací vždy tak docela validní JSON, ale kvůli jejímu pojmenování nikoho nenapadlo to prověřovat. Po přejmenování na „getInvalidJSON“ bylo hned zřejmé, kam je potřeba doplnit adaptéry, aby to začalo fungovat. Pak už byla oprava otázkou pár hodin práce.

Programování jako matematická disciplína

V sedmdesátých a osmdesátých letech 20. století se rozšířil názor, že programování je odrůdou matematiky, nebo matematické logiky. A když v matematice může být obsahem proměnné „x“ cokoli, proč by to tak nemělo být i ve Vašem programu? Myslím že tento způsob uvažování velmi silně přispěl k jevu zvanému „softwarová krize“ a i dnes působí nedozírné škody. Protože software má dva konce: na jednom konci je počítač, který funguje víceméně logicky, na druhém konci člověk – a ten funguje jinak. Zkuste si to sami: vezměte nějaký program a všechny identifikátory změňte třeba na jména svých přítelkyň (viz článek na daily WTF), nebo třeba filmových postav, pokud tolik přítelkyň nemáte. Počítač tomu porozumí snadno. Jak se ale takový software bude líbit programátorům?

confusing-sign-do-not-read

Zavádějící názvy

Pracoval jsem kdysi na projektu, kde byla entita nazvaná „Person“. Nejdříve se do ní ukládaly jen smlouvy, pak přibyly další údaje jako adresa apod. Na první pohled běžná věc, ale brzy nastaly potíže. Proč „Person“ nemá „jméno“ a „příjmení“ ale jen „název“? Proč je IČ povinná položka? Brzy se ukázalo, že se nejedená o běžnou osobu ale o tzv. „Právnickou osobu“, pojem „Person“ vznikl nesprávným překladem z češtiny. Tou dobou se už ale entita „Person“ používala např. pro registraci uživatelů. Vyžádalo si několik dní práce, než jsme to dali do pořádku a oddělili „fyzické osoby“ od „právnických osob“. Náklady na malý vývojový tým bývají minimálně 30 000 Kč na den, někdy ale i mnohem víc. V tomto případě zmatek v pojmech stál jistě více než sto tisíc Kč.

Vzal jsem si z toho ponaučení: když něco pojmenovávám, musím si dát si pozor na denotaci i konotace. Jinak to může vyjít dosti draho.

Zmatek v pojmenování

Pokud chcete opravdu účinně sabotovat svůj projekt, existují dvě metody které napáchají maximální škody při minimálním úsilí: můžete buď pojmenovat dvě různé entity stejným názvem, nebo naopak jedné entitě dát dva různé názvy. Oba případy jsou vidět v následujícím kódu:

 /** * This should delete user: */ 
function deleteUser(number) { 
  var records = getPersonalRecords(); 
  if (records.length > number) {  
    deletePerson(records[number].number); 
  } 
});

 

V kódu figuruje jen jeden objekt (nazývaný postupně „user“, „record“, „personalRecord“ a „person“). Dále je tu pořadové číslo záznamu nazvané „number“, identifikační číslo osoby se ovšem jmenuje také „number“. Jak vidno, nedá to ani moc práce a na pořádný průšvih je zaděláno.

Naming-Things-1

Příliš obecné názvy

Tento nešvar je tak rozšířený, že se dostal do mnoha frameworků a dokonce i přímo do programovacích jazyků. Princip je jednoduchý: když je pojmenování příliš všeobecné, nic neznamená. Nejčastěji bývají problémem obecné pojmy jako je například „item“, „identifier“, „manager“, „record“ atd. Objektové programování nám potom rozšířilo slovníček hrůz o věci jako je „this“, „self“, „object“ či „klass“ (ne, bohužel nejde o překlep). Proměnné, které se jmenují „this“, „item“ nebo „data“ mohu už rovnou pojmenovat „Fanda“, „Pepa“ a „Standa“, kód bude skoro stejně srozumitelný.

NeuvěřitelněDlouhéSloženinyKteréVámSežerouMozek

Jasně, čím přesnější a méně obecný název, tím bude kód čitelnější. Ale složeniny typu

private NewsArticleWithImageAndLink selectedVisibleNewsArticleWithImageAndLink

 

jsou většinou z hlediska čitelnosti kódu zlo. Jestliže se v celé aplikaci používá jen pár „Article“ objektů, zvažte jestli by se čitelnost nezlepšila, kdybyste napsali prostě jen

private Article selectedArticle 

 

Zkratky

Někdy je použití zkratek zcela namístě. Proměnné typu „dialogHtml“, „articleDto“ nebo „isbnString“ by byl nesmysl nějak rozepisovat. Pokud ale zkratka není tak rozšířená, že jí pochopí ihned každý, třikrát si rozmyslete, jestli jí raději nerozepsat. A ještě taková drobnost: používáte-li „camelCase“, pozor na přesný zápis. Technicky vzato, zápisy „innerHTML“ a „getID“ jsou špatně, zkratky se zapisují jako všechna ostatní slova, tedy „innerHtml“, „getId“. Realita je ale složitější a různé paskvily se objevují i v kódu, se kterým nemůžete nic dělat. Když už to tedy je špatně, držte to aspoň konzistentně špatně, aby nedocházelo k situacím, kdy máte v jednom kódu „getId“, „getID“ i „getid“.

Maďarská notace

Aby bylo jasno: když pracuji na projektu, který používá maďarskou notaci, používám maďarskou notaci. Jakékoli diskuse na téma „používám lepší konvenci než zbytek týmu“ jsou projevem přebujelého ega. Pokud ale začínáte projekt na „zelené louce“, doporučil bych maďarskou notaci nezavádět, protože prefixy snižují čitelnost. Když má každý objekt prefix „o“ a každý interface prefix „i“ (což není výmysl, opravdu jsem se s tím setkal), člověk si za chvíli připadá jak u blbejch na dvorku.

Naming-Things-3

Tím nechci říct že by se typ neměl uvádět v názvy proměnné. V Javě to není zas až tak důležité, ale v jazycích se slabou nebo žádnou typovou kontrolou je to nesmírně užitečné. Považuji ale za praktičtější typ uvádět na konci identifikátoru, tedy např. „userNameString“, „personDto“, „userNameElement“ nebo „changePropertyEvent“.

Inteligence je handicap

Čím chytřejší vývojář, tím složitější kód dokáže napsat a odladit. Chytří lidé dokáží myslet abstraktně, namapovat si v hlavě pojmy na úplně nesouvisející slova, pamatovat si spoustu zkratek… To je dělá, až na čestné výjimky, nezpůsobilé správně pojmenovat věci. Bohužel to většinou odnášíme my, inteligencí méně obdaření jedinci. Ale i když jste teď ti chytří, uvědomte si jednu věc: možná se ke svému kódu budete muset vrátit za pět či deset let. A to už se na vás podepíše věk, alkohol, televizní seriály, Facebook a objektově orientované programování. Myslete na to a pište kód tak, aby ho pochopilo i malé děcko, senilní stařík či vy po deseti letech práce v korporaci.

Vaše emailová adresa nebude zveřejněna

Komentáře

Děkujeme za váš komentář
Další
  • Buďme rádi, že jazykem pro vývoj je angličtina a nikoliv němčina. Rechtsschutzversicherungsgesellschaften nebo Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz jsou skutečnými lahůdkami.

  • Lukyn

    s tim innerHtml musim nesouhlasit ... HTML je zkratka, ktera se pise velkym ...

  • Lukyn: Nesouhlasit můžete, ale budete v nevýhodě, protože Vaše názvy proměnných pak budou hůře srozumitelné a nebudou odpovídat konvenci. Např. název "redIcbnHtmlButton" je mnohem čitelnější než "redICBNHTMLButton". Existuje jediná výjimka z camelCase, zavedená Microsoftem: když má zkratka jen dvě písmena, píší se obě uppercase - viz http://msdn.microsoft.com/en-us/library/141e06ef%28v=vs.71%29.aspx

  • Natix

    Javovské date & time API je krásným příkladem, kdy názvy tříd a metod vůbec neodpovídají tomu, co ve skutečnosti znamenají: Calendar calendar = Calendar.getInstance(); Date dateTime = calendar.getTime(); long millis = dateTime.getTime();

  • Radovana

    Zmierila som sa s tým, že niekedy musím pomenovať premenné alebo triedy aj po nemecky (keď ide o odbornú terminológiu a preklad do angličtiny by iba znížil čitateľnosť kódu), vtedy proste používam camelCase aj v nemčine.

  • Jakub Ferschmann

    Viděl jsem kód, kde autor vždy používal jen dva názvy proměnných: bagr a negr :D

  • Metalíza

    1. Výborný článek, díky za něj. Je fajn vědět, že nejsem sám, komu ty výše zmíněné našvary vadí. Asi ho budu používat jako referenční materiál pro svou argumentaci:-) Ten Person mi totiž cosi připomněl - ale to souviselo s projektovým slovníčkem a neexistencí kvalitní analýzy celkově:-( 2. Ta otázka pod článkem je zavádějící, protože automaticky předpokládá, že všichni ostatní (krom Vás) pojmenovávají věci špatně. A zase na druhou stranu: kategoricky prohlásit, že pojmenovávám věci vždy správně - to mi přijde příliš troufalé. Já si sice myslím, že pojmenovávám věci správně (resp. se snažím tomu věnovat náležitou péči), ale jestli se mi to vždy povedlo na 1 ... no, ruku do ohně bych za to asi nedal:-)

  • Metalíza - berte to takhle: 18 lidí hlasovalo, že pojmenovávají věci vždy správně. A já mezi nimi nejsem, ač jsem taky hlasoval ;-) Natix, Radovana, Jakub: jo, to je peklo :-)

  • Milos

    V matematice nemůže být v x cokoli. Pokud tam má být reálné číslo, nemůžu tam dát trojúhelník jako v netypovém programovacím jazyku. Navíc je často určen definiční obor funkce, např. 1/x nebo sqrt(x) v oboru reálných čísel. Se jmény v programování máte pravdu. Programování v Basicu s jednopísmennými proměnnými byl pocuc. Konzistence jmen: Začínám , kde se vyskytuje klient_adresa, klient_ulice, adresat_adresa, form_adresa, db_adresa Nebo že jde o ulici ulice_trvalá, ulice_korespondenční, ulice firma. Nebo form.ta.ulice, form.ka.ulice ..... Postupně se člověk poučí a vybere si nejlepší způsob, ale musí ho dodržovat konzistentně. Zažil jsem programy nebo skupiny programů, kde byl jmenný chaos. Někdo pojmenoval proměnné podle jmen v DB, stejný člověk v jiném programu podle byznys názvu (ale zase nekonzistentně). To je balada upravovat. Název this/self je poměrně jasný. Tváří se a je zděděný. Nemám rád používání členských proměnných v podtřídě. Maďarská notace měla význam dříve, když nebyla podpora od IDE. Mě se nelíbí atributové pojmenování tříd – např. v javě List, ArrayList, LinkedList – na druhou stranu ListArray nebo ListLinked by mohlo vyjadřovat něco sémanticky jiného, takže by se musely třídy jmenovat ListByArray...

  • DcZXcZcxZcx

    ty nazvy promennych bagr a negr mi pripominaji metasyntakticke nazvy jako foo, bar.... http://en.wikipedia.org/wiki/Metasyntactic_variable

  • Milos: Nemyslím si že jmenné konvence jsou otázkou toho co je "nejlepší" nebo na co jsem si zvykl. Myslím že je to spíš otázka ohleduplnosti a srozumitelnosti.

  • Metalíza

    @Lukyn: tak to jste nepochopil CamelCase (resp. jeho "lower" variantu camelCase):-) Princip CamelCase (a camelCase) je v tom, že MĚNÍ velikost písmen na základě několika pravidel: 1. U každého slova všechna písmena vyjma 1. změní na malá a to 1. písmeno změní na velké. 2. V případě lower varianty (camelCase) u 1. slova v sousloví to 1. písmeno změní také na malé. 3. Zaužívaná zkratka (HTML, XML, DTO, ...) se považuje také za slovo (postavené na roveň ostatním z běžného jazyka), takže se taky transformuje podle výše uvedených pravidel.

  • Milan Lempera

    Pěkné shrnutí problematicky pojmenování. Jen u té maďarské notace bych byl o něco přísnější ;-)

  • Natix

    Když je řeč o maďarské notaci - dalším zlem je věc, kterou osobně nazývám "hebrejskou notací" - viz http://www.andrewpetermarlow.co.uk/personal/ranting_hebrew.html