Personal tools
Come migliorare il nostro codice con Flake8 e il plugin per Vim

In teoria, teoria e pratica sono uguali, in pratica non lo sono (Einstein)

Dec 11, 2013

Come migliorare il nostro codice con Flake8 e il plugin per Vim

In questo blogpost vi mostrerò brevemente come migliorare la leggibilità e la qualità del vostro codice a costo praticamente zero

Nel lontano 1991, Guido Van Rossum creò uno tra i linguaggi più belli, anche in termini estetici: Python. Dieci anni dopo lo stesso autore, per rimettere un po' d'ordine, creò la Python Enhancement Proposal (PEP) numero 8: Style Guide for Python Code. Non starò ad elencare ora le linee guida, vi invito a leggere direttamente la proposal. Quello che vedremo qui, invece, è come l'applicazione di queste linee guida abbia migliorato stilisticamente, e non solo, il mio codice. Questo blogpost non vuole essere infatti l'ennesima riproposizione del dictat "seguite queste linee perché è giusto così", ma piuttosto un esempio di come la teoria abbia effettivamente migliorato la mia pratica.

Flake8, the modular source code checker

Nel 2010, Tarek Ziadé ha rilasciato la primissima versione di un tool "must have", Flake8. Non che l'idea dietro al prodotto fosse originale, è "solo" l'ennesimo code checker per Python, ma la parte geniale è stata quella di non reinventare la ruota. Flake8 infatti è un wrapper attorno a 3 ottimi code checker già esistenti: PEP8, PyFlakes e McCabe Script. Vediamo ora una brevissima descrizione di questi 3 tool per poi proseguire e capire come utilizzarli nella pratica.

PEP8, Python style guide checker

Pep8 is a tool to check your Python code against some of the style conventions in PEP 8.

Pep8, la cui prima release risale al 2006, è stata la prima e più importante implementazione della proposal corrispondente. La sua installazione e il suo utilizzo sono veramente semplici:

$ pip install pep8
$ pep8 ez_setup.py
ez_setup.py:18:12: E221 multiple spaces before operator
ez_setup.py:18:80: E501 line too long (86 > 79 characters)
ez_setup.py:65:1: W293 blank line contains whitespace
...

L'output di esecuzione mostra la riga/colonna degli errori e warning, un codice identificativo del tipo di errore e una breve descrizione. Normalmente la descrizione è sufficiente per identificarla ma, nel caso non fosse chiaro, basta cercare il codice errore sulla documentazione del prodotto: http://pep8.readthedocs.org/en/latest/intro.html#features.

PyFlakes, passive checker of Python programs

Un altro tool molto utile e nato più o meno nello stesso periodo è PyFlakes. PyFlakes analizza staticamente, quindi in maniera sicura, il codice alla ricerca di vari tipi di errori. Ad esempio, controlla che tutte le variabili utilizzate siano state prima definite, moduli inclusi. Installazione e utilizzo, anche in questo caso, sono immediati:

pip install pyflakes  
$ pyflakes test.py
ez_setup.py:133: 'shutil' imported but unused

mccabe, script to check McCabe complexity

L'ultimo tool di questo set è lo script mccabe che verifica la complessità ciclomatica (o complessità condizionale) del nostro codice. Quest'ultimo tool in particolare è stato quello che ha migliorato maggiormente il mio modo di scrivere codice. Nel 1976,  Thomas J. McCabe teorizzò che la complessità di un metodo/modulo/funzione o classe potesse essere misurata empiricamente contando il numero di cammini linearmente indipendenti di esecuzione di un blocco di codice. Intuitivamente questo numero è uguale al numero ottimale di test che dovrebbero essere scritti per una copertura completa di un blocco di codice. Un modo semplice e veloce per sapere la complessità ciclomatica di un blocco di codice è dato da:

π+ 1 con π = il numero di punti decisionali (es. IF, FOR, WHILE etc.) contenuti nel programma.

Ad esempio:

if( c1() )
f1();
else
f2();

if( c2() )
f3();
else
f4();

La complessità di questo blocco di codice è 3 (2 * Num. costrutti + 1). Nella sua formulazione iniziale, McCabe consigliava ai programmatori di contare la complessità dei propri blocchi di codice e di mantenerla sotto la soglia di 10. Studi statistici hanno infatti dimostrato che all'aumentare della complessità di un blocco di codice, la probabilità di presenza di errori ha un aumento non lineare. Nel tempo la soglia di complessità 10 è stata sostanzialmente accettata come una buona metrica, ma è sempre possibile avere una soglia più alta (ma mai superiore a 15) se ci sono specifiche motivazioni.

Vim e Flake8

Nonostante questi siano ottimi strumenti, il programmatore medio è pigro, e io non faccio eccezione in questo. Essendo ben conscio di questo fattore, ho installato nel mio ambiente di sviluppo (vim) un plugin che forza l'esecuzione di flake8 a ogni salvataggio. Grazie al mio fidato Vundle è stato molto semplice, ho aggiunto nel file .vimrc la seguente linea:

Bundle "nvie/vim-flake8"

e poi ho lanciato il comando:

:BundleInstall

Fatto! Ora configuriamo qualche parametro, aggiungendo queste poche righe al nostro file .vimrc:

let g:flake8_builtins="_,apply"
autocmd BufWritePost *.py call Flake8()
let g:flake8_ignore="E501,E128,E702"
let g:flake8_max_complexity=8

Due note sul nuovo riquadro: si comporta come una window di vim. Può essere chiusa con :q e, cliccando sulla linea dell'errore oppure spostandoci sopra con il cursore e poi premendo invio, il cursore viene spostato direttamente alla linea dell'errore nel nostro codice.

Sublime Text e Flake8

Per chi di voi utilizza Sublime Text 2 (nessuno è perfetto...) è ovviamente disponibile il plugin di integrazione. Per installarlo basta:

- aprire sublime text

- CTRL+SHIFT+p (o su Mac COMMAND+SHIFT+p)

- digitare "install" per lanciare il package manager di sublime

- cercare "flake8".

Fatto! Per configurarlo andate in "Preferences -> Package Settings -> Python flake8 lint. In particolare consiglio di abilitare il check della complessità che di default è disabilitato, sostituendo la seguente linea:

"complexity": -1,  

con

 "complexity": 10,

Continuous integration e Flake8

Un'altra applicazione molto interessante di flake8 è la sua integrazione in un qualsiasi sistema di continuous integration come ad esemio Travis-ci:

language: python
python:
- "2.5"
- "2.6"
- "2.7"
- "3.2"
- "3.3"
install: pip install flake8 --use-mirrors
script:
- python setup.py test
- flake8 -v .

Conclusioni

Anche se a prima vista l'utilizzo di strumenti come flake8 può sembrare un po' "sproporzionato", vale la pena di seguire le sue indicazioni perché migliora stilisticamente il nostro codice grazie a pep8, ci fa risparmiare tempo con i controlli di pyflakes e ci salva da complessità eccessive (e quindi bug!!) con il check della complessità di McCabe. In sintesi, uno dei nostri migliori amici come Python developer!

Filed under: ,
comments powered by Disqus