fbpx

Satis e Composer: come cambiano la vita di uno sviluppatore

ArticoloLAB_SatiseComposer_Blog

Vi è mai capitato di arrivare ad un punto della vostra vita da programmatori e dire: “Che cavolo: devo sviluppare di nuovo una mappa con geolocalizzazone… vabbè, lo copio da un altro progetto!” E poi ritrovarvi a migliorare la vostro mappa che vi state portando dietro da decine di progetti come la ruota di Fantozzi… e dopo averla migliorata, desiderare di aggiornarla ovunque?

Scordatevelo di farlo a mano! Riuscireste a tenere allineati massimo 2-3 progetti senza causare esplosioni termonucleari! Però viene la curiosità di capire come fa il resto del mondo, faccio ricerca e… ora sono più di tre anni che abbiamo trovato una soluzione a questo problema, e ci piace condividere con voi il nostro modo di lavorare.

Se siete sviluppatori Symfony o Laravel saprete bene che cosa sia Composer, se invece usate WordPress… le mie più sentite condoglianze!

Composer, per chi non lo sapesse, è un gestore di dipendenze per librerie PHP, e tramite la configurazione di un file json è possibile richiedere le librerie che intendiamo importare all’interno del nostro progetto. Il suo repository manager pubblico è Packagist dove sono disponibili decine di migliaia di librerie PHP che possono aiutarti a velocizzare il tuo sviluppo, tra cui circa 4000 librerie pubbliche per Symfony e 24000 per Laravel. Chiunque può contribuire alle community che usano composer come base dei propri progetti, ma come si fa?

Non è difficile: basta un repository git e sapere un minimo come funziona composer. 

Proviamo a creare la nostra prima libreria: come esempio proveremo a fare un bundle per Symfony.

Creiamo il nostro repository (es: su github o su bitbucket) e cloniamolo su computer.

Il primo passo da fare è creare il file composer.json, che sarà letto dal repository manager e indica tutte le dipendenze necessarie per il corretto funzionamento della libreria che sto creando.

Un esempio di composer.json, già arricchito di qualche info accessoria può essere

{
 "name": "oi/example",
 "type": "lib",
 "description": "Bundle di esempio",
 "keywords": ["Example"],
 "homepage": "https://www.oimmei.com",
 "license": "MIT",
 "authors": [
   {
     "name": "Ephraim Pepe <[email protected]>"
   }
 ],
 "require": {
   "php": ">=7.1"
 },
 "autoload": {
   "psr-4": {
     "OiExampleBundle": "src/"
   },
   "exclude-from-classmap": [
     "/Tests/"
   ]
 }
}

Il file json ha diverse chiavi, nel nostro caso d’uso le più significative sono:

  • name: nome della libreria, deve essere univoco in assoluto. Per installarla si dovrà chiamare il comando composer require oi/example, inoltre il name indica in quale cartella di vendor verrà copiato il codice, quindi se voglio modificare la mia libreria potrò andare cercare in <root>/vendors/oi/example
  • require: è la parte più importante del nostro composer.json e contiene tutte le dipendenze della nostra libreria, è qui che vengono indicate le librerie necessarie e le loro versioni per il corretto funzionamento del codice che state scrivendo.
  • autoload/psr-4: contiene la mappatura dei namespaces (solitamente è solo una, ma dà comunque la possibilità di specificare anche più namespaces), in questo caso il namespace OiExampleBundle avrà come base <root>/vendors/oi/example/src (nb: il valore “src/” può essere anche omesso, e nel caso avessimo messo “OiExampleBundle”: “” OiExampleBundle avrebbe avuto come base <root>/vendors/oi/example/).

La documentazione completa di composer.json potete trovarla all’indirizzo https://getcomposer.org/doc/ e qui sarà facile reperire tutte le informazioni su come strutturare il vostro file json.

Prima di proseguire, vi invito a visitare Packagist il repository manager di Composer. Qui possiamo ricercare le librerie pubbliche esistenti da includere eventualmente nel nostro progetto.

Il sito si presenta con il motore di ricerca e le istruzioni base per poter usare le librerie registrate e/o contribuire con le proprie. Ipotizziamo di voler usare le funzionalità di Mapbox all’interno del nostro codice e dopo aver effettuato la ricerca decidiamo ad esempio di voler usare la libreria geocoder-php/mapbox-provider, scelta fatta perché confrontando il numero di utilizzi e la documentazione, rispetto ad altre è decisamente la libreria migliore.

Ora possiamo aggiornare il nostro file composer.json aggiungendo delle dipendenze:

