Capítol 10

Codi net

En aquest capítol expliquem com pots escriure "codi net"

No sempre és bona idea fer... copia-enganxa

Aquí tens dos programes que fan exactament el mateix. Fixa't en les diferències:

✗ Codi brut
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
✓ Codi net
def avançar_i_recollir():
    move()
    if pearl_here():
        grab()

while front_is_clear():
    avançar_i_recollir()

El "codi brut" és molt llarg! I, a més, si vols canviar alguna cosa, és complicat i et pots equivocar en alguna línia.

El "codi net" és molt més senzill, i es llegeix millor. És molt fàcil fer algun canvi o millora.

Els noms que posem, els hem de pensar bé

Aquí tens dos programes que fan el mateix: en Karel recorre un corredor i recull cada perla que troba. Fixa't en la diferència... la veus?

✗ Noms que no expliquen res
def p():
    if pearl_here():
        grab()

while front_is_clear():
    move()
    p()
✓ Noms descriptius
def recollir_si_hi_ha_perla():
    if pearl_here():
        grab()

while front_is_clear():
    move()
    recollir_si_hi_ha_perla()

El nom p() no vol dir res!
En canvi, el nom recollir_si_hi_ha_perla() ens explica molt bé què volem fer.

Cada funció, una sola feina

Una funció ha de fer una sola cosa. Així la pots fer servir en molts programes.

✗ Una funció fa dues coses
def anar_i_deixar_perla():
    while front_is_clear():
        move()
    drop()

anar_i_deixar_perla()
✓ Cada funció fa una cosa
def avançar_fins_a_paret():
    while front_is_clear():
        move()

# Aquesta funció serveix per a molts programes
avançar_fins_a_paret()
drop()

avançar_fins_a_paret() només avança. Després, tu decideixes què fa en Karel: deixar una perla, girar…

Per què escriure codi net?

  • 🔍 Trobes els errors més de pressa.
  • ✏️ Fas els canvis en un sol lloc.
  • ♻️ Tornes a fer servir les teves funcions en altres programes.
  • 🤝 Un company entén el teu codi sense preguntar-te res.

Recorda les tres regles:

  • No repeteixis el mateix codi. Fes una funció.
  • Posa noms que expliquin què fa la funció. avançar_i_recollir() és millor que fer_cosa().
  • Cada funció, una sola feina.

Exercici 1. Netegem el codi

Aquest codi funciona, però és molt llarg: repeteix el mateix set vegades.
Escriu-lo net. Fes una funció avançar_i_recollir() i crida-la dins d'un while front_is_clear():.
En Karel ha d'arribar al final i agafar totes les perles.
# ✗ Codi brut: no el copiïs. Escriu-lo net!
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()
move()
if pearl_here():
    grab()

Exercici 2. Noms que expliquen

En Karel ha d'avançar fins al final, girar a la dreta, baixar una casella i agafar la perla.
Aquest codi funciona, però té dos problemes:
1) els noms f i g no diuen res;
2) hi ha tres move() seguits: fes servir un while.
Escriu-lo net.
# ✗ Codi brut: no el copiïs. Escriu-lo net!
def f():
    turn_left()
    turn_left()
    turn_left()

def g():
    if pearl_here():
        grab()

move()
move()
move()
f()
move()
g()

Recorda: tres turn_left() fan el mateix que un turn_right().

Exercici 3. Neteja total

En Karel ha d'agafar les perles del camí, fer mitja volta i tornar enrere deixant les perles.
Aquest codi funciona, però és un desastre. Escriu-lo net.
# ✗ Codi brut: no el copiïs. Escriu-lo net!
def aa():
    move()

def bb():
    if pearl_here():
        grab()

def cc():
    aa()
    bb()

def dd():
    turn_left()
    turn_left()

def ee():
    if not bag_is_empty():
        drop()

def ff():
    aa()
    ee()

cc()
cc()
cc()
cc()
cc()
cc()
cc()
dd()
ff()
ff()
ff()
ff()
ff()
ff()
ff()

Què cal arreglar:

  • Els noms aa, bb, cc… no diuen res.
  • dd() fa dos turn_left(). Això és turn_around().
  • Hi ha set cc() seguits i set ff() seguits. Fes servir while front_is_clear():.