Mondi su mondi, sistemi di sistemi.

OmniFocus e Org, pro e contro

Thursday, September 2nd, 2010

Come ho detto ieri1, ho deciso di abban­do­nare OmniFocus per pas­sare a Org. Vediamo un po’ più da vicino perché.

L’analisi sul consuntivo

Omnifocus è un per­fetto stru­mento per pia­ni­fi­care il da farsi ma è tra­gi­ca­mente ina­de­guato sulla parte con­sun­tiva. Non è pre­vi­sta la regi­stra­zione del tempo impie­gato, di con­se­guenza non posso nem­meno sapere quante ore ho lavo­rato su que­sto o su quel pro­getto oggi, que­sta set­ti­mana o que­sto mese.

Questa cosa mi ha sem­pre fatto pen­sare per­ché Omnifocus nasce come stru­mento ispi­rato al GTD2, dove ha un’importanza fon­da­men­tale il ricon­trollo set­ti­ma­nale dei pro­getti. Anche se potrei fare a meno di sapere quante ore ho speso su una certa cosa, se ce l’ho è meglio; se poi posso con­fron­tare le ore a con­sun­tivo con quelle pre­ven­ti­vate è molto meglio, anzi, fon­da­men­tale. 3

Progetti bloc­cati

Altrettanto impor­tante del vedere cosa è stato fatto è con­trol­lare se ci sono pro­getti bloc­cati. Con OmniFocus il con­cetto degli “stuck pro­jects” esi­ste, anche se è imple­men­tato in modo rigido; con Org è molto più fles­si­bile4

Contesti al computer

Anche sull’uso dei con­te­sti, un altro con­cetto deri­vato dal GTD, ho qual­che per­ples­sità. A mio parere, i con­te­sti sono uti­lis­simi per chi, al con­tra­rio di me, non è sem­pre attac­cato al com­pu­ter e ha un qual­che van­tag­gio nel defi­nire quando può fare certe azioni e non altre. Questa con­si­de­ra­zione var­rebbe sia per OmniFocus che per Org ma con quest’ultimo il costo per non usarli è nullo; con OmniFocus devo impo­stare le pre­fe­renze in modo adatto e fare a meno della “moda­lità con­te­sto” che è una delle due prin­ci­pali (l’altra è quella di pianificazione).

Con que­sto non voglio dire che la sepa­ra­zione fra pia­ni­fi­ca­zione ed ese­cu­zione non sia impor­tante, anzi, è fon­da­men­tale. Solo che non uso i con­te­sti per fil­trare le cose da fare.

  1. Addio a OmniFocus
  2. What is GTD?
  3. La cosa è ancora più curiosa in quanto OmniFocus è impa­ren­tato con OmniOutliner che uso a fasi alterne per il pri­mis­simo plan­ning e per cal­co­lare i pre­ven­tivi. Una volta finita la migra­zione da OmniFocus, penso che pas­serò anche i vari docu­menti di OmniOutliner in org mode.
  4. Anzi, come tutto quello che riguarda Org, fin troppo fles­si­bile. Ci tor­ne­remo.

Addio a OmniFocus

Wednesday, September 1st, 2010

Uso OmniFocus da quando è uscito, da tre anni, ormai ed è stato per tutto que­sto tempo lo stru­mento con cui ho orga­niz­zato pra­ti­ca­mente tutto, sia nel lavoro che fuori.

Anche se non l’ho mai con­si­de­rato per­fetto e non ho mai dige­rito la ver­sione per iPhone1, è quello che nel com­plesso era il più adatto a me.

Poi, qual­che set­ti­mana fa ho sco­perto Org, un modo di Emacs e ho deciso in tempo zero abban­do­nare OmniFocus. Nei pros­simi giorni entrerò un po’ più nel det­ta­glio sul per­ché e il per­come della deci­sione, spe­rando che possa ser­vire anche ad altri.

  1. Fra l’altro, sem­bra che la ver­sione per iPad sia ecce­zio­nale

Skype, le mode e la reinvenzione della ruota

Thursday, August 19th, 2010

Non è un mistero che mi piac­ciano le solu­zioni inu­suali, l’ho scritto in pas­sato: a pro­po­sito dell’intervista ad Avy Briant1, lo ripeto ora dopo aver visto que­sta pre­sen­ta­zione dell’architetto soft­ware di Skype2, sem­pre su InfoQ.

Avevo già letto l’articolo3 ma, anche se è stata una delle cose più inte­res­santi degli ultimi mesi, non mi era pro­prio venuta in mente l’intervista, né tan­to­meno que­sto mio post di due anni fa in cui avevo segna­lato que­sta descri­zione sull’architettura di Skype, che è basata su PostgreSQL.4.