{
 "name": "oi/example",
 "type": "lib",
 "description": "Bundle di esempio",
 "keywords": ["Example"],
 "homepage": "https://www.oimmei.com",
 "license": "MIT",
 "authors": [
   {
     "name": "Ephraim Pepe <[email protected]>"
   }
 ],
 "require": {
   "php": ">=7.1",
   "geocoder-php/mapbox-provider": "1.1.*",
   "symfony/framework-bundle": "^4.2 || ^5.0"
 },
 "conflict": {
   "symfony/framework-bundle": "<4.2"
 },
 "autoload": {
   "psr-4": {
     "OiExampleBundle": "src/"
   },
   "exclude-from-classmap": [
     "/Tests/"
   ]
 }
}

 

Vediamo che abbiamo aggiunto due dipendenze: la prima relativa a geocoder-php/mapbox-provider per tutte le versioni che iniziano per 1.1 (da qui la sintassi “1.1.*”), la seconda a symfony/framework-bundle per le versioni 4.2 o superiore e 5.0 o superiore (la sintassi ^4.2 permette di prendere tutte le versioni di 4.2, ma anche 4.3 e 4.4, mentre un cambio di major version non viene contemplato, per questo è necessario mettere in or le versioni con la sintassi “^4.2 || ^5.0”)

Notate anche la nuova chiave conflict: viene usata per indicare esplicitamente quando alcune versioni di librerie richieste non sono compatibili con la libreria che stiamo sviluppando.

Dopo questa breve spiegazione di come gestire le dipendenze, possiamo scrivere il nostro codice (seguiamo le best practices indicate sul sito ufficiale per mantenerci coerenti con gli standard di Symfony) e ora abbiamo la seguente struttura di cartelle:

Effettuiamo il push del codice su git e aggiungiamo un tag (es: 1.0.0). Consiglio di avere almeno 3 cifre, noi le chiamiamo <major>.<minor>.<version>: 

  • la version si aggiorna quando effettuiamo bugfix, aggiungiamo funzionalità, ottimizziamo il codice.
  • la minor si aggiorna quando c’è un cambio di logica che rischia di poter rendere incompatibile il codice con versioni precedenti.
  • la major si aggiorna quando c’è un salto tecnologico o logico molto importante o un refactoring del codice, un cambio di modello dati o altri interventi talmente grandi da essere certi di una mancata retrocompatibilità con la versione precedente.

Ora per pubblicare la vostra libreria, potete registrarvi a Packagist e seguire le istruzioni, e così la vostra libreria sarà pubblica, e chiunque potrà scaricarla ed utilizzarla.

Tutto molto bello, vero? Scommetto però che ci sono alcuni di voi che dicono “Sì, ma io non voglio condividere il mio codice, lo voglio usare solo io!

Ci sono 2 soluzioni, una sporca e una pulita:

  1. La fémo sporca? Questa soluzione è adatta a chi è a corto di tempo e di denaro, quindi usiamo un repository pubblico, ma non scriviamo la documentazione per il mio codice… vedrete che saranno in pochi a scaricare le vostre librerie… ma qualcuno può farlo e provare a fare un po’ di retroingegneria…
  2. Fémola pulita! Prendiamo un server, ci installiamo un server git o acquistiamo un account a pagamento che ci permette di avere repository privati, e sul server installiamo Satis, ovvero un repository manager privato, scritto dagli stessi autori di Composer!

Guardiamo quindi come poter installare Satis sul nostro server, e scopriremo che è semplicissimo!

Naturalmente si installa via Composer ed il comando da lanciare è 

php composer.phar create-project composer/satis --stability=dev --keep-vcs

e verrà creata una cartella ./satis là dove avete lanciato il comando, e questo è il contenuto della cartella:

nella root del progetto dovrete creare un file satis.json con il riferimento ai vostri repository

{
  "name": "oi/bundles",
  "homepage": "http://satis.oimmei.com",
  "repositories": [
    { "type": "vcs", "url": "https://[email protected]/oimmei/examplebundle.git" },
    { "type": "vcs", "url": "https://[email protected]/oimmei/testbundle.git" }
  ],
  "require-all": true
}

dovrete assicurarvi di caricare la vostra chiave ssh del server sul vostro github o bitbucket di turno e poi potete lanciare il comando 

php bin/satis build satis.json packages

Satis aggiornerà la sua libreria interna e ora è pronto per essere esposto via web: configurate il vostro web server (il nostro esempio è di nginx, anche perché gli esempi di apache abbondano online)

server {
    server_name packagist.oimmei.com;
    return  301 https://$server_name$request_uri;
}
server {
    server_name satis.oimmei.com;
    root /var/htdocs/satis/packages;
    include global/letsencrypt.conf; #configurazione comune a tutti i progetti https

    index index.html;
    location / {
try_files $uri $uri/ /index.php?$args;
    }
    location ~ .php$ {
include fastcgi.conf;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_index index.php;
    }
    location ~* .(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
    }

    rewrite ^http://(.*)$ https://$1;
    listen 443 ssl;
    ssl_certificate /var/www/letsencrypt/certs/packagist.oimmei.com/fullchain.pem;
    ssl_certificate_key /var/www/letsencrypt/certs/packagist.oimmei.com/privkey.pem;

    error_log /var/log/nginx/packagist.oimmei.com_error.log;
    access_log /var/log/nginx/packagist.oimmei.com_access.log;
}

