Blog post di Avdi Grimm. Opinioni?

Ciao a tutti,
vorrei segnalarvi questo blog post di Avdi G. che ho trovato molto
interessante e con cui concordo appieno forse in virt del mio passato
background Java.

Voi cosa ne pensate? Paolo Perrotta ha fatto qualche commento riguardo
ai pattern durante il suo talk e mi sarebbe piaciuto molto espandere
l’argomento di quale sapore abbiano in salsa ruby :slight_smile:

Ciao e grazie!

2011/8/24 Gian Carlo P. [email protected]:

Ciao a tutti,
vorrei segnalarvi questo blog post di Avdi G. che ho trovato molto
interessante e con cui concordo appieno forse in virtù del mio passato background
Java.

Your Code is My Hell - avdi.codes

Voi cosa ne pensate? Paolo Perrotta ha fatto qualche commento riguardo ai
pattern durante il suo talk e mi sarebbe piaciuto molto espandere l’argomento di
quale sapore abbiano in salsa ruby :slight_smile:

A me suona molto vera "The warnings Ruby produces are dumb; just
disable them.”.
Da qualche parte verso il 2006 la comunità ha sostanzialmente deciso
che i warning non servono.

Mai provato a lanciare una cosa banale come

ruby -w -Ilib:test test/unit/model_test.rb

?
Molto illuminante, non solo per quel che riguarda rails :slight_smile:


twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com www.circleme.com

A me suona molto vera "The warnings Ruby produces are dumb; just
disable them…
Da qualche parte verso il 2006 la comunit ha sostanzialmente deciso
che i warning non servono.

Mai provato a lanciare una cosa banale come

ruby -w -Ilib:test test/unit/model_test.rb

?
No, ma ho provato adesso :slight_smile: OMG! una pletora di “warning: loading in
progress, circular require considered harmful” e warning…

A corollario aggiungo questo link

Molto illuminante, non solo per quel che riguarda rails :slight_smile:

Anche io lo penso :slight_smile:

Per esteso penso che, pi che i design pattern del GoF per s (che sono
solo esempi di buon OOAD ma che non sempre si applicano a tutti i tipi
di linguaggi), il vero valore sia dato dai principi di OOAD (OCP SRP LSP
ISP DIP). In effetti i differenti diversi livelli di scrittura del
codice ruby overo dallo scripting procedurale passando dall’OO fino
quasi a funzionale fanno s che sembrino meno importanti. Inoltre un
framework come rails che invita ad utilizzare molte buone pratiche ed
imposta il codice nei suoi binari (pattern? approcci?) architetturali
(come REST) e pratici (i.e. una buona e standardizzata suddivisione
delle directory) spesso permette un risultato accettabilmente buono o
per lo meno manutenibile anche con una limitata attenzione ai principi
ed al testing su progetti sufficientemente piccoli.
Quando il progetto cresce ecco che se il codice non sufficientemente
“clean” allora sono dolori.

Cosa ne pensate?

Ciao!

gk

Piccola precisazione a ci che ho detto

Per esteso penso che, pi che i design pattern del GoF per s (che sono solo
esempi di buon OOAD ma che non sempre si applicano a tutti i tipi di linguaggi),
il vero valore sia dato dai principi di OOAD (OCP SRP LSP ISP DIP). In effetti i
differenti diversi livelli di scrittura del codice ruby overo dallo scripting
procedurale passando dall’OO fino quasi a funzionale fanno s che sembrino meno
importanti.

fanno s che sembrino meno importanti ma NON sono per nulla meno
importanti!

Rimangono fondamentali per scrivere codice OO pulito e manutenibile nel
tempo.

Ciao,

Pienamente d’accordo sulla qualit del codice, tranne che per il
ragionamento sulla DI, che trovo totalmente inutile per un linguaggio come
Ruby.
Personalmente mi sono approcciato alla DI per rendere il mio codice pi
testabile, e penso sia il suo maggiore beneficio.
In generale tutti i principi di OO servono per avere codice dal buon
design e poco accoppiamento e quindi buona leggibilit e facile
manutenibilit. Un effetto collaterale del buon codice che sia anche
testabile e su questo side effect si basa il TDD.
Per cui molto vero che il DIP viene comodo nei linguaggi con interfacce
per lo unit testing.

