• 10. května 2022

Guard Clauses - zbavení se if-else

Dlouho jsem přemýšlel a zkoušel různé techniky na to, jak být lepší v psaní kódu. Jedna z mnoha technik/postupů je tzv. Guard-clauses technika. Je to velmi jednoduchý přístup ke strukturování funkcí/metod. Pokusím se tuto techniku v krátkosti představit.

Guard-clauses technika nám umožní psát daleko čitelnější a udržitelnější kód.

Tzv. guard by měl být takový boolean výraz, který se vyhodnotí jako False, pokud má v dané funkci/metodě pokračovat. Jinak funkce/metoda skončí.

Pokud je kód správně napsaný s tímto design-patternem, člověk, který na kód kouká poprvé by měl hned vědět, co se stane když...

Proč bychom takové guardy potřebovali?

  • kód nebude tak moc vnořený do sebe -> nebudeme se ztrácet v odsazování
  • odstranění else větví nám způsobí daleko lepší čitelnost kódu
  • výrazy se stanou hrozně jednoduchými a máme kontrolu nad tím, co se stane, když kód selže

Jak to v praxi funguje?

Pokud mám kód, který vypadá např. takto:

def not_guarded_function(request):
   if request.user:
      if request.user.is_authenticated:
         data = request.data
         if data.get('success', False):
            return data
         else:
            raise Exception('Data not valid')
      else:
         raise Exception('User not authenticated')
   else:
      raise Exception('User not found')

Tak si hned můžu všimnout, že se v kódu skoro nedá orientovat. S trochou luštění dokážu zjistit, jaká exceptiona se vykoná po nějakém ifu.

Python nám to trochu usnadňuje odsazováním, ale i tak, orientace je velmi špatná. Nehledě na to, že pokud mám splnit PEP8, tak se za chvilku nevejdu do maximálního počtu znaků na řádek.

Pokud použiji guard-clause pattern, kód se najednou promění v naprosto přehledný a čitelný kód:

def guarded_function(request):
   if not request.user:
      raise Exception('User not found')
   
   if not request.user.is_authenticated:
      raise Exception('User not authenticated')
   
   data = request.data
   if not data.get('success', False):
      raise Exception('Data not valid')
  
   return data

Můžu si hned všimnout, co se stane když... Zmizely nám všechny else bloky - nejsou potřeba!

Kód je přehledný a v hlavní části funkce - neodsazené - je kód, na který se mám soustředit.

Ve výsledku Guard-clauses pattern jenom invertoval podmínky. Stačí velmi málo a váš kód se promění v kód, za který by se nemusel stydět ani nějaký seniornější vývojář.

career

Zajímá tě guard clauses?

Mrkni se, jestli by ses nám nehodil.