riavviate il web server et voilà, il vostro repository manager è pronto ad essere usato!

Ma non è finita! Per usare le vostre librerie all’interno del progetto dovrete aggiungere il codice indicato nell’intestazione della pagina web del vostro satis.

{
   "type": "project",
   "license": "proprietary",
   "require": {
       ...
       "oi/example": "4.3.1.*",
       ...
   },
   ...
   "repositories": [{
       "type": "composer",
       "url": "https://packagist.oimmei.com"
   }]
}

Il file satis.json può contenere un array di repository, e ogni volta che aggiungete una nuova libreria o rilasciate una nuova versione di una libreria già registrata dovrete lanciare nuovamente il build.

Ora che avete il vostro repository manager sarà molto semplice riutilizzare lo stesso codice che avete scritto per gestire le mappe con geolocalizzazione in tutti i progetti che volete, e quando create una nuova versione sarà sufficiente andare sui progetti desiderati, cambiare eventualmente il vostro composer.json di progetto e lanciare il comando

php composer.phar up

Ephraim Pepe

Symfony Live London 2016

  • Symfony Live London 2016
  • Symfony Live London 2016
  • Symfony Live London 2016
  • Symfony Live London 2016
  • Symfony Live London 2016
  • Symfony Live London 2016

Oimmei ha partecipato al congresso Symfony Live London 2016. Una nuova esperienza inglese per noi, diversa dalle precedenti, ma sicuramente molto interessante.

La prima cosa da segnalare è l’imponente organizzazione di cui gran parte del lavoro è stato fatto da Anne Sophie Bachelard, che ha curato ogni minimo aspetto della comunicazione, a partire dalle email dei giorni precedenti a chi ha partecipato ai workshop alla conduzione della conferenza del secondo giorno.

Sicuramente ci sarebbe tanto da dilungarsi, ma cercheremo di andare subito al sodo.

Sono stati due giorni intensi: il primo dedicato ad un workshop (ce ne erano 4 a cui era possibile partecipare, abbiamo scelto il workshop dedicato ad API Platform 2.0), ed il secondo è stato un susseguirsi di talk, spesso in contemporanea in più sale, e per questo abbiamo dovuto scegliere quelli che secondo noi potevano essere più interessanti per il nostro lavoro.

GIORNO 1: PLATFORM API 2.0

Questa giornata è stata sicuramente la giornata di maggior interesse di questa due giorni. Abbiamo assistito alla presentazione in anteprima della nuova Platform API 2.0. La Platform API 2.0 sfrutta al massimo le potenzialità di Symfony 3.0 e del PHP 7.0 e ci hanno lasciato molto entusiasti.

Il seminario è stato tenuto da Samuel Roze (ideatore del progetto) (github) coadiuvato da Kévin Dunglas (github) e Amrouche Hamza (github), altri due sviluppatori del progetto (Kévin è anche uno degli sviluppatori del Core di Symfony).

In classe eravamo in 8, provenienti un po’ da tutta Europa (eccetto 2 Indiani) e tutti al primo approccio con l’API Platform.

La giornata è passata realizzando la demo che attualmente presentano su https://demo.api-platform.com/ e c’è da dire una cosa: il codice scritto è stato veramente minimo!

Le API Platfom 2.0 sono veramente impressionanti per velocità di sviluppo e semplicità!

Le Annotation sono le artefici di questa “magia”. Se si conoscono bene è possibile scrivere pochissimo codice! Questo ci spinge a dire che con molta probabilità, considereremo di usarle nelle prossime App che Oimmei svilupperà!

Naturalmente finita la demo abbiamo abbiamo avuto modo di vedere anche altre funzionalità che già ora stiamo usando nelle nostre integrazioni web-app e che ci stanno permettendo di sviluppare con maggior velocità e minor probabilità di errori le nostre chiamate server.

Ci sono tante cose da dire sulle Platform API 2.0, ci ripromettiamo di parlarne in futuro in un articolo dedicato, per ora vi lasciamo con un parere più che positivo!

GIORNO 2: IL SYMFONY DAY

Mentre ai seminari la partecipazione era di poche decine di persone (circa 30 fra tutti e 4 i workshop) alla seconda giornata erano presenti oltre 300 sviluppatori da tutto il mondo! È stato impressionante vedere tutti questi sviluppatori riuniti a Londra per seguire e per conoscere le novità di Symfony 3, ed è stato deludente scoprire che Oimmei è stata l’unica realtà italiana a partecipare!

Dopo una breve presentazione fatta Anne Sophie che ci ha illustrato la giornata, e subito dopo sono iniziati i talk, tutti rigorosamente della durata di 40 minuti.

Poiché molti talk, come già scritto, erano in contemporanea, abbiamo seguito quelli che ci sembravano più adatti al nostro target lavorativo: non sempre abbiamo azzeccato il talk più adatto, ma comunque è stato interessante.

Dopo il benvenuto, Beau Simensen (github) ha messo subito le cose in chiaro: Symfony non è facile da digerire, è potente, ma molto ostico, soprattutto se non si seguono le best practics suggerite dalla Sensio Labs. L’organizzazione del codice è essenziale per la manutenibilità dei progetti. Se si approccia allo sviluppo senza avere le idee chiare, il rischio è di avere un codice confuso. La cosa interessante è che ha demonizzato l’uso dei form di Symfony, cosa che avrebbe fatto sicuramente saltare di gioia Andrea!

Dopodiché abbiamo ritrovato Samuel Roze che ci ha raccontato la sua personale esperienza con i Design Pattern. Un ottimo esempio di come in pochi anni, sia riuscito a padroneggiare prima un linguaggio e poi un framework con il solo studio dei design pattern (e di come abbia sfruttato ciò che ha imparato per realizzare la Platform API 2.0)

Jules Pietri (github) invece avrebbe fatto disperare Andrea, perché al contrario di Beau ha messo il focus del suo intervento sui form, ma soprattutto ne ha esaltato la loro versatilità se usati come servizi di Symfony. È stato sorprendente: non conoscevamo ancora questa possibilità, e così appena rientrati abbiamo iniziato a creare i primi form gestiti da servizi, e c’è da dire che, anche se non è immediato da capire, alla fine il codice da gestire è molto più semplice.

Prima della pausa, ci sono stati un paio di speed talk da 5 minuti, dove abbiamo iniziato a sentire parlare di Docker, e la cosa mi stuzzica.

Dopo pranzo sono continuati gli interventi, e abbiamo scelto di seguire quello di Jakub Zalas (github) sul microkernel di Symfony. Eravamo incuriositi da lui perché il giorno prima durante una pausa l’abbiamo incrociato al buffet, e sentivo che sparava a zero sulle criticità del PHP e su come non siano mai state affrontate seriamente dagli sviluppatori del linguaggio. Ci è bastato per rendercelo subito simpatico, ma purtroppo l’argomento del suo talk non mi ha preso tanto. È stato forse troppo astratto rispetto a quello che mi aspettavo, ad ogni modo abbiamo scoperto che dalla versione 2.8 è stato introdotta la possibilità di usare un kernel ridotto che a discapito di un minor numero di funzionalità possibili, maggior verbosità del codice, migliora le prestazioni e diminuisce l’uso di memoria.

E ora era l’ora di Docker presentato da Andre Rømcke (github) della ezSystem (uno degli sponsor dell’evento). Sinceramente era il talk che aspettavamo maggiormente, ma anche quello che ci ha deluso maggiormente! Conoscevo già Docker, ce lo aveva presentato il nostro amico Arialdo (github), ce l’aveva suggerito per l’installazione dei software su un server, ci eravao già documentati un po’, ma alla fine non abbiamo voluto rischiare di stoppare uno dei nostri server per passare tutto su Docker. Così, quando abbiamo sentito ripetere cose che già sapevamo, è stato deludente. Quando poi nelle slide ha fatto vedere i file di configurazione per usare Docker per far girare un’istanza di Symfony, è stato talmente veloce che non c’è stato nemmeno il tempo di fare una foto per provare a replicare quella configurazione.

Dopo l’ultimo break abbiamo seguito il talk di Nicolas Grekas (github) su come Symfony stia seguendo a pieno le linee guida del PSR-6 per la gestione della cache. Per chi non lo sapesse il PSR sono degli standard raccomandati per PHP (PHP Standards Recommendations) ancora in via di stesura, e che ha come obiettivo la standardizzazione dei concetti di programmazione in PHP ispirandosi all’ormai consolidato JSR (Java Specification Request).

E infine… gran finale con domande a ruota libera al Team di sviluppo del core di Symfony, e fra i 4 sviluppatori abbiamo ritrovato Kévin e Jakub. L’imbarazzo iniziale era palpabile, ma dopo che Samuel Roze ha rotto il ghiaccio chiedendo quando Symfony abbandonerà PHP 5 per passare a PHP 7 le domande hanno iniziato a venire. Così hanno parlato di Roadmap, di come decidono il contenuto di una nuova release, della prima LTS di Symfony 3 e molto altro.

Insomma sono stati due giorni veramente intensi e che hanno permesso di accrescere le conoscenze di questo framework sicuramente ostico, ma decisamente potente!