Prefazione


Come spesso accade, nasce l'esigenza di sperimentare cose nuove, per puro gusto di conoscere, anche se non esiste un immediata applicabilita' di cio' che imparero'.
A differenza di altre volte dove leggo, leggo, leggo, provo, provo, provo, ma poi di "toccabile" non mi rimane piu' niente, a parte qualche progetto di test e qualche appunto, (ovviamente in testa qualcosa ci rimane :-) ) questa volta ho deciso che oltre a leggere, leggere, provare, provare, di aggiungere anche uno "scrivere, scrivere".
Ma cosa scrivere ? una serie appunti, o vari copia/incolla magari potrebbero essere utili, ma so gia' che quando avro' di fronte un problema non andro' a rivederli e usero' il tradizionale metodo di prove incrociate e ricerche su Internet..., quindi ho deciso di scrivere a mo' di diario di bordo gli step e le impressioni che di volta in volta si presenteranno, spero che potranno essere utili a qualcuno e che qualcuno li possa in parte condividere.
La scelta del tema e' venuta un po' cosi. potevo scegliere qualcosa sempre relativo a Java ad esempio approfondire la tecnologia degli EJB 3.0 ma poi avendo gia' studiato le JPA e le Annotation di Hibernate, avrei rischiato di andare un po' troppo sul tecnico. avrei potuto imparare un po' di linguaggi "vecchi" ma pur sempre usati esempio Perl o Python, o fare il salto in .NET ma non mi ispirava : troppo "asettico" ...   La scelta e' caduta Ruby e conseguentemente su Ruby on Rails quindi, su un linguaggio che come per Java ci si puo' "innamorare" (o odiare) che oltre a essere come gli altri un insieme di comandi, funzioni etc.. e' anche un insieme di concetti e filosofie (ovviamente informatiche) che possono essere apprezzate o disprezzate.
Vedremo, nel corso dell'approfondimento cosa uscira' ...
* Per una veloce consultazione le informazioni di carattere tecnico sono racchiuse tra rettangoli.

Diario


31 Maggio 2009

Bene guardiamo cosa offre la rete, la comunita' e' apparentemente ricca vedremo se poi sui problemi salienti e particoliri offrira' sempre una risposta data dall'esperienza degli altri come avviene per la comunita' Java.
Molti siti si rifanno al "Developer Kit" InstantRails-2.0 che permette un avvio molto veloce e  semplice da installare in quanto consiste di un package (semplicemente da scompattare) con in bundle il linguaggio Ruby, il framework Ruby on Rails, un Apache e un Mysql (e altri strumenti di supporto) gia' configurati e pronti all'uso.
Per adesso per lo sviluppo va bene questa configurazione che fa tutta da sola, vedremo in seguito in cosa consiste effettivamente il Runtime di Ruby in quanto in un ipotetico ambiente di produzione, l'esperienza insegna che non ci si dovrebbe mai fidare delle cose automatiche e di cui non abbiamo il pieno controllo.

2 Giugno 2009

