Ruby e i principi dell'OOP

Ciao a tutti.
Premetto che sono un neo-rubysta e provengo da anni di C#.

Una delle cose “strane” di Ruby che mi sono balzate all’occhio la
“dimensione” delle classi. Gi la classe Object ha 56 metodi e
scendendo nell’albero gerarchico il numero di metodi aumenta (la
classe String ne ha 160).
Questa cosa rappresenta in genere una puzza, almeno nella teoria (SRP,
ISP).

Volevo sapere cosa ne pensavate voi rubysti d’annata :slight_smile:

grazie

2011/1/12 Emanuele DelBono [email protected]:

Ciao a tutti.
Premetto che sono un neo-rubysta e provengo da anni di C#.

Una delle cose “strane” di Ruby che mi sono balzate all’occhio la
“dimensione” delle classi. Gi la classe Object ha 56 metodi e
scendendo nell’albero gerarchico il numero di metodi aumenta (la
classe String ne ha 160).
Questa cosa rappresenta in genere una puzza, almeno nella teoria (SRP, ISP).

Volevo sapere cosa ne pensavate voi rubysti d’annata :slight_smile:

Mi sembra una domanda interessante!

Mi viene in mente: il design di una libreria di classi (o anche della
fondamentale gerarchia di classi di un linguaggio OO) non dice
seccamente ‘che le classi abbiano pochi metodi’, prescrive
semplicemente che le classi siano coese e/o abbiano una sola
responsabilita’. E’ vero, esaminando i metodi di Object si individuano
almeno 2 responsabilita’ distinte maggiori (introspezione, servizi
base tipo dup, hash, e ==), piu’ altri piu’ frammentati. D’altra
parte, che utilita’ avrebbe avere degli oggetti non introspezionabili?
e’ vero, e’ meno puro, ma in questo caso, considerata anche la
prevedibile stabilita’ di questi fondamenti di ruby, direi che la cosa
fornisca piu’ comodita’ che altro - anche alla luce del fatto che in
qualche modo ruby si considera un linguaggio di scripting, che nella
mia accezione significa che ‘fare le cose semplici deve essere
semplici’,ovvero il programma ‘hello world’ deve essere lungo circa
una riga . Che e’ lo stesso motivo per cui Kernel e’ mixato a Object,
e quindi funziona exec che in realta’ vuol dire ‘qualsiasi self sia
nel contesto corrente’.exec.

Anche per quanto riguarda String, vale lo stesso discorso sulla
coesione… finche’ String implementa metodi relativi alla
manipolazione di stringhe, non mi sembra una tragedia (anzi mi sembra
desiderabile!) il fatto che abbia tanti metodi!

Ad ogni modo non vorrei sembrare un rubista bigotto… come divide
queste responsabilita’ C#, ad esempio riguardo a String? ti ci trovi
bene?

Ciao