Qual è il nesso?

D’accordo, ammesso che in comune ci sia la capa­cità di tro­vare solu­zioni senza affi­darsi a pre­con­cetti, in un modo che potremmo defi­nire con­text dri­ven5, cos’ha di così par­ti­co­lare l’architettura di Skype? Per capirlo, dob­biamo fare mente locale sul con­te­sto attuale.

L’ascesa del NoSQL

In que­sto periodo, diciamo negli ultimi due anni, si è fatta strada l’idea secondo cui non puoi sca­lare vera­mente un’architettura se ti affidi ai data­base SQL, soprat­tutto se par­liamo di sca­la­bi­lità oriz­zon­tale6. Questo è uno degli assunti, forse il prin­ci­pale, che ha por­tato alla ribalta il cosi­detto movi­mento NoSQL7.

Non c’è dub­bio che ci pos­sano essere pro­blemi a sca­lare i data­base “tra­di­zio­nali”, né che siano adatti a qual­siasi uso e nem­meno che ci sia ancora molto da fare per ren­derli più adatti al modo di lavo­rare attuale8 9.

Naturalmente i data­base SQL sono ancora usa­tis­simi ma non mi aspet­tavo di vedere la pre­sen­ta­zione di uno che lavora esclu­si­va­mente con le sto­red pro­ce­du­res10. Ecco per­ché un’architettura come quella di Skype sem­bra così par­ti­co­lare rispetto a quello che oggi fa ten­denza ed ecco per­ché è così impor­tante tenerla presente.

Reinventare la ruota, ogni volta

Siamo sem­pre attratti dall’adottare quello che ha fun­zio­nato l’ultima volta o quello che sem­bra fun­zio­nare per tutti gli altri. A volte è la cosa giu­sta da fare, a volte no, ognuno sba­glia a modo proprio.

Forse è uno scherzo della memo­ria ma credo di ricor­dare che in un’intervista gli svi­lup­pa­tori della Bungie (quelli di Halo, poi com­prata da Microsoft) dice­vano che uno degli obiet­tivi che si pone­vano era pro­prio quello di rein­ven­tare la ruota, per fare piazza pulita delle cose supe­rate. Sembra che abbia fun­zio­nato! 11

  1. Outside the box.
  2. Learning from Five Years as a Skype Architect Andres Kutt discus­ses his expe­rience as archi­tect at Skype for five years, sha­ring some of the les­sons lear­ned: rules of thumb do not always apply, func­tio­na­lity is impor­tant, use sim­ple solu­tions, buz­z­words are dan­ge­rous, the archi­tec­ture needs to fit into the orga­ni­za­tion, and com­mu­ni­ca­tion is impor­tant.
  3. Learnings from Five Years as a Skype Architect: Too often in our work as archi­tects and desi­gners we focus on the task at hand, sel­dom reflec­ting on the past. We should really know bet­ter, how else do you improve? This arti­cle sum­ma­ri­zes six lear­nings from 55 mon­ths as an archi­tec­ture team lead at Skype.
  4. PostgreSQL: ana­lisi dell’architettura di Skype
  5. Context dri­ven testing. Non fatevi ingan­nare dal fatto che si parla di testing, sono con­si­de­ra­zioni di vali­dità gene­rale.
  6. Da Wikipedia: To scale hori­zon­tally (or scale out) means to add more nodes to a system, such as adding a new com­pu­ter to a distri­bu­ted soft­ware appli­ca­tion. An exam­ple might be sca­ling out from one web ser­ver system to three.
  7. Da Wikipedia: In com­pu­ting, NoSQL is a term used to desi­gnate data­ba­ses which dif­fer from clas­sic rela­tio­nal data­ba­ses in some way. These data sto­res may not require fixed table sche­mas, and usually avoid join ope­ra­tions and typi­cally scale hori­zon­tally. Academics and papers typi­cally refer to these data­ba­ses as struc­tu­red sto­rage, a term which would include clas­sic rela­tio­nal data­ba­ses as a sub­set.
    Notable pro­duc­tion imple­men­ta­tions include Google’s BigTable and Amazon’s Dynamo.
  8. I refac­to­ring che coin­vol­gono il data­base riman­gono ancora troppo mac­chi­nosi. In parte è un pro­blema di stru­menti, in parte è un pro­blema di metodo di lavoro per­ché, forse più che in altri con­te­sti, le ope­ra­zioni da fare sul data­base sono molto spe­ci­fi­che.
  9. Bisogna anche far notare che sotto l’ombrello della defi­ni­zione NoSQL ci sono realtà molto diverse, alcune sono pen­sate per la sca­la­bi­lità (Cassandra, ad esem­pio), altre per modelli di dati che non sono facil­mente ridu­ci­bili all’SQL come i graph data­base.
  10. Anche se, a onor del vero, la pre­sen­ta­zione non riguarda PostgreSQL ma quello che que­sta per­sona ha impa­rato lavo­rando per cin­que anni a Skype
  11. La ten­sione fra riscrit­tura da zero e refac­to­ring è uno dei temi che ricor­rono in que­sto blog, non c’è niente da fare… Dovrò fare una rac­colta dei vari post, un giorno o l’altro.