Ok, adesso troviamo un buon pdf da seguire e via con le prove, mi ricordo che tempo fa (a fine 2007) mi ero scaricato un Free Book che sembrava molto ben fatto "Build Your Own Ruby on Rails Web Applications" di Patrick Lenz (purtorppo volevo mettere il link per scaricarlo ma l'offerta Free e' Expired :-( ), la mia copia e' un po' datata ma va bene lo stesso.
E' convenzione identificare i metodi che modificano l'oggetto stesso, con "!",Es. Classe.update!.
Mentre i metodi che restituiscono un valore Vero/Falso, con "?, Es. Classe.isNumber?.
Il metodo initialize puo' essere considerato il metodo "Costruttore", dato che viene chiamato ad ogni istanziazione.
Una consuetudine e' di creare un metodo chiamato "inspect" che ritorna i valori "importanti" di una classe, cio' e' utile in fase di Debugging.
il comando "return" permette di ritornare un valore al chiamante di un metodo, ma per default viene restituita l'ultima espressione elaborata.


19 Luglio 2009

E' passato un bel po' di tempo dall'ultima volta che mi sono messo a studiare un po' di Ruby. Ma nel frattempo mi sono comprato qualche libro sull'argomento da leggere nelle vacanze, quindi ho lasciato per il momento il PDF e ho cominciato : 'Ruby per applicazioni web' di Marco Ceresa edito da Apogeo. Sembra ben fatto, comunque alla fine sapro' se consigliarlo o no. L'introduzione e' appassionante e le aspettative sul linguaggio sono alte: diretta competizione con PHP e con Java (quando il linguaggio sara' piu maturo e la dotazione di librerie piu' completa).
Tramite il comando ri e' possibile ottenere l'Help relativo all'argomento ricercato (es. ri print); la convenzione utilizzata e' di identificare con "è #" i metodi di istanza (Es. Classe#Metodo) e con "::" i metodi di Classe (Es. Classe::Metodo).
Tramite irb invece si puo' in modo interattivo provare i programmi Ruby direttamente da Prompt.


21 Luglio 2009

Eccoci adesso si entra piu' nel vivo del linguaggio, sembra che le variabili non debbano essere tipizzate in modo esplicito, quindi non vedremo piu' un "private String var1" o equivalente o una definizione dei metodi con i parametri con il relativo tipo. La semplificazione e' evidente, ma non associando il tipo dato durante la scrittura del codice, molti controlli in fase di compilazione vengono inevitabilmente a mancare, spostando la verifica e l'eventuale correzione alla fase di runtime. Ovviamente una programmazione snella e flessibile si paga con un aumento dei rischi di creare incongruenze e 'subdoli' malfunzionamenti. Non tipizzare esplicitamentte una variabile non significa escludere la gestione dei tipi, anzi, la loro gestione sembra molto completa e mirata alle esigenze del programmatore.
Per accedere al contenuto di una variabile tramite la sintassi #{nome_variabile}.
Per espandere lo Scope di una variabile a livello di classe occorre anteporre al nome della variabile il carattere "@".
Per far diventare una variabile Globale all'intero programma invece si usa il carattere "$".
Per eredirare da una classe si usa la sintassi : class nome_classe < nome_superclass.
Il Valore nullo e' identificato da nil


22 Luglio 2009

Sto sperimentando l'argomento blocchi e alcune funzioni e comandi di utilizzo comune (each, select, iteratori etc..) , sembra impossibile ma tutto viene abbastanza spontaneamente e gli errori di costruzione sintattica tipici durante i primi utilizzi di un linguaggio sono molto ridotti. La funzione dei blocchi e la loro applicabilita' nelle funzionalita' di base e' molto potente e da buoni margini di benefici nell'utilizzo.
In generale dalle prove fatte, la scrittura del codice e' facilissima e basta poco per entrarci, e' tutto molto snello, essenziale, ma nello stesso tempo coerente.
Il valore di default di un metodo lo si puo' specificare nela firma del metodo (es. def metodo1(par1 = 10 , par2 ).
con * si puo' specificare un numero indeterminato di parametri di un metodo (es. def metodo1(*param)) il parametro verra' trattato come un array
Si puo' definire piu' parametri di ritorno (questo evita come in altri linguaggi definire parametri di IN e di OUT o INOUT) e lasciare il tutto piu' coerente.
Es.
a,b = metodo1(10,20)
def metodo1(q,w)
....
return x,y
end
ad a e b viene assegnato il valore di x e y.
attr_accessor permette di costruire in automatico i metodi getter e setter tipici dei bean.
Una variabile di classe si definisce con una doppia @, es. @@var1


23 Luglio 2009

Addentrandosi ancora un po' nella metodologia di scrittura del codice, si nota subito l'obbiettivo primario del linguaggio : la semplicita' d'uso. Quante volte e' capitato di costruire una classe in modo da condividerne i metodi magari ereditandoli, solo per un esigenza di sviluppo e non di analisi ? Magari per permetterere versatilita', lasciando l'implementazione di qualche metodo alla classi figlie definendoli come Abstract ? Tutto questo in Ruby si traduce con l'utilizzo dei moduli che hanno la doppia valenza di aggregatori (e per evitare collisioni di nomi) e di strumenti per implementare una sorta di ereditarieta' multipla.
Ovviamente occorre trovare il giusto compromesso di utilizzo, in Java, la rigidita' della struttura di un programma garantiva anche l'affidabilita' e il buon codice, in Ruby come in altri linguaggi "Agili" tutto e' demandato alla buona condotta dello sviluppatore. Quindi se da un lato in Java era a volte difficile rimettere le mani in un codice perche scritto troppo bene, in Ruby penso occorra stare attenti a non fare oggetti ingestibili e "intrecciati" incoerentemente tra loro.

1 Agosto 2009

Per quanto riguarda le eccezioni e la gestione degli errori, in Ruby non esiste una sostanziale differenza rispetto ad altri linguaggi, se in Java si usa Try..catch..finally, qui si usa begin..rescue..ensure. C'e' qualche funzionalita' in piu' nella definizione del blocco ad esempio non e' detto che debba iniziare con begin ma puo' essere un inizio metodo, inoltre con i comandi retry e next possiamo intervenire sul processo di recovery di un errore.
Ma fondamentalmente la gestione eccezioni rimane quella che e', e rimane inevitabilmente a carico del programmatore l'onerosa e spesso trascurata gestione degli errori.

5 Agosto 2009

Oggi si apre un nuovo capitolo nell'apprendimento di Ruby e cioe' quello che riguarda l'interfacciamento alle basi dati. Java da questo punto di vista ha portato aria fresca riuscendo a sganciarsi dai maledetti ODBC, OLEDB, ADO etc.. che ormai da anni portano piu' problemi che altro (non mi dite che non vi e' mai capitato un errore o un comportamento inaspettato usando gli ODBC da Access, Visual Basic etc..?). L'uso degli JDBC veramente ha semplificato e standardizzato il modo con qui si accede e ci si interfaccia ad un Database. Il database per un'applicazione e' spesso di fondamentale importanza e un buon interfacciamento dato dal linguaggio e' obbligatorio, per non compromettere l'affidabilita', la scalabilita' e la portabilita' (qualora ce ne fosse bisogno). In ruby abbiamo diversi modi di interfacciamento al DB :
- Driver Nativo
- DBI
- tramite ORM
Non resta che percorrerli un po' per vedere i pro e i contro. Provando un po' a interfacciarsi a Mysql tramite driver nativo sembra piuttosto semplice purtroppo in questo modo si compromette la portabilita' su altri DB e si soffre delle peculiarita' del dialetto del database, comunque per obiettivi mirati e' una strada da prendere in considerazione per la semplicita' di implementazione.

6 Agosto 2009

Adesso e' la volta dell'uso del DBI, provando a eseguire un piccolo test di connessione sempre a Mysql, incorro in un temibile :
c:/ruby/lib/ruby/site_ruby/1.8/dbi.rb:329:in `load_driver': Unable to load driver 'Mysql' (DBI::InterfaceError)
from c:/ruby/lib/ruby/site_ruby/1.8/dbi.rb:227:in `_get_full_driver'
from c:/ruby/lib/ruby/site_ruby/1.8/dbi.rb:213:in `connect'
ovvia !! un po' di problemi, filava troppo tutto liscio, e per imparare un linguaggio occorre incontrare un po' di problemi. Ovviamente la prima cosa e' guardare su internet alla comprensione delle possibili cause del problema : l'errore sembra dovuto alla mancanza del driver DBD per Mysql utilizzato da DBI. Praticamente DBI crea un interfaccia generica verso il driver specifico e per qualche motivo non lo trova.
Sembra che per risolvere la cosa occorra aggiornare il pacchetto dbi e installare il DBD-Mysql. e qui inizia il secondo problema nidificato al primo : Per aggiornare/installare i pacchetti su Ruby ci sono prevalentemente due modalita', installazione manuale da pacchetto scaricato in stile MAKE in Linux o tramite Rubygems sullo stile di APT o RPM di linux. Inizialmente mi concentro su RubyGem, provo a fare una ricerca per vedere i pacchetti disponibili con : "gem search --remote dbi" e la console si blocca (o meglio inizia un processo molto lungo, circa 20 minuti) con visualizzato :
"Bulk updating Gem source index for: http://gems.rubyforge.org"
occupando in modo incrementale fino a 400mb di memoria e molta CPU tutto per ricostruire il file source_cache nella dir di Ruby, e ad ogni lancio la storia si ripete.
Ovviamente la cosa non e' normale e occorre investigare, e dopo purtroppo tanti "20 minuti" di prove, ho trovato che il problema sembra dovuto alla versione di rubygems che occorre aggiornare, dalla versione 1.0.1 sono passato alla 1.3.5, che guardando sulle Release notes disabilita il "Bulk update" dell'indice. Dopo l'aggiornamento eseguito con "gem update --system", rubygem e' tornato a essere usabile. Quindi riparto con lo scopo principale aggiornare DBI e il DBD-Mysql, eseguo il gem install dei due pacchetti, riprovo a eseguire l'applicazione di test ma niente. A questo punto lascio perdere l'installazione tramite "gem" e provo quella manuale, che comunque ti da maggiore controllo.
Ho notato che nella dir. ...ruby\site_ruby\1.8\DBD non ha messo il driver DBD, provo quindi a eseguire la procedura tramite setup.rb che piazza i file nella directory. Ma ancora niente di fatto, adesso DBI li trova ma ancora non va un altro errore viene rilanciato dalla load_driver di DBI. L'ultima cosa da fare e' aggiornare anche DBI tramite setup.rb alla versione 0.4.2 e questa volta FUNZIONA !!!!
Guardando un po' i sorgenti, il problema sembra dovuto all'implementazione del metodo load_driver dentro dbi.rb che pare completamente riscritto : nella versione 0.1.1 c'erano una serie di : require "#{DBD::DIR}/#{driver_name}/#{driver_name}" che adesso sono scomparsi portando anche al fatto di non far cercare piu' i driver obbligatoriamente dentro la dir DBD.
Comunque tutto sembra ritornato alla normalita' e tutto cio' e servito ad investigare ulteriormente l'aspetto di configurazione dell'ambiente di runtime e delle dipendenze, il cui controllo in un sistema di produzione sono fondamentali a eventuali azioni di recovery. In ogni caso un maggior approfondimento su questo punto e' doveroso per un pieno controllo della situazione e per la risoluzione di problemi di librerie e driver.

10 Agosto 2009

Adesso non mi resta per chiudere la parentesi DB guardare un po' riguardo l'uso di ActiveRecord.
Mi sembra di vedere che ActiveRecord sia molto simile alle funzionalita' che in Java ritroviamo con l'uso delle JPA o di Framework di persistenza tipo Hibernate, dove il programmatore si deve solo dedicare a gestire oggetti di classi dedicate alla persistenza dei dati sul DB. L'unica (e non piccola) differenza e' che quello che si faceva con Bean, file xml, Annotation etc... in Ruby lo si fa veramente in poche righe di codice. Comunuque su questo argomento e su un uso approfondito si rimanda al momento dell'impiego di Rails.
Per adesso dalle prove fatto sembra molto facile interfacciarsi e separare lo strato DB dalla nostra applicazione tramite ActiveRecord, davvero un ORM ben fatto.

11 Agosto 2009

Prima di affrontare l'argomentone Web, un capitoletto e' dedicato ai Thread che in Ruby sono gestite bene, tanto quanto gli altri linguaggi, non ci sono grosse differenze (se non nella sintassi).
Comunque penso che l'argomento Thread va approfondito quando capitera' di usarli, dato che fanno parte di quelle funzionalita' avanzata di cui pero' non bisogna abusarne, per non incorrere in forti controindicazioni, nel caso specifico : difficolta' di Debugging, complicazioni nel codice, Errori di sincronismo inaspettati e randomici etc...

13 Agosto 2009

Eccoci alla parte Web, Ruby e' decollato proprio sul fronte Web deve essere per forza potente !! purtroppo ho trovato diversi problemi, piu' che per colpa di Ruby, sono dovuti alla sua implementazione su Windows.
E' vero bisogna usare Linux etc.. etc.. ma e' un dato di fatto che se un linguaggio vuole evolvere deve abbracciare tutti i sistemi operativi (anche quelli nemici).
Prima di tutto ho voluto provare un semplice CGI e sono partito a configurare il Server Apache con il modulo Ruby e scopro che per Windows non e' esistente, sul progetto Mod_Ruby su Rubyforge si rimanda all'uso del progetto InstantRails ma poi li nel package non e' presente.
Alla fine mi dirigo a implementare un WebServer con WebRick (uno dei server Web integrati nel linguaggio) e scopro che e' davvero molto potente e facile; purtroppo anche qui mi scontro con l'installazione di Ruby in Windows, in quanto si verifica un comportamento anomalo durante l'esecuzione dei CGI che sfocia in uno strano : "Premature end of script headers". C'e' voluto qualche oretta per scoprire che il problema e' sul fatto che in Windows non riesce a recuperare il percorso all'interprete Ruby e il tutto viene risolto in due modi :
1) o con un brutto chiodo durante il new del server WebRick : ":CGIInterpreter =>"/ruby.exe"
2) o con un piu' elegante istanzaServer.config.store( :CGIInterpreter, "#{HTTPServlet::CGIHandler::Ruby}")
in questo modo almeno i CGI funzionano a dovere, passando alle pagine html (con estensione .rhtml) con codice Ruby interpretate da ERB, si verifica un comportamento differente tra Firefox e Internet Explorer, purtroppo in Firefox non riconosce l'estensione e tenta di scaricare il file piu' che interpretarlo, comunue il tutto si risolve :
1) aggiungendo "include WEBrick"
2) e dichiarando il MimeType con "HTTPUtils::DefaultMimeTypes.store('rhtml', 'text/html')"
Inoltre volevo provare "eruby" al posto di "erb", ma in instantRails non e' presente, penso invece che nell'installazione in Linux, questo fatto non sia presente. Comunque poco male sembra che erb funzioni a dovere quindi per il momento lascio perdere. In ogni caso ancora mi manca LA soluzione per un sistema di produzione qualora si ritenesse l'uso di WebRick improprio : penso che la risposta sia Mongrel visto che le applicazioni Rails girano li sopra, ma su questo punto tornero' quando verra' approfondito l'uso del framework.

16 Agosto 2009

Oggi ho avuto una impressione molto positiva e una negativa, quella negativa si e' manifestata durante qualche prova con le librerie ImageMagic, su cui si basano diverse altre librerie di grafica (es. Gruff per i grafici) In realta' la libreria Ruby non implementa tutte le funzioni di gestione delle immagini ma semplicemente fa da interfaccia verso le librerie del Software ImageMagic.
Questo aspetto pero' pone un punto di criticita' perlomeno nei sistemi Windows in cui non c'e' mai la sicurezza che non ci sia conflitti tra DLL e che il runtime giri correttamente.
Infatti al momento dell'uso un bel "Runtime Error" utilizzando il runtime C durante l'uso della librerie di ImageMagic si e' prontamente verificato.
Le librerie Java invece se non in pochi casi (es. per mettere un'icona in Traybar), non sfruttavano librerie esterne dipendenti dal S.O. e questo secondo me ne fa un punto di forza, nell'affidabilita'. Probabilmente il problema non e' da imputare a Ruby, tra l'altro e' in piena filosofia con il concetto Linux di far fare ad ogni software il lavoro che sa fare meglio, ne e' la dimostrazione la dura vita di "Nero for Linux" contro l'accoppiata mkisofs e Cdrecord (insieme ai vari Frontend).
Forse tutti questi problemi non ne avrei avuti con ImageMagic per Linux, ma come detto precedentemente un linguaggio deve abbracciare il piu' possibile i vari ambienti se vuole progredire.
Fortunatamente a contrbilanciare ho avuto l'impressione molto positiva nell'uso di XML in Ruby. E' veramente potente e allo stesso tempo semplice. In Java, ma in quasi tutti gli altri linguaggi interfacciarsi a XML e' una noia pazzesca : creazione dell'oggetto factory, istanziazione del Document, lettura ricorsiva dei figli istanziazione di Element, Node, NodeSet e cosi via.
Per non parlare della scrittura che per aggiungere il testo dentro un nodo occorrono 4 righe di codice (stessa cosa per gli attributi).
E' vero ci sono librerie che facilitano la vita, stile Jdom ma comunque non arrivano alla facilita' e immediatezza dimostrata in Ruby.

17 Agosto 2009

Anche sull'argomento programmazione distribuita, Ruby sa dire la sua, con poche righe di codice si riesce a serializzare, trasportare e reinterpretare istanze di classi, in modo semplice e fruibile. Tramite DRB si riesce a mettere in piedi servizi remoti facilmente utilizzabili e anche per quanto riguarda tutta la tematica SOAP questa e' pienamente supportata.

18 Agosto 2009

Un aspetto che fa proprio capire che Ruby e il collage del meglio dei vari linguaggi e' la libreria per i test funzionali. E' praticamente la trasposizione in Ruby di cio' che e' Junit in Java e dei vari derivati negli altri linguaggi.
Il meccanismo dei testcase era gia' perfetto non si poteva fare di meglio in Ruby.

22 Agosto 2009

Anche per quanto riguarda la documentazione non posso che ripetere quanto detto sui TestCase, anche qui ritroviamo praticamente tutti i concetti applicatio con Javadoc, tranne qualche formalismo cambiato e una struttura meno rigida dei commenti.