Quasi tutti i metodi su object (sia per le istanze che per il class
object)
servono a fare metaprogramming/reflection e sono l’ equivalente dei
metodi
presenti nell’ assembly System.Reflection del framework. In ruby li
trovi
direttamente sugli oggetti, in .NET le informazioni sul tipo sono di
fatto
wrappate dall’ oggetto Type. Stesso discorso per le stringhe - in ruby
tutto
direttamente sulla stringa (c, in .NET trovi un po’ di cose sull’
istanza, un
altro po’ in String (String.Format ad esempio) ed altri ancora in classi
diverse (tipo RegEx).

Il senso credo sia quello di rendere la sintassi il pi concisa possibile

“02d” % 5 meglio di String.Format(“00:{0}”, 5). Se in un’ applicazione
vedessi tante funzionalit in una classe sola probabilmente mi farei due
domande ma a livello di framework una scelta di design che mi pu andare
bene: rende la vita pi “difficile” a chi mantiene il framework per
facilitare
il lavoro di chi lo usa.

Andrea D.

Ciao,

In aggiunta alle considerazioni gi fatte, che sposo pienamente, vorrei
aggiungerne un paio di mie.

Una principale differenza che Ruby ha rispetto a C# (e a Java) la
presenza
dei mixin, che consentono il riuso di codice fra classi non appartenenti
alla stessa gerarchia. Ovvero risolvono il problema dell’ereditariet
multipla.
Ad esempio, come gi stato detto, dentro Object stato inserito il mixin
Kernel. Pi che contare i metodi totali di un singolo oggetto quindi
secondo me pi importante valutare il numero di metodi definiti
all’interno
della classe stessa, senza contare quelli ereditati/mixati.
Inoltre proprio grazie a questa capacit, estremamente facile aggiungere
decine di metodi ai nuovi oggetti.

Infine, ricordiamo che in ruby presente la keyword alias, che permette
di
esporre un vecchio metodo con un nuovo nome. Ruby infatti sposa un dei
principi cardini del perl, ovvero che vi possano essere pi modi corretti
di
svolgere lo stesso compito (al contrario di Python, ma un altro
discorso!). Ovviamente, avere lo stesso metodo con pi alias aumenta
considerevolmente il conto che fai tu.

Matteo

Il giorno 12 gennaio 2011 09:41, Emanuele DelBono <
[email protected]> ha scritto:

Avere tanti metodi in una classe non significa avere un pessimo design
del
framework, almeno in Ruby :slight_smile:

Ti faccio un esempio pratico.
class File - RDoc Documentation - API della classe File
in
ruby
come puoi notare non c’ un metodo ‘copy’.
Eppure, se nel tuo codice dai un:
require ‘ftools’

magicamente puoi eseguire il metodo File.copy

Questo dovuto al fatto che in ruby, a differenza che con .NET, non
detto
che se String ha 56 metodi, il sorgente di String abbia anch’esso 56
metodi.
Potresti avere string_core.rb con 10 metodi, string_regex.rb con altri 2
metodi, e cos via. Tutti i file manipolano la classe String aggiungendo
metodi.

Detto questo, magari il sorgente di String in ruby ha 56 metodi tutti in
un
singolo file :slight_smile:

Il giorno 12 gennaio 2011 11:23, Emanuele DelBono <
[email protected]> ha scritto:

Ciao Luca

Concordo con quello che dice Andrea e che anche tu sostieni: il
framework deve semplificarmi la vita e quindi meglio avere tanti
metodi disponibili che dover sbattermi per trovare la classe che fa la
tal cosa. Quindi ok, rinuncio ad un buon design del framework (tanto
non lo devo mantenere io) ma molto pi facile da usare.

In .NET oltre alla classe String ci sono altre classi che si occupano
di operazioni collaterali: RegEx, Encoding, StringBuilder, ecc…
Mi ci trovavo bene, nel senso che quello il modo di lavorare in .NET
e non mi ero mai posto il dubbio fino a quando non ho scoperto Ruby
:wink:

Forse si tratta di definire qual’ il Single Responsibilty Principle
della classe string? :slight_smile:

Non so, la mia non una critica a ruby, volevo solo capire come viene
vista questa cosa dai rubysti.

ema
http://blogs.ugidotnet.org/blogema

2011/1/12 Emanuele DelBono [email protected]:

Ciao Luca

Concordo con quello che dice Andrea e che anche tu sostieni: il
framework deve semplificarmi la vita e quindi meglio avere tanti
metodi disponibili che dover sbattermi per trovare la classe che fa la
tal cosa. Quindi ok, rinuncio ad un buon design del framework (tanto
non lo devo mantenere io) ma molto pi facile da usare.

Anche se in effetti nel caso di ruby piu’ che di framework si parla di
una zona “grigia” fra il linguaggio e la libreria di classi base (ad
esempio in ruby ‘==’ non e’ una parola riservata, ma un metodo, cosi’
come gli iteratori)

Non so, la mia non una critica a ruby, volevo solo capire come viene
vista questa cosa dai rubysti.

No no… avevo capito che non era una critica, ma solo uno spunto di
riflessione.
Credo di poter affermare che la cosa viene vista dai rubysti con
simpatia, visto che rende la vita piu’ semplice e produce codice piu’
leggibile e sintetico.

Ciao

2011/1/12 Luca De Marinis [email protected]:
[…]

Non so, la mia non una critica a ruby, volevo solo capire come viene
vista questa cosa dai rubysti.

No no… avevo capito che non era una critica, ma solo uno spunto di riflessione.
Credo di poter affermare che la cosa viene vista dai rubysti con
simpatia, visto che rende la vita piu’ semplice e produce codice piu’
leggibile e sintetico.

Effettivamente per chi viene da altri mondi il difficile rimuovere
tutte le sovrastutture mentali che derivano da linguaggi tipo C# (che
peraltro un ottimo linguaggio) e ritornare all’essenza della
programmazione. :slight_smile:

Ciao Matteo
Giustissime le tue considerazioni.

2011/1/12 Matteo C. [email protected]:

Ciao,

In aggiunta alle considerazioni gi fatte, che sposo pienamente, vorrei
aggiungerne un paio di mie.

Una principale differenza che Ruby ha rispetto a C# (e a Java) la presenza
dei mixin, che consentono il riuso di codice fra classi non appartenenti
alla stessa gerarchia. Ovvero risolvono il problema dell’ereditariet
multipla.

…e quando li ho scoperti ne ho apprezzato la potenza :slight_smile:

svolgere lo stesso compito (al contrario di Python, ma un altro
discorso!). Ovviamente, avere lo stesso metodo con pi alias aumenta
considerevolmente il conto che fai tu.

Anche qui concordo, ma (provocazione) gli alias semplificano la vita a
chi scrive il codice ma la complicano a chi lo legge :slight_smile: