mercoledì 28 gennaio 2015

I benefattori

Osservando le nuove offerte in campo dello sviluppo, vedo strumenti cross platform sopratutto per i cellulari.
Ho parlato con un amico, titolare di una importante software house, il quale mi diceva che stava cercando uno strumento per scrivere il codice una volta sola per Android e iOS.
Scrivere il codice una volta sola vuol dire risparmiare, avere una base unica sulla quale fare le modifiche, vuol dire tagliare i costi di produzione del proprio prodotto e raggiungere un target di clienti il più ampio possibile.

Uso Java dalla versione 1.0.1beta su OS/2 Warp, che i più giovani forse nemmeno ricordano. Dovrei sentirmi inorgoglito del fatto che oggi sempre più persone riconoscano che avevo ragione, che è importante non escludere dei clienti possibili, rispettando le loro scelte, perché il sistema operativo è parte importante del modo di lavorare di una persona e una persona lavora diverse ore al giorno...
Ricordo il dileggio di chi mi faceva notare che Microsoft era la più forte, che il mercato era saldamente nelle sue mani e gli altri erano ininfluenti. A onor del vero oggi lo scenario delle piattaforme mobili è ben diverso, molto più variegato e probabilmente gli stessi che tempo fa imparavano a usare VisualBasic e si sentivano Grandi Programmatori non si preoccuperebbero minimamente di studiare HTML, JavaScript, Java ecc... se il loro campione da seguire oggi fosse ancora il dominatore assoluto delle percentuali di installato, come negli anni '90. A loro vorrei ricordare che senza Java non ci sarebbe nemmeno C#, tentativo fallito di Microsoft di copiare una tecnologia allora migliore della loro. Oggi C# è un ottimo strumento per sviluppare su piattaforma Microsoft e gli altri mercati desktop sono ininfluenti, diverso invece è il discorso per quanto riguarda il mercato mobile.

Invece io non sono più così convinto che il cross platform sia la scelta vincente sempre.

E' più facile oggi fare cross platform rispetto a 20 anni fa: ci sono più librerie che nascondono la piattaforma e la crescente potenza dell'hardware permette di tenere degli strati di compatibilità tra l'applicativo nativo e il sistema sottostante. Penso per esempio all'ottimo Parallels su Mac OS X che permette di fare girare ad esempio  Microsoft Office per Windows senza vedere il desktop di Windows, ma di vedere le finestre Windows assieme a quelle del Mac. Penso proprio ai tempi di OS/2 quando di vedevano le finestre dei programmi per windows 3.1 assieme a quelle di OS/2, ma allora l'hardware non era così generoso come oggi e andava tremendamente piano.

20 anni di sviluppo cross platform mi hanno però insegnato che ci sono delle spine in questo mondo di rose. Le applicazioni cross platform non sfruttano mai le caratteristiche della macchina, ma soprattutto NON SI COMPORTANO SECONDO LE ABITUDINI DEGLI UTENTI.

Parlavo con un utente Windows che per le prime volte usava il fantastico The Gimp per il fotoritocco. Egli si arrabbiò perché la finestra di dialogo per aprire i file non era quella alla quale lui era abituato (The Gimp usava finestra di dialogo per Gnome) e questo particolare sminuiva tutto il progetto.

Chi ci "regala" applicazioni cross platform lo fa per LEGARCI ALLA SUA PIATTAFORMA, rendendo inutile il sistema operativo sottostante, per creare un ecosistema di applicazioni e quindi di persone, che hanno bisogno di lui. Questo spiega anche perché spesso le piattaforme cross platform impongono il loro look and feel anche quando potrebbero (e dovrebbero) appoggiarsi ai componenti del sistema sottostante. Garantire lo stesso aspetto su più piattaforme non serve tanto agli utenti, i quali tipicamente ne usano soltanto una. HTML5 mi sembra un'ottima specifica, applicata solo in parte dai produttori di piattaforme, i quali vedono positivamente la sostituzione di Flash, che è proprietario e i plugin sono pesanti, con uno standard aperto, ma l'idea che gli applicativi possano farsi senza dipendere da loro non va loro certamente a genio: quindi l'uso di uno strumento cross platform è sempre più scomodo per l'utente rispetto alle applicazioni native.

Prima di scegliere lo strumento bisogna pensare bene a cosa serve e a CHI LO USA.

NON DICO CHE BISOGNA TORNARE ALLE SOLUZIONI NATIVE in massa, dico che vedo un futuro migliore per chi sviluppa una soluzione nativa per il core dell'applicazione, che deve espandersi e crescere tramite dei generatori di codice o con dei motori che creano l'applicazione a partire da regole o parametri. Questa soluzione è oggi usata da pochi, per quando posso vedere dalla piccola finestra che ho sulla realtà, il motivo è che progettare un'applicazione è un conto, ma progettare un'architettura magari personale è tutt'altra cosa. Su questo fronte c'è ancora spazio per la piccola azienda creativa, che riscopra il valore della progettazione e dell'analisi sui dettagli che si ripropongono nei vari progetti dei quali si occupa.