Tool del giorno: livereload

Wednesday, August 11th, 2010

Se c’è una cosa che ha inse­gnato l’xp è che il tempo per rice­vere il feed­back è cri­tico: più è breve, meglio è. D’altra parte se c’è una cosa che diventa dolo­ro­sa­mente chiara dopo la prima mezz’ora pas­sata a svi­lup­pare una pagina html è che siamo schiavi della com­bi­na­zione ⌘-r: fatta una modi­fi­china? Ricarica. Errore? Ricarica. Forse c’è qual­cosa in cache? Ricarica.

Così qual­che per­sona d’ingegno ha pen­sato bene di ren­derci la vita un po’ più sem­plice con live­re­load: una com­bi­na­zione di una gem di Ruby e di un’estensione per WebKit che fa rica­ri­care auto­ma­ti­ca­mente la pagina al bro­w­ser ad ogni modi­fica all’interno di una cartella.

Dopo cin­que minuti di uti­lizzo non saprete più con­ce­pire il mondo senza que­sta cosa. Installate!

Una sola rac­co­man­da­zione. Se per caso avete instal­lato ruby tra­mite MacPorts, non usa­telo. La gem fun­ziona solo con quello di sistema.

Da Subversion a Git

Wednesday, August 4th, 2010

Qualche tempo fa avevo descritto alcuni dei miei pro­ce­di­menti per snel­lire le pro­ce­dure di deploy­ment sfrut­tando gli hooks1 di Subversion.2

Addio Subversion, buon­giorno Git!

Da allora sono pas­sato a Git. Dovendo quindi rive­dere il pro­cesso ho cer­cato anche di sfrut­tare le poten­zia­lità di que­sto soft­ware per il con­trollo di ver­sione. Per chi non avesse mai sen­tito par­lare di Git, diciamo che la dif­fe­renza prin­ci­pale rispetto a Subversion è che il primo è un sistema distri­buito, men­tre il secondo è cen­tra­liz­zato3.

Perché Git?

La prima con­se­guenza è una distin­zione molto più netta fra il con­trollo di ver­sione e la pub­bli­ca­zione delle pro­prie modi­fi­che. In Subversion l’atto stesso di fare il com­mit implica la pub­bli­ca­zione della nostra attività.

Per alle­viare il pro­blema potremmo fare il com­mit su un ramo pri­vato per poi far con­fluire que­ste revi­sioni nel filone prin­ci­pale. Qui però ci scon­triamo con un secondo limite di Subversion che è una minore robu­stezza nel ricon­ci­liare le revi­sioni. Subversion cal­cola le dif­fe­renze al momento della ricon­ci­lia­zione, igno­rando la genea­lo­gia delle due revi­sioni; Git applica le ope­ra­zioni che hanno por­tato da una revi­sione all’altra.

Nuove pos­si­bi­lità

Comunque, il punto fon­da­men­tale in que­sto con­te­sto è che in virtù della natura distri­buita di Git, ogni repo­si­tory fa sto­ria a sé ed è anche per que­sto che può dia­lo­gare con altre repo­si­tory, scam­bian­dosi le revi­sioni. Possiamo quindi crearne più d’una, anche per un sin­golo pro­getto, ognuna con la pro­pria con­fi­gu­ra­zione e con gli hooks adatti. Facciamo un paio di esempi.

Il primo è quello in cui abbiamo due repo­si­tory, una per lo sta­ging e una per la pro­du­zione. Dalla mia mac­china di svi­luppo posso man­dare le revi­sioni sull’una o sull’altra, oppure spe­dire le revi­sioni da sta­ging a pro­du­zione: gli hooks pen­se­ranno al resto. In que­sto modo pos­siamo ripor­tare in pro­du­zione la ver­sione testata in sta­ging o, se neces­sa­rio, instal­lare una modi­fica urgente diret­ta­mente in produzione.

Il secondo riguarda i fil­tri, che di solito uso per minia­tu­riz­zare CSS e JavaScript, che si appli­cano all’entrata e all’uscita, per così dire, dei con­te­nuti dalla repo­si­tory. In que­sto caso, le ope­ra­zioni aggan­ciate a que­sti fil­tri hanno senso solo nelle fasi di deploy­ment, per­ché altri­menti ci por­te­remmo nel pro­getto le ver­sioni minia­tu­riz­zate. Per fare que­sto basta atti­varli solo sulla repo­si­tory di sta­ging ed entre­ranno in azione quando espor­te­remo da lì il sorgente.

Cos’è cam­biato negli script, quindi?

Il prin­ci­pio di base non è cam­biato e con­si­ste nello sfrut­tare gli hooks messi a dispo­si­zione, in par­ti­co­lare quello di post-receive, che viene appli­cato quando una repo­si­tory riceve delle revi­sioni da un’altra4. In aggiunta ho sfrut­tato la pos­si­bi­lità di defi­nire dei fil­tri per scar­tare alcuni file, come gli unit tests o appli­care delle tra­sfor­ma­zioni ad altri.

Dato che però ora ogni repo­si­tory fa sto­ria a sé, non esi­ste più un elenco di tutti i pro­getti da con­trol­lare; poi, visto che Git non usa un numero pro­gres­sivo per indi­care la ver­sione, le con­tor­sioni per tro­vare il tag cor­retto. Per il resto la logica è invariata.

  1. Ovvero, script ese­guiti in con­co­mi­tanza di deter­mi­nati eventi
  2. Coda & Subversion
  3. In realtà la que­stione è un po’ più com­plessa per­ché Git non nasce come VCS ma, di fatto, lo usano tutti per quello
  4. È inte­res­sante notare che non esi­stono agganci alla crea­zione di un tag su una repo­si­tory. Per farlo devo rice­vere la ver­sione tag­gata da un’altra repo­si­tory

Utility del giorno: localghost

Thursday, May 27th, 2010

Attraverso @rentzsch ho sco­perto Localghost, un pro­gram­mino per con­fi­gu­rare al volo /etc/hosts, per defi­nire quali domi­nii pun­tano al 127.0.0.1

Basta lan­ciarlo, defi­nire le voci DNS e il gioco è fatto. Una volta create, le voci pos­sono essere atti­vate e disat­ti­vate a piacimento.

Cloudkit

Wednesday, April 7th, 2010

L’uso di Ajax rende desi­de­ra­bile, se non neces­sa­rio, il poter met­tere in piedi un ser­ver REST in tempi rapidi.

In que­sto post mi sono imbat­tuto in CloudKit, un’applicazione in Ruby che per­met­tere di met­terne in piedi uno in un bat­ter d’occhio, aggan­cian­doci pure un minimo di bac­kend, in que­sto caso Tokyo Cabinet.

L’installazione è sem­pli­cis­sima e l’unica cosa che ho cam­biato rispetto alla ricetta ori­gi­nale è che ho usato MacPorts per Tokyo Cabinet al posto di com­pi­larlo da zero.

Una volta che Cloudkit è attivo, pos­siamo subito comin­ciare a pro­get­tare l’API che il nostro ser­vi­zio REST esporrà verso l’esterno, magari con un approc­cio TDD usando una delle innu­me­re­voli libre­rie in JavaScript per i test1.

Quando poi le cose saranno più sta­bili potremo sosti­tuire Cloudkit con un bac­kend più adatto, senza toc­care una riga nella parte Ajax.

Strumenti come Cloudkit sono vitali per rac­cor­dare le diverse fasi di svi­luppo per­ché, anche se abbiamo fami­lia­rità con bac­kend più strut­tu­rati e siamo in grado di atti­varli con faci­lità, spesso non sono suf­fi­cien­te­mente agili per aiu­tarci nelle fasi fluide dello svi­luppo, dove le cose cam­biano rapi­dis­si­ma­mente ed è inu­tile essere troppo rigorosi.

Coda & Subversion

Thursday, March 25th, 2010

Uso Coda ormai da qual­che tempo. È un buon pro­gramma per lo svi­luppo dei siti, pia­ce­vole da usare e affi­da­bile, non ho avuto biso­gno di molto altro per diverso tempo.

I limiti più evi­denti di Coda

