"Se ci sono due o più modi di fare una cosa,
e uno di questi modi può condurre a una catastrofe,
allora qualcuno la farà in quel modo.

(Edward Murphy)

Aggiungere software di terze parti: YAML

Dom, 16/03/2014 - 12:47 -- arturu

Siamo arrivati al punto in cui abbiamo costruito la base del core e l'avvio delle "app" specifiche. Ora in questo articolo cerchiamo di semplificare la gestione della fase di boot per renderla il più modulare possibile. Concentriamoci su "\Concerto\Core::boot()", attualmente abbiamo scritto:

/**
* @todo Metodo che avvia il sistema
* @access public
*/
public function boot() {
       
    // // faccio partire security
    // Security::run();
       
    // faccio partire il getore della sessione
    Sessione::run();
       
    // faccio partire la localizzazione
    Locale::run();
       
    // faccio partire il gestore delle richieste
    Request::run();
       
    // faccio partire il routing
    Routing::run();
       
    // faccio partire le applicazioni
    App::run();
        
    // // setto il tipo di Response
    // Response::run();
       
    // // faccio partire il sistema di templating
    // Template::run();
        
}

Andado ad analizzare ciò che abbiamo scritto ci rendiamo conto che se si volesse usare altri gestori bisognerebbe modificare manualmente questa funzione, questo modo di procedere non è molto ottimale, specialmete durante gli aggiornamenti, infatti, ad ogni aggiornamento del Core bisognerebbe andare a modificare ogni volta questa funzione. La soluzione migliore è definire un elenco con i vari gestori dentro un file di configurazione, il metodo boot() recupera l'elenco e li avvia in sequenza. Quest'ultima soluzione ci permette di generalizzare e rendere più snello il metodo boot(), ma in special modo, ci permette di poter inserire, togliere, modificare, estendere il nostro boot().

Ricordiamoci sempre che il ragionamento è parte dello sviluppo, adottare un modo di ragionare che ci permetta di scrivere il meno codice possibile è sempre positivo, in quanto, la soluzione di molti problemi è intrinseca alle soluzioni adottate. Andiamo per gradi, la prima operazione è costruire un array con l'elenco, boot() diventa:

/**
 * @todo Metodo che avvia il sistema
 * @access public
 */
public function boot() {       
    // l'eleco delle applicazioni del core da avviare
    $core_boot = array(
        // '\Concerto\Security', // analizza gli input
        '\Concerto\Sessione', // il gestore della sessione
        '\Concerto\Locale', // gestore della localizzazione
        '\Concerto\Request', // gestore delle richieste
        '\Concerto\Routing', // routing
        '\Concerto\App', // gestore delle applicazioni
        // '\Concerto\Response', // gestore di response
        // '\Concerto\Template', // gestore di template
    );
        
    // avvio le applicazioni come da elenco
    foreach ($core_boot as $value) {
        $value::run();
    }    
}

Il modo "sbagliato" (per sbagliato intendo: non ottimale) per modificare la sequenza di boot() sarebbe stato l'uso di diverse funzioni hook e di if, else, elseif, isset ecc, che in questo caso ci avrebbero fatto scrivere molto più codice, facendo aumentare i probabili bugs, costi nello sviluppo, nel mantenere il codice e tempo speso nella formazione da parte di chi utilizzerà il nostro framework.

Come si può vedere, abbiamo costruito un array in cui ogni elemento è il gestore (o app, chiamatevo come più vi piace) da avviare, l'abbiamo scritto nel formato "\Namespace\App", facendo in questo modo sarà facilemente estensibile. Facciamo un ipotesi: c'è l'esigenza di estendere il gestore della sessione, ad es. si andrà a costruire il gestore in "\Esempio\Sessione" (si può estendere o costruire ex novo), successivamente, nell'array $core_boot si sostiuisce "\Concerto\Sessione" con "\Esempio\Sessione". Logicamente se si costruisce ex novo un qualsiasi elemento (invece che estendere) bisognerà stare attenti a fornire sempre lo stesso tipo di interfaccia agli altri oggetti che lo utilizzano.

Ora dobbiamo preoccuparci di spostare l'array in un file esterno che sia facilmente personalizzabile, per fortuna non dobbiamo svilupparlo in quanto esiste già un'ottima soluzione per fare ciò. YAML è un formato che ci permette di scrivere un array in un formato facilmente comprensibile da un essere umano, è utilizzato in tantissimi progetti di grande importanza come Symfony. Per chi vuole approfondire può leggere questa pagina Il componente YAML.

Esistono diversi parser YAML, riutilizzeremo quello di Symfony 2, lo possiamo trovare a questo indirizzo: https://github.com/symfony/Yaml, scarichiamo il file zip e lo scompattiamo dentro "/app/Symfony/Component/Yaml" (NB. se per caso durante l'esecuzione riceviamo un errore di Classe non trovata, dobbiamo dare una sistemata ai permessi sui file, il webserver deve avere i permessi di lettura).

Scriviamo il nostro file di configurazione in "/app/Concerto/boot.yml":

Vedi Codice Su GitHub

Il nostro core diventa:

Vedi Codice Su GitHub

Così facendo abbiamo spostato la sequenza di avvio dentro un file di configurazione, facile da capire e facile da modificare.

Vedi Commit Su GitHub