Ad un livello pi alto per il DIP sancisce semplicemente che la parte di
codice pi astratta non dovrebbe dipendere dai dettagli implementativi
cosa che succede tipicamente nel codice procedurale pi classico.
Un esempio potrebbe essere una procedura che elabori dei dati e poi li
salvi su di un database MySQL. Tale procedura deve conoscere i dettagli
di astrazione della logica applicativa e contemporaneamente sapere come
accedere nello specifico a MySQL conoscendo i dettagli del suo driver.
Il concetto base del DIP suggerisce di porre i dettagli di come
persistere i dati in un oggetto che incapsuli il comportamento e
passarlo a quello pi astratto che gestisce la logica. In questo modo
logica e dettagli che si trovano a livelli di astrazione differenti non
sono dipendenti e tutto risulta pi leggibile e mantenibile.

Ma con Ruby (e rspec, ma vale anche per altri framework di mocking) si pu
scrivere:

MyCass.stub(:new).and_return(your_mock)
Qui IMHO lo applichi senza accorgertene (dato che non hai bisogno di
interfacce) perch l’oggetto stubbato verr utilizzato da un altro oggetto
separando la responsabilit (per esempio) di alto e basso livello.
Ti torna?

Ciao,

Il giorno 24 agosto 2011 14:48, Gian Carlo P.
[email protected]ha scritto:

Pienamente d’accordo sulla qualit del codice, tranne che per il
ragionamento sulla DI, che trovo totalmente inutile per un linguaggio
come
Ruby.
Personalmente mi sono approcciato alla DI per rendere il mio codice pi
testabile, e penso sia il suo maggiore beneficio.
Ma con Ruby (e rspec, ma vale anche per altri framework di mocking) si
pu
scrivere:

MyCass.stub(:new).and_return(your_mock)

Quindi in sostanza posso, in qualunque momento nei miei test,
sovrascrivere
il ‘new’ con una mia implementazione.
Personalmente la flessibilit di Ruby ha fatto s che scomparisse il
principale motivo per implementare la DI.

Matteo

Aggiungo altro materiale su cui ragionare:

:slight_smile:

ciao
ema

2011/8/24 Gian Carlo P. [email protected]:

Hai pienamente ragione, nella spiegazione sono rimasto ad un livello pi
pragmatico, dai una letta a questo articolo:
Coming Soon – Alistair Cockburn.
Personalmente un modello che trovo illuminante, e non incompatibile con
Rails, semplicemente Rails non ti limita alle best practices, ma consente di
aggiungere debito tecnico alla tua applicazione in maniera quasi schifosa
:slight_smile:
LOL :slight_smile: +1 su tutto.
E sono sempre stato un grande fan delle architetture esagonali che (TBH)
in java vedo pi cruciali che non in ruby dato che si usa spesso il data
mapper con oggetti di dominio non in relazione diretta con le tabelle.

No, non si tratta di Dependency Injection. Non c’ un risolutore delle
dipendenze, ma una semplice invocazione di metodo (new) .
[omissis]
E ovviamente, utilizzare i metodi ‘stub’ di RSpec o similari per testare
questo codice non implica implementare la DI, ma solo sfruttare le
potenzialit del linguaggio per semplificare lo sviluppo.
Mi chiaro che una new da sola non faccia una injection :slight_smile:
Mi sono spiegato male e parto dal tuo esempio e dando qualche nome a
metodi e classi:

class MySqlDriver
def save(data)

do something

end
end

class DataCruncher
def initialize(db_driver)
@db_driver= db_driver
end

def process(input)
data = crunch(input)
db_driver.save(data)
end
end

cruncher = DataCruncher.new(MySqlDriver.new)
cruncher.process(input)

Per cui utilizzare una struttura simile solo per sostituire MySqlDriver
con MySqlDriverStub per fare testing unitario in ruby overkilling dato
che ruby permette di modificare addirittura il risultato di una new. In
questo senso mi son preso la licenza poetica di immaginare il patch
della new come una injection dato che permette di modificare a runtime
l’oggetto che viene utilizzato dalla classe DataCruncher.

Nel caso in cui invece occorresse supportare anche il PostgreSQLDriver e
l’OracleDriver il precedente codice, a mio avviso, potrebbe costituire
una via percorribile in quanto separa il processing dei dati dal
dettaglio del loro salvataggio che viene demandato ad oggetti
differenti. Mi sembra di capire per che in ruby si prediliga usare una
classe o un file con la configurazione in cui la DI viene effettuata con
codice tipo

DataCruncher.config do |c|
c.driver = MySqlDriver
end

Che tu (voi) sappia: ne esistono altre di modalit “standard” ruby? Sono
curioso e voglioso di apprendere il rubystyle :slight_smile:

Tanto per chiarire le cose, fondamentale leggersi l’articolo di Martin
Fowler: Inversion of Control Containers and the Dependency Injection pattern.
Sono reduce negli anni dai framework Avalon, nano container, Spring e
Guice, quindi (mio malgrado) ho dovuto imparare i dettagli della
Dependency Injection e del Dependency Inversion Principle molto tempo fa
:slight_smile:
Una buona risorsa, bench datata, sui principi OO si trova a casa dello
Zio Bob[1]

[1]
http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf

Ciao,

gk

Il giorno 30 agosto 2011 12:37, Gian Carlo P.
[email protected]ha scritto:

side effect si basa il TDD.
Il concetto base del DIP suggerisce di porre i dettagli di come persistere
i dati in un oggetto che incapsuli il comportamento e passarlo a quello pi
astratto che gestisce la logica. In questo modo logica e dettagli che si
trovano a livelli di astrazione differenti non sono dipendenti e tutto
risulta pi leggibile e mantenibile.

Hai pienamente ragione, nella spiegazione sono rimasto ad un livello pi
pragmatico, dai una letta a questo articolo:
Coming Soon – Alistair Cockburn.
Personalmente un modello che trovo illuminante, e non incompatibile
con
Rails, semplicemente Rails non ti limita alle best practices, ma
consente di
aggiungere debito tecnico alla tua applicazione in maniera quasi
schifosa
:).

No, non si tratta di Dependency Injection. Non c’ un risolutore delle
dipendenze, ma una semplice invocazione di metodo (new) .
La Dependency Injection prevede una figura che inserisca l’oggetto A
all’interno dell’oggetto B.

in Ruby, questo si traduce in:

class A
def do_a
# do something
end
end

class B
def initialize(a)
@a = a
end

def do_b
# do something with a
end
end

def build_everything
a = A.new
b = B.new(a)
{ :a => a, :b => b }
end

build_everthing[:b].do_b

Questo modo di fare per non comune in Ruby, perch tipicamente si fa (o
qualcosa di simile):

class B
def initialize
@a = A.new
end
end

E ovviamente, utilizzare i metodi ‘stub’ di RSpec o similari per testare
questo codice non implica implementare la DI, ma solo sfruttare le
potenzialit del linguaggio per semplificare lo sviluppo.

Tanto per chiarire le cose, fondamentale leggersi l’articolo di Martin
Fowler: Inversion of Control Containers and the Dependency Injection pattern.

Matteo

Ciao,
dalla mia ultima esperienza purtroppo devo confermare quello che
si legge nell’articolo… Sono appassionato di Ruby da un po’ di anni
per i vari motivi che conoscete meglio di me. Ma è solo da poco che ho
incominciato a lavorare a tempo pieno su Rails (prima ho passato molto
tempo facendo progetti da casa, altri piccoli a lavoro e cercando di
convincere il dirigente di turno che passando a Ruby/Rails avrebbe
risparmiato). Ricapitolando, non vedevo l’ora di entrare nel picolo
magico mondo di…Ruby. Ma se devo essere sincero, l’impatto non è stato
molto rassicurante, ovviamente non a causa del linguaggio, il quale è un
ottimo linguaggio, ma proprio per delle cose molto simili a quello che
si legge nel blog. Pensate anche che ho quasi litigato con dei senior
(si chiamano cosi?) perché mi rinfacciavano dei principi OO come se
fosse una cosa legato a Java…??? WTF! E poi tutti i discorsi che si
basano troppo su una particolare tecnologia anziché sui principi e
metodologie sono, direi nel caso migliore, sospetti. Che dire, prima di
partire full-time pensavo che fosse solo questione di tempo affinché
ruby diventasse il java del futuro, ora sono molto meno convinto. Penso
che la cosa peggiore sia quella di spostare degli sviluppatori
medi-scarsi da Java a Ruby. Avendo una potenza espressiva maggiore in
Ruby è molto + facile fare delle cagate ancora + grosse di quelle che si
facevano in Java. Questo ultimo motivo penso che potrà essere un rischio
per quanto riguarda la diffusione del linguaggio all’interno delle
società. Boh, probabilmente è ancora presto per cui dovro’ pazientare e
farmi una idea + precisa.

PS: per quanto riguarda la DI credo di “sbagliato” ci sia solo il
nome…) (Mistaeks I Hav Made: Dependency "Injection" Considered Harmful un bell’articolo
secondo me).
A volte penso che gli esempi che si fanno tipicamente per dimostrare che
Ruby “non ha bisogno” del “DI” facciano sempre parte del problema “il
linguaggio è molto espressivo” che parlavo prima: “With great power
comes great responsibility…”. Sono d’accordo pero’ che non serve un
framework.