Dopo qual­che tempo, però, ho comin­ciato a sen­tire la man­canza di Emacs e così ho con­fi­gu­rato Coda in modo da usarlo come edi­tor esterno. A quel punto ho sco­perto con fasti­dio che la lista dei file da cari­care sul sito non veniva sem­pre aggior­nata con le modi­fi­che da Emacs, nono­stante fos­sero cor­ret­ta­mente indi­vi­duati come file modi­fi­cati rispetto alla repo­si­tory nel VCS (Version Control Software; attual­mente è Subversion), costrin­gen­domi ogni volta a mar­carli a mano. No fun.

Inoltre non sem­pre abbiamo a che fare con un deploy­ment diretto. Spesso dob­biamo prima cari­care il sito su un ser­ver di sta­ging e poi, veri­fi­cato che tutto vada bene, pas­sarlo in pro­du­zione. Teoricamente potremmo “ripun­tare” Coda fra i due ser­ver ma, in pra­tica, sarebbe un delirio.

Sfruttiamo Subversion!

Il modo ovvio di risol­vere que­sti pro­blemi è usare i punti di aggan­cio che Subversion mette a dispo­si­zione, ovvero, la pos­si­bi­lità di ese­guire delle ope­ra­zioni arbi­tra­rie in con­co­mi­tanza di alcuni eventi:

  • post-commit
  • post-lock
  • post-revprop-change
  • post-unlock
  • pre-commit
  • pre-lock
  • pre-revprop-change
  • pre-unlock
  • start-commit

In que­sto caso, lo script aggan­ciato sarà aggan­ciato in post-commit ed effet­tuerà il deployment.

I det­ta­gli importanti

Una cosa piut­to­sto sem­plice, insomma, anche se ci sono diverse cosine di cui tener conto. In primo luogo, è sem­pre pre­fe­ri­bile disim­pe­gnare Subversion il prima pos­si­bile1 e quindi dob­biamo posporre le varie ope­ra­zioni; inol­tre, dato che lo script è con­di­viso per tutta la repo­si­tory, dob­biamo avere l’accortezza di fare le azioni giu­ste per il pro­getto giu­sto; infine, visto che ogni pro­getto fa sto­ria a sé, dob­biamo tro­vare un buona fles­si­bi­lità2 per poter spe­ci­fi­care le azioni che vogliamo, nel modo che rite­niamo più oppor­tuno per quel progetto.

Disimpegnare velo­ce­mente la repository

Ad ogni com­mit viene creato uno script di shell (a par­tire da un tem­plate descritto più avanti) chia­mato con il numero di release. La crea­zione è pra­ti­ca­mente istantanea.

Questo script va a finire in una spe­cie di coda sul file­sy­stem. Il fatto di usare una direc­tory invece di un file sin­golo evita pro­blemi di accesso con­tem­po­ra­neo, lasciando com­pleta libertà nel suo con­te­nuto e mi con­sente di sfrut­tare laun­chd per fare in modo che il pro­ces­sa­mento degli script nella coda venga lan­ciato solo al momento oppor­tuno. Questo è il file di configurazione:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>it.refactor.deployment-queue</string>
<key>OnDemand</key>
<true/>
<key>Program</key>
<string>/usr/local/bin/projects-auto-deployment</string>
<key>QueueDirectories</key>
<array>
<string>/var/tmp/deployment-queue</string>
</array>
</dict>
</plist>

Il det­ta­glio impor­tante è la diret­tiva QueueDirectories che, a dif­fe­renza di WatchPaths, lan­cia il pro­cesso alla modi­fica del con­te­nuto della direc­tory, ma solo quando in pre­ce­denza era vuota.

In alter­na­tiva avremmo potuto usare un qual­che dae­mon. Non un gran pro­blema ma mi sem­brava un po’ meno robusto.

Progetti diversi, copioni diversi

Come dicevo prima, lo scopo di usare degli script di shell è quello di lasciare la mas­sima libertà.

Ogni voce della con­fi­gu­ra­zione letta dallo script è simile a questa:

    <regexp> {
        env {
            REL=$rev
        }
        preflight {...}
        deploy {...}
        postflight {...}
    }

Le quat­tro voci: env, preflight, deploy e postflight rag­grup­pano e ordi­nano i diversi fram­menti che vanno a com­porre lo script di deploy­ment, che viene atti­vato in base all’eventuale match dell’espressione regolare.

L’unica varia­bile cono­sciuta è il numero della release, che è pas­sato da Subversion, il resto è tutto libero. Più gene­rico di così!

Di solito, dopo aver defi­nito le varia­bili ambien­tali in env, il preflight si occupa di fare il chec­kout dal VCS; il deploy fa quello che si può imma­gi­nare; il postflight si occupa di fare un po’ di puli­zia ecc. Ribadisco però il fatto che quelle descritte prima sono solo sezioni: se per assurdo voglio met­tere tutto nella sezione env lo posso fare.

Ma non è finita qui…

Tutto bene? Quasi. Così com’è pen­sato, il sistema non per­mette di fare alcune cose molto importanti.

Percorsi varia­bili

Se vogliamo usarlo anche per il deploy­ment delle release “tag­gate”3, dob­biamo aggan­ciare lo script al per­corso dei tag. Tuttavia, dato che l’url com­pleta cam­bia ad ogni nuovo tag — ad esem­pio avremo …/tags/REL1, …/tags/REL2 — come fac­ciamo a sapere in post-commit quale prendere?

Per ora non ho tro­vato una solu­zione gene­rica. Mi sono affi­dato al fatto che il nome della ver­sione in tags è uguale al numero pre­ce­dente della release di post-commit4. Ad esem­pio, se l’operazione è stata ese­guita alla release 3753, cer­che­remo la direc­tory r3752. Una volta otte­nuta l’URL rien­triamo nel caso standard.

Azioni spe­ci­fi­che per le sin­gole release

Un’altra cosa abba­stanza fre­quente è l’esecuzione di ope­ra­zioni spe­ci­fi­che per una data ver­sione. Esempio tipico: delle modi­fi­che allo schema del data­base, che vanno fatte una volta sola e non devono essere riapplicate.

Per risol­vere que­sto pro­blema, all’interno del pro­getto, in una direc­tory nota, creiamo uno script che verrà cer­cato dal sistema di deploy­ment per essere ese­guito5.

roll-up delle modifiche

Infine, nello sce­na­rio sta­ging & deploy­ment è desi­de­ra­bile che una serie di ope­ra­zioni fatte in sta­ging pos­sano venire appli­cate in una volta sola in deployment.

Dato che lo script spe­ci­fico per una data release è anch’esso sotto con­trollo di ver­sione, abbiamo accesso a tutta la sua sto­ria. Bisognerà andare a pren­dere quella por­zione di modi­fi­che inter­corse fra l’ultimo deploy­ment e quello attuale e appen­derle ad un unico file, con un comando del genere, ad esem­pio:
svn log -r3778:3783 -q URL | egrep ^r | awk '{ print $1 }' | sort | while read r; do svn cat -$r URL; done

Come ottengo il range da pas­sare al comando appena visto? Partiamo da un sce­na­rio sem­pli­fi­cato all’osso, sup­po­nendo di par­tire da una repo­si­tory nuova di zecca.

Dalla r1 alla r10, lavoro solo nel trunk; quando creo un nuovo tag, in base alle con­ven­zioni adot­tate prima, il suo nome sarà r10 e il suo numero di release sarà r11. Proseguendo, dalla r12 alla r20, lavoro sem­pre nel trunk; come prima, creando un nuovo tag, il nome sarà r20 e il suo numero di release sarà r21.

A que­sto punto, se cerco tutte le modi­fi­che in tags, esclu­dendo quella rela­tiva alla crea­zione della direc­tory tags, avrò r11 ed r21. Come prima, in base al numero di release pas­sato in post-commit, che al secondo tag sarà 20, posso rica­vare il range da con­si­de­rare, cal­co­la­bile come (release immediatamente precedente):(numero di release - 1), ovvero, r11:r19.

There’s more than one way to do it

Per chi non avesse voglia di rein­ven­tare la ruota, ci sono delle alter­na­tive. In par­ti­co­lare, una delle pos­si­bi­lità che ho preso in con­si­de­ra­zione è quella di instal­lare il soft­ware di VCS diret­ta­mente sul server.

In effetti è una solu­zione piut­to­sto comoda, dato che basta fare un svn up per aggior­nare l’installazione e con VCS distri­buiti le pos­si­bi­lità sono ancora più ampie.

Ci sono però diversi punti dolenti. Come visto prima è raro che basti un sem­plice aggior­na­mento del codice; in secondo luogo non mi piace mol­tis­simo l’idea che si crei un’ulteriore dipen­denza fra il sistema che pub­blica gli aggior­na­menti e quello che li riceve.

Tolta que­sta pos­si­bi­lità, ci sono i soft­ware di SCM veri e pro­pri, da Puppet a Capistrano, pas­sando per Fabric. Il primo pro­pone un modello in pull, dove i cliente con­tat­tano il ser­ver per sta­bi­lire cosa c’è da fare; il secondo e il terzo sono più vicini ai sistemi in push, dove l’azione è ini­ziata dal server.