La logica si può sviluppare con uno dei tanti linguaggi cross platform (Java, C#, JavaScript, anche il C++ 14 va bene) o con sistemi più sofisticati di scripting.
Anche le tanto vituperate stored procedure oggi sono piuttosto portabili e possono essere prese in considerazione e chi le sceglie merita rispetto.

Ci vuole coraggio per sviluppare la propria libreria di base. Scrivere generatori di codice o addirittura scrivere in xml dei layout che poi si applicano automaticamente ai dati da rappresentare, magari seguendo il Naked Object pattern e mettendo da parte il sopravvalutassimo MVC.

Sono queste secondo me le linee da seguire per chi nel 2015 non lavora solo su progetti altrui e vuole continuare a fare il proprio mestiere di produttore di progetti software, senza reinventare la ruota ma mantenendo la propria indipendenza e libertà.


domenica 18 gennaio 2015

Il Pinguino Talebano

  Sono un talebano, l'ho scoperto, me l'hanno detto tanto tempo fa e non ci volevo credere.
  Sono un incoerente che a volte apre il software a volte lo chiude, odia i progetti ai quali partecipa e che lo impegnano anima e corpo in una condizione monodimensionale, sottraendo tempo ed energie al resto della propria vita, come tutti i talebani insomma.

  Quindi?

  Per coerenza se sbatto la testa sul muro devo forse continuare a dare craniate affinché la gente mi applauda per la mia perseveranza, mentre io li ringrazio, con i cerotti in faccia magari?

  Stanco della classificazione e dei commenti, posso dire ora, dopo circa 20 anni di carriera nel campo del software, che la coerenza non mi interessa: mi interessano gli obiettivi e volta per volta cerco di decidere al meglio. Essere considerato un talebano perché i compromessi proposti dagli altri non risolvono il problema ora lascia il tempo che trova.

 Veniamo ora a capire perché si fanno progetti open source e dove invece l'open source non è da preferirsi.
  Ci sono diverse ragioni e motivazioni dietro alla rinuncia della segretezza: narcisismo, voglia di fare cose con gli altri, voglia di contattare altre realtà che ci possono dare lavoro, progetti scolastici, voglia di aiutare gli altri, voglia di restituire alla comunità mondiale una parte di ciò che si ha ricevuto, come se fosse un parziale risarcimenti di un debito ecc...

 Le scelte dietro alla volontà di aprire il codice VANNO RISPETTATE e ho sempre considerato dei cafoni coloro i quali hanno si facevano beffe all'inizio della comunità open, considerando a stregua di fessi quelli che rinunciavano al segreto del proprio lavoro per mettere le manette ai polsi dei propri utenti, pratica assai comune per costringere il malcapitato che ci aveva dato fiducia a continuare a pagare il bravissimo autore del proprio software.

 Ora, stando alle parole di Mr. Stallman, usare il cloud sarebbe stupido e toglierebbe libertà agli utenti. A parte il fatto che nessuno punta una pistola alla tempia dell'utente se non usa il cloud e usare il cloud è semplicemente un servizio comodo, poi ognuno fa le sue scelte.

  Ha senso aprire sempre il proprio codice, sviluppato magari a costi bassi come strategia commerciale per puntare a una lunga assistenza dopo ? Ha senso consentire ad altre persone di trarre giovamento dai nostri sforzi  e dalle nostre procedure o non è forse favorire un concorrente? E' una decisione troppo egoistica pretendere di vivere ? Oggi posso dire che a volte la chiusura è necessaria, per proteggerci da competitori senza scrupoli, però è altresì vero che sviluppare procedure ad hoc alle quali delegare la nostra sopravvivenza economica, in un mondo globalizzato, ha sempre meno senso.

  Quest'ultimo punto merita un approfondimento: 30 anni fa dove sviluppatori indipendenti e software house erano come isole staccate tra di loro, con comunicazione pressoché inesistente e delegata ai libri e alle riviste, era alta la probabilità che un diverse persone giungessero alle stesse conclusioni ma non venissero mai in contatto. La richiesta di software era in aumento costante, quindi la protezione e la chiusura erano strategie vincenti.

  Ma oggi assistiamo in ambito commerciale ciò che è stato per anni vero in ambito scientifico: le scoperte veramente originali sono pochissime, si cresce piano partendo da ciò che già esiste, le forze a disposizione delle piccole società di sviluppo sono poca cosa rispetto alla massa di software e di soluzioni testate e affidabili già disponibili.
  I grandi progetti custom sono necessari e sostenibili più che altro per le banche, le assicurazioni e la pubblica amministrazione, realtà che tipicamente rimangono proprietarie dei sorgenti dei quali commissionano lo sviluppo. La chiusura della soluzione geniale e originale venduta al cliente serve in pratica sempre meno, perché di originale non c'è proprio niente.

 Oggi l'open source è una necessità sempre più spesso, non necessariamente sempre.

 



 

 

lunedì 12 gennaio 2015

Mutatis mutandis

Ultimamente si vedono diversi articoli sulla rete che parlano di oggetti immutabili.

Addirittura classi final con metodi final che non dovrebbero essere nemmeno estensibili per evitare che una sottoclasse possa modificane il comportamento.
Indubbiamente in un contesto multi thread questa pratica risolve in partenza il problema dell'accesso concorrente, tuttavia si pongono dei problemi di ordine pratico rilevanti: per esempio se un oggetto è la radice di un albero e si desidera cambiare il nome del nodo radice, trattandosi di oggetti immutabili, bisognerebbe creare un nuovo oggetto radice e clonare tutti i nodi figli, cioè clonare l'intero albero.

Un approccio che non prevede alcun metodo set potrebbe essere devastante per lo spreco di risorse, prima di tutto per quanto riguarda l'uso della memoria, per non parlare del tempo di esecuzione.
Un altro problema degli oggetti immutabili riguarda i riferimenti alle vecchie versioni degli oggetti, che andrebbero cambiati per aggiornarli ai nuovi.

Ci può essere però una soluzione intermedia e di buon senso che risolve il problema tra oggetti mutabili e oggetti immutabili: il comportamento.

Un oggetto ha una identità, definita da uno o più proprietà, ma ha anche un comportamento, cioè ci sono dei dati che di solito sono archiviati da qualche parte e che possono cambiare senza che si cambi l'identità dell'oggetto. Per esempio prendiamo un oggetto anagrafica che ha nome, cognome indirizzo, per semplicità non ne consideriamo altri. Ora, cambiare il nome e il cognome significa cambiare l'identità della persona, quindi sono campi immutabili, il cui cambiamento è giusto che generi un nuovo oggetto anagrafica. Diverso invece è il discorso per quanto riguarda l'indirizzo, che può cambiare e che dovrebbe riflettere un  dato sul database, cioè la modifica dell'indirizzo si dovrebbe tradurre in un aggiornamento di un campo su un record dell'archivio.

In questo modo il campo indirizzo è mutabile, ma l'oggetto non muta, muta soltanto il suo "comportamento".
Il concetto di comportamento è più intuitivo se pensiamo a un oggetto che abbia il nome di un giocatore e il suo punteggio, il nome definisce l'identità e dovrebbe essere immutabile, invece il punteggio è mutabile. Dal momento che il punteggio magari è archiviato in un unico luogo (potrebbe essere una cache ma questo complicherebbe questo ragionamento, perché una cache non è altro che una copia più veloce dei dati), il riferimento degli altri oggetti all'oggetto giocatore non cambia.

Potrebbe essere questo compromesso una soluzione di buon senso. Peccato che tutto il mondo Java Enterprise non si comporti in questo modo e gli entity siano a tutti gli effetti una cache che copia spesso il modello delle tabelle sul db, essendo oggetti completamente mutabili.

La domanda che ci si può porre a questo punto è se gli oggetti del dominio applicativo possano essere degli entity o se invece non sarebbe più corretto ricorrere a oggetti che facciano da proxy verso gli entity, facendo venire i capelli bianchi a qualche manager di progetto, per i tempi di sviluppo iniziale... chissà... lascio aperto il dubbio ma credo di sì.


lunedì 5 gennaio 2015

Singleton con gli Enum

Chiudiamo questa breve carrellata sui pattern creazionali con la presentazione di una variante del Singleton Pattern.
L'intento di un pattern singleton è assicurare che una classe abbia soltanto un'istanza e che fornisca un punto globale per accedervi.

Questo implica che bisogna impedire agli altri programmatori di creare le proprie istanze, per non venire meno alla specifica di avere una sola istanza di questa classe.
Perché si debba volere una sola istanza è una scelta dell'architettura, che si può condividere o meno.
Personalmente ritengo che le singleton siano una pratica di programmazione non ottimale, soprattutto se diverse parti possono scriverci: espongono al rischio di avere dei problemi, tuttavia bisogna riconoscere alle singleton che possono tornare comode, mi viene da pensare per esempio ad una cache di dati o a un  insieme di proprietà di configurazione da accedere in sola lettura.

Le classi singleton sono spesso un problema, infatti negli ambienti managed non si possono realizzare usando semplicemente un metodo statico, che è pratica sconsigliata sia con Java Enterprise, che con Android e in generale è sconsigliabile in tutti quei casi dove ci possono essere diverse virtual machine o nodi paralleli.

La novità qui è che si può definire un costruttore privato oppure un tipo enum.

public enum Paolo {
  INSTANZA;

  public void faiQualcosa() {
  ...
  }
}

Non è una tecnica molto utilizzata, perché pochi la conoscono, però il tipo enum a un solo elemento rappresenta la soluzione migliore per implementare un singleton.

In caso di deserializzazione non si creano altre istanze e non c'è bisogno di scrivere altro codice per questo, come avviene con gli altri approcci.

Riferimenti presi da "Design Pattern Java Workbook" di Steven John Metsker ed. Eddison Wesley e Effective Java di Joshua Bloch editore Pearson Informatica.