Vyhledávání na webu

4 jednoduché návyky, které okamžitě promění Bash skripty v čistší a čitelnější kód


Ať už jste začátečník nebo ostřílený veterán v psaní Bash skriptů, vždy je prostor na získání nových tipů. Některé z nejlepších se naučíte během několika okamžiků, ale jsou tak přelomové, že změní celý váš přístup. Mám čtyři, které rozplétají vaše Bash špagety do dobře formátovaného díla umění.

Rozprostřete své pipeline do více řádků

Trubka (pipeline) je sekvence příkazů spojených znakem „|“. Každý příkaz zpracovává výstup předchozího. Obvykle lidé píší trubky takto:

fd --type file --exec ls -l | awk '{print $3}' | grep --invert-match '^$' | sort | uniq --count | sed --regexp-extended 's/(root|user)/\1-owned files/'

I když je funkční, postrádá jednotnost a je těžké jej upravovat.

Předchozí příkaz důkladně prohledá aktuální adresář a spočítá počet různých vlastníků souborů. Je záměrně dlouhý, aby ilustroval pipeline. Není to nejelegantnější nebo nejefektivnější přístup, protože stejný výsledek můžete dosáhnout příkazem find . -type f -printf '%u\n' | sort | uniq --count.

Při procházení zdrojového kódu (nebo jakéhokoli textu) hledáme vzorce. V uvedeném příkladu jste pravděpodobně bez přemýšlení hledali znak „|“, který určuje hranice mezi příkazy. Protože však příkazy i hranice existují na stejné horizontální ose, musíme vynaložit úsilí na vizuální hledání těchto rour a pochopení částí mezi nimi. To je zbytečně namáhavé, takže abychom uvolnili naši koncentraci, můžeme navíc využít vertikální prostor:

fd --type file --exec ls -l \
  | awk '{print $3}' \
  | grep --invert-match '^$' \
  | sort \
  | uniq --count \
  | sed --regexp-extended 's/(root|user)/\1-owned files/'

Naše mozky jsou velmi dobré ve vizuálním zpracování, a pokud toho můžeme přímo využít, můžeme uvolnit naši pracovní paměť a soustředit se na záměr. Místo toho, abychom se snažili zjistit, kde každý příkaz začíná a končí, vidíme konzistentní vertikální řadu trubek.

Tento přístup také usnadňuje úpravy v IDE, protože nám často umožňují smazat nebo přesunout celé řádky.

Udělejte své funkce kompozitní

Pojďme předchozí příkaz rozložit, aby byl čitelnější a lépe kombinovatelný.

„Složitelný“ kód znamená, že můžeme sestavovat různé věci z základních prvků (např. funkcí) - stejně jako skládat zeď z cihel.

Nejprve pravděpodobně chceme funkci, která poskytuje surové hodnoty, poté na tom můžeme stavět různými způsoby:

file_stats() {
  fd --type file --exec ls -l
}

Pak chceme vybrat něco z výsledku:

owner() {
  awk '{print $3}'
}

Poté sečtěte výstupy:

tally() {
  grep --invert-match '^$' \
    | sort \
    | uniq --count
}

Nakonec upravte konečnou zprávu, aby byla jasnější:

clarify_ownership() {
  sed --regexp-extended 's/(root|user)/\1-owned files/'
}

Nyní můžeme s těmito novými prvky sestavit potrubí:

file_stats \
  | owner \
  | tally \
  | clarify_ownership

Nejenže je to čitelnější, ale můžeme také měnit jednotlivé prvky. Například:

clarify_date() {
  # Replace a month (e.g., "Feb") with "files modified in <month>."
  sed --regexp-extended 's/([[:alpha:]]+)/files modified in \1./'
}

mod_date() {
  # Modification month column from "ls -l."
  awk '{print $6}'
}

file_stats \
  | mod_date \
  | tally \
  | clarify_date

Funkce „clarify_date“ používá regulární výrazy a POSIX znaky.

Můj kód je přehnaně složitý, ale je to jen pro ilustrativní účely. Ve skutečném světě začnete s většími funkcemi a rozložíte je pouze tehdy, když to bude potřeba.

