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:
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()
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?
def p():
if pearl_here():
grab()
while front_is_clear():
move()
p()
def recollir_si_hi_ha_perla():
if pearl_here():
grab()
while front_is_clear():
move()
recollir_si_hi_ha_perla()
El títol p() , no vol dir res!
En canvi, el títol recollir_si_hi_ha_perla() ens explica molt bé què volem fer.
def anar_i_deixar_perla():
while front_is_clear():
move()
drop()
anar_i_deixar_perla()
def avançar_fins_a_paret():
while front_is_clear():
move()
# Cada acció és independent i reutilitzable.
avançar_fins_a_paret()
drop()
⏱ A curt termini
- Trobes errors més de pressa. Amb
avançar_i_recollir()saps exactament on mirar. Ambf()ibb()has de llegir funció per funció fins a entendre qui fa què. - Modifiques en un sol lloc. Vols que en Karel deixi dues perles en lloc d'una? Canvies la definició de la funció i el canvi s'aplica arreu. Amb codi repetit, hauries de buscar i modificar cada còpia.
- Rellegeixes el teu codi l'endemà.
while front_is_clear(): avançar_i_recollir()s'entén d'un cop d'ull.
📅 A mig termini
- Reutilitzes el que ja has escrit. Tens
recollir_si_hi_ha_perla()d'un repte anterior? La copies directament al repte nou. Funciona sense errors, sense reescriure res. - Construeixes comportaments complexos.
avançar_fins_a_paret()+recollir_si_hi_ha_perla()+turn_around()combinades donen un programa sofisticat llegible en tres línies. - El codi s'adapta sol. Si el món canvia —corredor més llarg, més perles— el teu codi net sovint no cal tocar-lo. El brut, sí.
🌍 A llarg termini
- Pots compartir-lo. Un company llegeix
while front_is_clear(): avançar_i_recollir()i l'entén sense que li expliquis res. El codi brut necessita una explicació verbal. - El codi es llegeix molt més que no s'escriu. En el món professional, el mateix codi el llegeixen desenes de persones durant anys. Escriure'l net és un acte de respecte cap als qui vindran després (incloent el tu del futur).
- Col·laborar es torna possible. Sense noms clars i funcions petites, treballar en equip en un mateix projecte és un caos.
En resum, tres regles simples:
- No dupliquis codi.
- Posa noms que expliquin bé el que fas.
avançar_i_recollir()sempre és millor quefer_cosa(). - Cada funció, una idea. Quan escrius una funció, ha de ser per aconseguir un sol objectiu, i no per fer tres coses alhora.
Exercici. Netegem el codi
while. El resultat ha de ser el mateix: en Karel ha de recórrer tot el corredor i recollir totes les perles.
Codi brut que has de netejar:
# ✗ NO copiïs això — reescriu-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()
Pista: crea una funció avançar_i_recollir() que faci el move() i el if pearl_here(): grab(). Després usa un while front_is_clear(): per cridar-la tantes vegades com calgui, sigui quin sigui el corredor.
Noms i estructura
while. Reescriu-lo net.
Codi brut que has de netejar:
# ✗ NO copiïs això — reescriu-lo net!
# Problema 1: f i g no diuen res sobre el que fan
# Problema 2: els tres move() s'haurien d'expressar amb while
def f():
turn_left()
turn_left()
turn_left()
def g():
if pearl_here():
grab()
move()
move()
move()
f()
move()
g()
Pista: canvia els noms de f i g per noms que descriguin el que fan. Afegeix una funció avançar_fins_a_paret() que usi while front_is_clear(): move() en lloc dels tres move() explícits. Recorda que turn_right() existeix com a instrucció directa si vols simplificar el gir.
Neteja total
turn_left() que es podria fer en una sola instrucció. Troba tots els problemes i reescriu el codi completament net.
Codi brut que has de netejar:
# ✗ NO copiïs això — reescriu-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()
Set problemes a corregir:
- Les funcions
aa,bb,cc,dd,ee,ffno expliquen res amb els seus noms. cc()fa dues coses alhora: avançar i recollir. Viola la regla «una funció, una idea».ff()fa dues coses alhora: avançar i deixar una perla. Mateixa violació.dd()usa dosturn_left()per fer mitja volta, quan existeix la instruccióturn_around().- Els set
cc()consecutius s'han de substituir per unwhile front_is_clear():. - Els set
ff()consecutius s'han de substituir per unwhile front_is_clear():. - Les funcions
aaibbgairebé no calen si defineixes bé les funcions compostes.