Infine, non dimen­ti­chia­moci di Hudson che, pur essendo un ser­ver di inte­gra­zione, può auto­ma­tiz­zare pra­ti­ca­mente qual­siasi cosa e quindi anche pro­cessi come questi.

Hudson è quello più adatto, essendo un vero e pro­prio ser­ver di con­ti­nous inte­gra­tion. Anzi, non escludo di comin­ciare ad usarlo a breve, ma per ora mi bastano le due righe che ho scritto in Tcl.

Per quanto riguarda gli SCM, più vicini al mondo dei sysad­min, Puppet mi piace di più, anche per­ché ci ho gio­cato un paio di volte, men­tre ho visto usare Capistrano in situa­zioni simili a quelle descritte.

Come si può notare, alcune delle parti più con­torte sono dovute a Subversion. Dato che ho in pro­getto di pas­sare a Git, sono curioso di sapere se e come il pro­ce­di­mento si semplificherà.

  1. In post-commit Subversion ignora l’esito delle ope­ra­zioni, dato che il com­mit è già stato fatto; tut­ta­via non mi è chiaro se lo ese­gua in asin­crono
  2. avete mai sen­tito di un pro­getto che non deve essere fles­si­bile?
  3. Per chi non lo sapesse, un tag è un’istantanea del codice sor­gente ad un dato momento. In Subversion, è di prassi che le ver­sioni uffi­ciali stiano in tags e le ver­sioni di svi­luppo che deviano da quella prin­ci­pale stiano in branches.
  4. l’uso dei numeri di release come nome del tag non mi risulta sia la cosa più con­si­glia­bile, lo so, tut­ta­via nelle appli­ca­zioni con rila­sci con­ti­nui la cosa non mi sem­bra così grave
  5. Qualcuno stor­cerà il naso nel vedere una com­mi­stione fra deploy­ment e svi­luppo, all’interno del sor­gente. Non è sicu­ra­mente la solu­zione più pulita anche se ha l’indubbio van­tag­gio di tenere sotto con­trollo di ver­sione anche cose che spesso ven­gono lasciate un po’ a se stesse. Ad oggi credo che il bilan­cio costi/benefici sia posi­tivo.

Cosa ci insegna Duke Nukem

Wednesday, January 20th, 2010

Non rie­sco a smet­tere di pen­sare a que­sto arti­colo su Duke Nukem Forever. La sto­ria è sem­plice: dopo il suc­cesso pla­ne­ta­rio di Duke Nukem 3D, rila­sciato nel gen­naio del 1996, nel 19971 la 3D Realms annun­cia l’inizio dello svi­luppo del seguito (Duke Nukem Forever, appunto), che non verrà mai terminato.

Il treno passa una volta sola, se passa…

Com’è potuto suc­ce­dere che un video­gioco sia stato svi­lup­pato per dodici anni senza arri­vare a un risul­tato con­creto? In poche parole, è stata la spinta mania­cale alla ricerca della perfezione.

Non era mai il momento adatto per tirare le fila, rifi­nire il gioco e farlo uscire. C’era sem­pre qual­cosa da fare ancora, qual­che nuova solu­zione da pro­vare, un nuovo limite da supe­rare. E in un mondo come quello dei video­gio­chi c’è una novità ogni santo giorno.

Questa sto­ria l’ho già sentita…

Il rac­conto è avvin­cente, eppure, man mano che pro­cede, non si distin­gue molto da altre sto­rie, que­sta volta di suc­cesso, anch’esse piene di deci­sioni rischiose. Qual è dun­que la differenza?

Ad esem­pio, a poste­riori è facile pen­sare che solo un pazzo cam­bie­rebbe il motore di ren­de­ring tre volte ma ho l’impressione che siamo con­di­zio­nati dall’esito della vicenda. Ogni cosa si spiega quindi a par­tire dal fal­li­mento, ma è tutto da dimo­strare quanto que­sta o quella deci­sione abbiano influito negativamente.

È ovvio che una cosa come il cam­bio del motore 3D com­por­terà dei ritardi ma se il video­gioco fosse uscito pro­ba­bil­mente ammi­re­remmo il corag­gio della decisione.

Forse la verità è che la dif­fe­renza fra un fal­li­mento epo­cale come que­sto e il più cla­mo­roso dei suc­cessi è meno di quanto pen­siamo2. Per non par­lare del fatto che ten­diamo a dimen­ti­carci quanti siano i fal­li­menti rispetto ai suc­cessi3.

Troppa libertà?

