Proč v kódu nemixovat tabelátory a mezery

Od Petr Zemek, 2014-07-26

Někdo preferuje mezery, někdo tabelátory. Diskuse o tom, který způsob je lepší, bývají nekonečné, protože každý z nich má své pro a proti a každý programátor to vidí jinak, takže to nemá smysl řešit. V následujícím článku bych však chtěl argumentovat, proč není dobrý nápad v kódu tabelátory a mezery mixovat.

Proč ne?

Protože velikost tabelátoru se liší editor od editoru a programátor od programátora. Typická nastavení bývají zobrazovat tabelátor jako 2, 4, či 8 mezer. Pokud mixujete mezery a tabelátory, tak se kód ve vašem editoru sice může zobrazovat korektně, ale jiný programátor uvidí nepořádek a pomyslí si o vás nepěkné věci.

Pojďme na příklad. Dejme tomu, že máte v editoru nastaveno, ať se vám tabelátor zobrazuje jako 4 mezery. Pak může kód, který mixuje tabelátory a mezery vypadat korektně ( značí tabelátor):

if (shouldMove) {
→   →   target->move();} else {
        target->standStill();   // Zde se k odsazení místo tabelátorů použily mezery.}

Pokud má ale někdo nastaveno, ať se mu tabelátor zobrazuje jako 8 mezer, uvidí nepořádek:

if (shouldMove) {
→       →       target->move();} else {
        target->standStill();  // Zde se k odsazení místo tabelátorů použily mezery.}

Buďte proto svědomitý programátor a nemixujte mezery a tabelátory.

Jazyk Python je pak případ sám o sobě. Pokud v něm budete mixovat tabelátory a mezery, buď vám kód bude vyhazovat výjimku IndentationError, nebo (hůř) bude fungovat, ale bude dělat něco jiného, než očekáváte (např. příkaz se přiřadí do jiného bloku, než vidíte v editoru). Důvodem je, že v Pythonu jsou oproti ostatním jazykům bílé znaky signifikantní ze syntaktického hlediska.

Odsazování pomocí tabelátorů, zarovnání pomocí mezer

Někteří programátoři mixují mezery a tabelátory tak, že k odsazení používají tabelátory a k zarovnání mezery. Příklad:

→    →    collide(getFirstObjectInCollision(),
→    →            getSecondObjectInCollision());  // Zde se k zarovnání použily mezery.

Tento kód se zobrazí korektně nezávisle na nastavení editoru. Je zde však jiný problém: při dalších úpravách, ať už autorem či jinými programátory se často zapomene či dojde k přehlédnutí, co se k odsazení a zarovnání použilo. Pokud pak jiný programátor změní název funkce a zarovná pomocí tabelátorů, nastane opět zmatek:

→    →    collideTwoObjects(getFirstObjectInCollision(),
→    →            →    →    getSecondObjectInCollision());  // Zde se mixují mezery a tabelátory.

Typicky totiž v editoru mezery a tabelátory nejsou vidět, takže se špatně rozlišuje, co je kde. Když si pak kód zobrazí někdo, u koho je tabelátor zobrazován jako 8 mezer, zobrazí se mu toto:

→        →        collideTwoObjects(getFirstObjectInCollision(),
→        →                →        →        getSecondObjectInCollision());  // Zde se mixují mezery a tabelátory.

Takže odsazování pomocí tabelátorů a zarovnání pomocí mezer taktéž nedoporučuji.

Zobrazení mixování mezer a tabelátorů v editoru

Abych se vyhnul neúmyslnému způsobování nepořádku při editaci kódu, tak mám ve Vimu nastaveno zvýraznění mixování mezer a tabelátorů:

" Highlight mixture of spaces and tabs
au BufEnter * hi SpacesTabsMixtureGroup guibg=gray18 guifg=red ctermbg=gray ctermfg=red
au BufEnter * match SpacesTabsMixtureGroup /^ \+\t\+\|^\t\+ \+/

Ukázka:
Ukázka zvýraznění mixování mezer a tabelátorů u mě ve Vimu.

Dále mám ve Vimu na klávese F2 nastaveno zobrazení mezer, tabelátorů a konců řádků v kódu:

" Tell Vim which characters to show for expanded TABs, trailing whitespace,
" ends of lines, and non-breakable space
set listchars=tab:>-,trail:#,eol:$,nbsp:~,extends:>,precedes:<
 
" F2: Toggle the display of unprintable characters
nnoremap <silent> <F2> :set list!<CR>

Hodí se to, když se chci podívat, co přesně za bílé znaky (angl. white space) v kódu jsou:

Ukázka:
Ukázka zvýraznění bílých znaků u mě ve Vimu.

Když edituji cizí kód, tak si pomocí F2 zobrazím, co se k odsazení používá, nastavím si příslušně Vim a vesele edituji. Ve Vimu lze např. k odsazení používat pořád klávesu TAB a nastavit si, zda vám má vložit tabelátor nebo ekvivalentní (nastavený) počet mezer. Lze tak pro každý jazyk/projekt použít speciální nastavení.

Další čtení

Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
11 + 1 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.