2015-05-09 18:45 GMT+01:00 Giovanni Porcari <giovanni.porc...@softwell.it>:

> Sono certo che molti criticheranno il fatto di partire subito definendo
> una classe
> ma per mia esperienza, con questo tipo di approccio un programma iniziato
> per piccole esigenze può crescere bene. Se si buttano giù linee di codice
> affastellate, alla fine tocca buttare tutto e ripartire :D.
>

Io criticherei il fatto che una classe siffatta e' inusabile e viola in
modo necessario piu' o meno ogni regola di programmazione ad oggetti.
Il problema piu' grosso e' che mischia concerns molto diversi: input,
output e logica business. Non solo: lega l'input ad una specifica logica di
input.

Allora, andiamo per gradi: tipicamente vuoi che una classe abbia delle
invarianti. Quanto piu' costante e' la classe, quanto piu' e' facile
mantenere delle invarianti. L'ideale e' avere una classe completamente
immutabile: le invarianti vanno controllate nel costruttore e poi non sono
piu' un problema; inoltre hai garanzie forti sul fatto che qualunque
triangolo hai nel tuo programma rispettera' *sempre* le invarianti
(altrimenti il costruttore avrebbe lanciato un'eccezione).

Viceversa, con un approccio a mutatori ti trovi a doverle controllare ogni
volta che cambi qualcosa (e potenzialmente a dovere introdurre il concetto
di transazione se hai mai due mutatori che vanno chiamati insieme per
mantenere l'invariante. E non e' codice esattamente banale da scrivere
correttamente (immagina proprio un triangolo: immaginatelo mantenuto con
dei vertici, puoi trovarti che modificando un vertice non hai piu' un
triangolo e devi appunto spostare *due* vertici).

Riguardo l'input, hai legato:
1. la fonte di input
2. la strategia di input
3. il formato di input

Non solo quella classe funziona esclusivamente prendendo i dati da standard
input (per come hai definito l'interfaccia), ma presuppone che quello che
hai su standard input sia in uno specifico formato *non* negoziabile. Devi
fare *due* letture (e se ti scordi di farne una, hai rotto verosimilmente
tutto).

Quindi la classe non e' adattabile ne a cose come prendiamo input da file,
ne a cose come invece che prendere i numeri separati da newline li
prendiamo separati da tab nella stessa linea. Per piu' forte ragione, anche
cose tipo prendiamo i triangoli da un database non si possono fare e
nemmeno cose come prendiamo i triangoli da un file json (o da un pickle o
da dove ti pare).

Non solo: anche cose a livello di logica di input piu' di alto livello sono
rotte (per esempio invece che prendere base e altezza -- assumendo che la
base sia un segmento, quindi vuole dire succhiare due punti oppure un
punto, una direzione e una lunghezza -- vuoi prendere invece 3 vertici --
che potrebbero essere in coordinate cartesiani o polari).

L'output ha essenzialmente lo stesso problema (sebbene almeno non abbia
necessita' di due chiamate).

Quindi in altre parole il principiante che si trovasse avendo scritto una
classe del genere non sarebbe nella condizione di potere estendere il suo
codice facilmente per fare cose estremamente banali e legittime. Lo schema
e' talmente lontano da una buona struttura che l'unica cosa che potrebbe
fare sarebbe aggiungere qualche dozzina di metodi ad hoc -- che poi non
sarebbe testare in modo incrociato e si troverebbe con una API fragilissima
--.

Personalmente, rimanendo all'esempio del triangolo, progetterei tutto con
una named-tuple (ma questo e' un dettaglio implementativo) che tiene un
certo set di dati minimi in memoria. Poi ci sabbero dei metodi statici per
prendere diverse strutture (che so... base - altezza, 3 vertici, etc etc
etc). Ovviamente tutto questo richiede di un concetto di Punto
relativamente ben fatto (ancora una volta immutabile, che puoi costruire,
per dire, con coordinate cartesiane oppure polari). A questo punto il
triangolo avrebbe un metodo per darti l'area.

Il resto rimane molto piu' semplice.

-- 
.
..: -enrico-
_______________________________________________
Python mailing list
Python@lists.python.it
http://lists.python.it/mailman/listinfo/python

Rispondere a