Si ricon­ferma ancora una volta, invece, che la man­canza di limiti è un nemico for­mi­da­bile. I vin­coli sono fon­da­men­tali per dare forma e dire­zione a un progetto.

Credo ci voglia un talento par­ti­co­lare per pro­durre qual­cosa in quelle con­di­zioni: se ce l’hai può venir fuori qual­cosa di gran­dioso ma è meglio non con­tarci. È un talento che con­si­ste nel lavo­rare senza bus­sola, facendo affi­da­mento su una qual­che forma di senso inte­riore o forse, sem­pli­ce­mente, è la capa­cità di auto-imporsi dei paletti da non oltrepassare.

Alla fine…

Alla fine, nel mag­gio del 2009 Broussard e Miller, i pro­prie­tari della 3D Realms, hanno stac­cato la spina, scio­gliendo il team di sviluppo.

Mi chiedo cosa possa pas­sare nella testa di una per­sona che fino a quel momento sem­brava non riu­scire a stac­care il piede dall’acceleratore? Soffrirà di una spe­cie di sin­drome dell’arto fan­ta­sma? Oppure non ha ancora abban­do­nato del tutto l’idea? Forse non è ancora finita…

Grande rac­conto, leggetelo!

  1. Sì, tutto è ini­ziato tre­dici anni fa:
    As one patient fan poin­ted out, when deve­lo­p­ment on Duke Nukem Forever star­ted, most com­pu­ters were still using Windows 95, Pixar had made only one movie — Toy Story — and Xbox did not yet exist.

  2. Wow, how many times have you been here, near the finish line, and you thought you were way out?

  3. Unrealized pro­jects

Contro i frameworks?

Thursday, December 24th, 2009

Se dò una scorsa ai libri sugli scaf­fali ne trovo diversi che par­lano dei fra­meworks e delle loro virtù, a par­tire dal vene­ra­bile Design pat­terns. Cito:

The fra­mework dic­ta­tes the archi­tec­ture of your appli­ca­tion. It will define the ove­rall struc­ture, its par­ti­tio­ning into clas­ses and objects, the key respon­si­bi­li­ties the­reof, how the clas­ses and object col­la­bo­rate, and the thread of con­trol. A fra­mework pre­de­fi­nes these design para­me­ters so that you, […], can con­cen­trate on the spe­ci­fics of your application.

[…]

Reuse on this level leads to an inver­sion of con­trol bet­ween the appli­ca­tion and the soft­ware on which it’s based.

D’altra parte, come forse ricor­dano quelli che si sono dati la pena di leg­gere i miei pen­sieri sul map­ping OR, sanno che non li ho più in gran simpatia.

Frameworks vs librerie

Il motivo fon­da­men­tale è che c’è una ten­sione irri­du­ci­bile fra il riu­ti­lizzo (di codice, di impo­sta­zioni, di pat­terns) pro­mosso da un fra­mework e la rela­zione inversa fra esten­sione del codice e riutilizzabilità.

Più il fra­mework è esteso meno è effi­ciente, dove, in que­sto con­te­sto, l’efficienza è data dalla esten­sione rispetto alla por­zione real­mente utilizzata.

Inoltre – e soprat­tutto – un fra­mework nasce con la pre­messa che l’inversione di con­trollo 1 sia una buona cosa. Ma è poi vero?

Se siamo incerti sul da farsi un fra­mework risulta pre­zioso per­ché, in un certo senso, non pos­siamo sba­gliare, appunto gra­zie all’inversione di con­trollo che det­terà a grandi linee i punti in cui inse­rirci. Viceversa, una libre­ria “nor­male” funge da sem­plice depo­sito di codice che viene chia­mato dall’applicazione, nei modi e nei tempi rite­nuti opportuni.

Quando e come con­viene usare un framework?

A mio parere, un fra­mework risulta van­tag­gioso con un pro­getto nuovo, dove è impor­tante riu­scire ad arri­vare ad un risul­tato nel minor tempo pos­si­bile ma, ideal­mente, sarebbe da con­si­de­rare come un’impalcatura che verrà smon­tata quando non è più necessaria.

Più facile a dirsi che a farsi, certo, ma non è raro che dopo una prima release un’applicazione venga riscritta senza i fra­mework usati in pre­ce­denza, spesso per ragioni di prestazioni.

  1. cito ancora:

    Reuse on this level leads to an inver­sion of con­trol bet­ween the appli­ca­tion and the soft­ware on which it’s based. When you use a tool­kit, you write the main body of the appli­ca­tion and call the code you want to reuse. When you use a fra­mework, you reuse the main body and write the code it calls.

« Voci Precedenti Prossime Voci »