Upřednostňujte příkazy case před bloky if-else, zejména při rozesílání příkazů

Miluji příkazy switch (case). Podmíněné větvení if-else vypadá nepořádně, ale switche působí stručněji a cíleněji. Normálně je používám na konci svého skriptu k přiřazení argumentů z CLI funkcím (tzv. dispatcher).

Když máme dispečera s dobře pojmenovanými, skladebnými funkcemi, získáme skript s mnohem jasnějším záměrem:

case "$1" in
  dates)
    file_stats \
      | mod_date \
      | tally \
      | clarify_date;;
  ownership)
    file_stats \
      | owner \
      | tally \
      | clarify_ownership;;
esac

Není těžké vidět, co se děje, a stačí nám změnit jen pár řádků, abychom zcela změnili výsledek.

O rozesílačích případů rozvíjím více v jiném článku, který jsem napsal. Popisuje idiomatický (přirozený nebo doporučený) způsob zpracování argumentů CLI. Tu radu můžete kombinovat s tím, co jste si zde přečetli, aby byl váš rozesílač co nejčistší.

Používejte jednorázové příkazy pro krátké podmíněné větve

Více kódu znamená více čtení. Čím méně píšete, tím lépe—pokud je to snadno pochopitelné. Podmínky if jsou jedním z viníků. Když zaplevelují náš kód kontrolou stavu programu (tzv. assertions), mohou vypadat například takto:

if [[ "$something" == "foo" ]]; then
  exit 1
fi

if [[ "$something_else" == "bar" ]]; then
  echo "'\$something_else' cannot be 'bar'"
  exit 1
fi

if ! [[ -f "$file_path" ]]; then
  echo "'\$file_path' must be a file path"
  exit 1
fi

Když vezmete v úvahu všechny podmíněné větve v celém zbytku skriptu, výše uvedený kód působí, jako by vytvářel problémy s čitelností. Jak bylo naznačeno dříve, věřím, že kód by měl být vizuálně snadno prohledávatelný, a můžeme měnit náš styl, abychom toho dosáhli. Například často používám následující přístup pro tvrzení:

[[ "$something" == "foo" ]] && exit 1
[[ "$something_else" == "bar" ]] && { echo "'\$something_else' cannot be 'bar'"; exit 1; }
[[ -f "$file_path" ]] || { echo "'\$file_path' must be a file path"; exit 1; }

Musíte zahrnout ";" před uzavírací "}".

Používám tyto na začátku svého skriptu a funkcí. Když vidím jednorádkový výraz jako tento, vím, že se jedná o asertaci a ne o podmíněný větvení. Pomáhá mi to rychle posoudit, co se děje, aniž bych musel vůbec přemýšlet. Z chybové zprávy dokážu pochopit, co kód znamená, takže nepotřebuji komentáře.


Konzistence je klíčová pro čitelnost. Když používáme opakující se vzory pro drobné detaily, naše mysl je může přeskočit a soustředit se na záměr kódu.

Volba ,jak píšete svůj kód, je klíčovým faktorem a týká se to stejně vizuální estetiky jako funkčnosti. To je pravděpodobně nepopulární názor, ale je založený na vědě. Ano, tvrdím to, protože můžeme najít paralely mezi estetikou kódu a uživatelskými rozhraními.

Věda o návrhu uživatelských zkušeností (pokud jde o uživatelská rozhraní) spočívá v podpoře uživatelů, aby s produktem interagovali požadovaným způsobem. Zahrnuje používání volného prostoru, uspořádání a mnohem více k ovlivnění jejich rozhodnutí. Obecný princip je snížit kognitivní zátěž uživatele a posílat mu jasné signály. U esteticky příjemného kódu usilujeme o totéž, ale pro čtenáře místo toho.

Pište konzistentní, přímý kód a rozlišujte prvky pomocí vizuálních vzorů—posílejte čtenáři jasné signály, stejně jako to dělá dobře navržené uživatelské rozhraní.

Související články