Share |

mercoledì 14 luglio 2010

Anticipazione: Source Code Decorator

E' in fase di collaudo un nuovo componente software, da me pensato e realizzato, per formattare il codice sorgente, presente in molti miei articoli, come farebbe un IDE evoluto(Integrated Development Environment, in italiano: Ambiente di sviluppo integrato), per rendere più leggile codice sorgente già ben presentato.

Stato avanzamento dei lavori

Durante le sessioni di test, iniziate ormai da qualche giorno, mi sono reso conto di alcune differenze strutturali tra i vecchi posts, scritti con il vecchio editor di Blogger, ed i nuovi, scritti con l'ultima versione dell'editor fornito: tali differenze strutturali, purtroppo, interagiscono con l'esecuzione del nuovo componente Source Code Decorator causando solo nei vecchi post delle inattese ed inopportune sorprese!

Il componente che sto collaudando, che rientra nel vasto concetto di Parser, lavora bene anche con i vecchi posts, nel senso che il suo sporco lavoro di formattazione lo esegue correttamente, anche se però poi ripresenta tutto il codice, correttamente riformattato, scrivendolo su una unica riga, perdendo di fatto tutta l'indentazione originale del codice ed anche il senso della sua funzione, ovvero rendere più leggile codice sorgente scritto secondo le regole del buon programmatore.

Questo problema, che si manifesta con la perdita di tutta l'indentazione del codice, è dovuto fondamentalmente al fatto che il vecchio editor aggiungeva ad ogni fine riga il tag HTML <br /> anche nelle parti di codice contenute nell'elemento <PRE>.

Utilizzando invece l'ultima versione dell'editor fornito da Blogger, tutto questo non si verifica più: effettivamente il <br /> non è più presente ed è sostituito dal carattere di nuova linea rappresentato comunemente dalla scrittura \n.

Quindi, prima di poter rilasciare definitivamente il nuovo componente, dovrò normalizzare tutti i vecchi articoli postati.


Da fare prima del rilascio

Di seguito la lista delle attività necessarie da completare prima di rilasciare il componente:

  • Censire gli articoli scritti con il vecchio editor di Blogger: completata il 10/07/2010;
  • Normalizzare i vecchi articoli individuati dallo step precedente: completata il 12/07/2010;
  • Introdurre il componente e verificare la formattazione del codice sorgente delle intere sezioni:
    • Java: completata il 16/07/2010;
    • Javascript: completata il 25/07/2010;
    • PHP: completata il 13/07/2010;
    • XML: completata il 25/07/2010;
    • XPath: completata il 25/07/2010;
    • XSD;
    • XSLT;
  • Racchiudere il codice del componente in un unico file .js;
  • Procedere alla minimizzazione del codice javascript;
  • Modificare il template di Blogger per compiere il rilascio definitivo del nuovo componente;

Detto questo, posso comunque rilasciare delle anticipazioni e degli screenshots sul componente, su come opera e cosa si ottiene utilizzandolo.


Source Code Decorator

Come dicevo, si tratta di un parser scritto in Javascript, il cui peso attualmente non supera i 10KB.

Ad oggi se la cava benissimo con l'analisi e la formattazione di codice Java, Javascript e PHP, mentre devo ancora finire i test per quanto riguarda il linguaggio XML e derivati.

Di seguito alcuni screenshots del risultato dell'elaborazione del codice da parte del Source Code Decorator:

Esempio di formattazione di codice sorgente Java:
Esempio di formattazione di codice sorgente Java

Esempio di formattazione di codice sorgente PHP:
Esempio di formattazione di codice sorgente PHP

Il componente consiste fondamentalmente in una classe Javascript, che incapsula la logica del parser provvedendo all'analisi del codice sorgente ed alla sua formattazione (colori differenti per classi, funzioni, tipi primitivi, operatori, commenti, Javadocs ecc...), e da un mappa, o HashMap, che ragionando nei termini di chiave/valore è ottimizzata per il recupero del codice HTML da sostituire ad ogni ricorrenza di determinati tokens.

Da ora al momento del definitivo rilascio, il componente acquisirà un peso maggiore, sicuramente non spropositato, e questo dipenderà dal livello di formattazione e precisione che mi farà sentire soddisfatto.

E' già all'ordine del giorno, nel momento in cui il componente sarà rilasciato definitivamente, la sua minimizzazione per ridurne il peso totale; sarà distribuito ovviamente in un file .js dedicato in maniera da sfruttare i sistemi di caching dei browsers.

Perchè Javascript?

Aver scelto Javascript per eseguire questo compito garantisce che nessun utente subirà rallentamenti durante la navigazione dovuti ad un maggiore impegno di risorse del web-server, che non dovrà elaborare la formattazione, perchè sarà il client utente, utilizzando le proprie risorse, a riformattare il codice sorgente degli articoli letti.


Il tuo contributo

Se ti accorgessi di qualche problema di impaginazione su articoli datati, è probabilmente dovuto alla mancata normalizzazione dell'articolo stesso(mea culpa), ti chiedo gentilmente di comunicarmelo inviandomi una mail o, meglio ancora, postando un commento sull'articolo stesso.

Successivamente al rilascio del componente, provvederò a redarre un articolo per spiegarne nei dettagli il codice sorgente ed il suo utilizzo.

Alla prossima,
MA

sabato 10 luglio 2010

Java: Leggere, scrivere e modificare files

In questo articolo Java presenterò il componente software FileFactory che automatizza le più comuni operazioni di I/O su file system e che facilita quindi il compito dello sviluppatore Java.

Premesse

La classe FileFactory nasce in ambito lavorativo dall'esigenza di dover supportare la generazione di files complessi utilizzando come input files di template.

In particolare, per ogni template in input deve essere generato lo stesso output, ma con alcune parti, conosciute a priori e dette anche tokens, differenti perché sostituite alle originali.

Per agevolare la programmazione e garantire il corretto accesso al file system e lo svolgimento di tutte le operazioni necessarie, la classe espone un set di metodi pubblici e statici grazie ai quali è possibile:

  • referenziare una risorsa esistente, o crearla;
  • verificare l'esistenza di una risorsa;
  • eliminare una risorsa;
  • leggere il contenuto di un file;
  • scrivere in un file;
  • modificare il contenuto di un file;

Per mostrare quanto è semplice compiere operazioni di I/O su file system utilizzando la classe FileFactory, ho preparato come esempio la generazione di fantomatici menù di cucina a partire da un file template. Come output, oltre al menù del Lunedì avremo anche il file di log per controllare se tutte le operazioni si sono concluse correttamente.

La classe FileFactory

La classe è fondamentalmente un gestore di servizi per operare su files; non è necessario crearne istanze ed i servizi che offre sono tutti rappresentati dai metodi pubblici e statici accessibili.

Il codice sorgente della classe FileFactory è pulito, ordinato, ben commentato e formattato secondo le regole della sintassi Javadoc.

Come si può notare è presente il metodo main: al suo interno è documentata la logica dell'esempio che ho scelto per mostrare l'utilizzo intuitivo del componente.

Di seguito il codice sorgente della classe Java FileFactory, mentre il file di template menu_template.txt, utilizzato nell'esempio per la creazione dei menù del giorno, è reperibile a questo indirizzo.

/**
 * Factory per la creazione/modifica/lettura 
 * e verifica di risorse su filesystem.
 * 
 * @author  Mirko Agrati
 * @version 1.2
 */
public class FileFactory {
 
  /**
   * Testa l'esistenza di una risorsa su filesystem.
   * 
   * @param path L'indirizzo fisico della risorsa.
   * @return     <code>true</code> se esiste 
   *             altrimenti <code>false</code>.
   */
  public static boolean fileExists(String path){
    return new File(path).exists(); 
  }
 
  /**
   * Restituisce il contenuto del file 
   * all'indirizzo <code>path</code>
   * 
   * @param  path  Indirizzo fisico del file da leggere.
   * @return       Il contenuto del file in una stringa.
   * 
   * @throws FileNotFoundException
   * @throws IOException
   */
  public static String getFileContent(String path) 
      throws FileNotFoundException, IOException{
    String content = "";
    BufferedReader br = 
        new BufferedReader(new FileReader(path));

    while (br.ready())
      content += "\n" + br.readLine();
     
    br.close();
    return content;
  }

  /**
   * Restituisce il contenuto del file <code>f</code> 
   * 
   * @param  f  Il file da leggere.
   * @return    Il contenuto del file in una stringa.
   * 
   * @throws FileNotFoundException
   * @throws IOException
   */
  public static String getFileContent(File f) 
      throws FileNotFoundException, IOException{
    String content = "";  
    BufferedReader br = 
        new BufferedReader(new FileReader(f));
  
    while (br.ready())
      content += "\n" + br.readLine();
     
    br.close();
    return content;
  }
 
  /**
   * Ricerca nel file <code>f</code> 
   * tutte le ricorrenze di ogni chiave della mappa 
   * <code>h</code>
   * per sostituirle con i valori ad esse abbinate. 
   * 
   * @param f  File in cui eseguire la ricerca 
   *           ed eventuale sostituzione.
   * @param h  Contiene le chiavi da ricercare 
   *           e i valori con cui sostituirle.
   * @return   Il contenuto del file con 
   *           le sostituzione apportate.
   * 
   * @throws FileNotFoundException
   * @throws IOException
   */
  public static String getSubstitutedFileContent
        (File f, Hashtable<String, String> h) 
      throws FileNotFoundException, IOException{
    String content = "";  
    BufferedReader br = 
        new BufferedReader(new FileReader(f));

    while (br.ready())
      content += "\n" + substitute(br.readLine(),h);
     
    br.close();
    return content;
  }
 
  /**
   * Esegue le sostituzioni chiavi/valori 
   * nella stringa ricevuta.
   * Nel caso valore contenga chiave allora 
   * verrà sostituita solo la prima occorrenza.
   * 
   * @param input  La stringa su cui operare
   * @param h      Le chiavi ed i valori necessari.
   * @return       La stringa con le sostituzioni apportate
   */
  private static String substitute
      (String input, Hashtable<String, String> h){
    if(input.length()<1) return "";
  
    Enumeration<String> keys = h.keys();  
    while(keys.hasMoreElements()){   
      String key = keys.nextElement();   
      String value = h.get(key);
      int index = input.indexOf(key);
      
      while(index > -1){
        String firstpart = 
            input.substring(0,index) + value + "";
        String lastpart = 
            input.substring(index+key.length());
        input = new String(firstpart + lastpart);    
  
        index = (value.indexOf(key)>-1) 
            ? -1 : input.indexOf(key);
      }
    }
    return input;
  }
 
  /**
   * Inserisce del contenuto in un file.
   * 
   * @param f        File in cui scrivere
   * @param content  Contenuto da scrivere nel file
   * 
   * @throws FileNotFoundException
   * @throws IOException
   */
  public static void setFileContent
        (File f, String content) 
      throws FileNotFoundException, IOException{
    FileOutputStream fos;      
    fos = new FileOutputStream(f);
    fos.write(content.getBytes());
    fos.close(); 
  }
 
  /**
   * Rimuove un file.
   * 
   * @param path  Indirizzo fisico del file da cancellare.
   * @return      <code>true</code> se il file è stato 
   *              eliminato, altrimenti <code>false</code>. 
   */
  public static boolean removeFile(String path){
    return new File(path).delete();
  }
 
  /**
   * Crea un file.
   * 
   * @param path        Indirizzo fisico del file da creare.
   * @param isdirectory Indica se bisogna creare una directory
   * @return            Il file creato oppure <code>null</code> 
   */ 
  public static File createFile
        (String path, boolean isdirectory) 
      throws IOException{
    File f = new File(path);
    boolean created = (isdirectory) 
        ? f.mkdir() : f.createNewFile();
    return (created) ? f : null;
  }
 
  /**
   * Crea un nuovo file e restituisce il suo riferimento.
   * 
   * @param path  Indirizzo del file da creare.
   * @return      Il file appena creato.
   * 
   * @throws IOException
   */
  public static File createFile(String path) 
      throws IOException{
    File f = new File(path);
    if(f.exists())
      f.delete();

    if(!f.createNewFile()) 
      throw new IOException("Non è stato possibile creare il file '" 
          + path + "'");
  
    return f;
  }
 
  /**
   * Crea un nuovo file solo se non esiste 
   * già all'indirizzo indicato.
   * 
   * @param path        Indirizzo del file.
   * @param isdirectory Indica se si tratta di una directory.
   * @return            Il file esistente o creato;
   *
   * @throws IOException  Se non è possibile operare sul file system.
   */
  public static File createFileIfNotExists
       (String path, boolean isdirectory) throws IOException{
    File f = new File(path);
    if(!f.exists()){
      boolean created = (isdirectory) 
          ? f.mkdir() : f.createNewFile();
      return (created) ? f : null;
    }
    return f;
  } 
 
  /**
   * Utilizza il template dei menu 
   * per creare il menù del Lunedì.
   * 
   * TEMPLATE:
   *  PRIMI:
   *      *PASTA1*
   *      *RISOTTO1*
   *      *MINESTRA1*
   *
   *  SECONDI:
   *      *CARNE1*
   *      *CARNE2*
   *      *PESCE1*
   *      
   *  CONTORNI:
   *      *VERDURE1*
   *      *VERDURE2*
   *      
   *  DOLCI:
   *      *DOLCI1*
   *      *DOLCI2*
   * 
   * @param args
   * @throws IOException
   */
  public static void main(String[] args) throws IOException{
    //Path del file di template in input
    String menu_path = "C://temp//menu_template.txt";
  
    //Path del file che verrà creato per il menù del Lunedì
    String lunedi_path = "C://temp//menu_Lunedi.txt";
  
    //Path del file che verrà creato per tracciare 
    //l'andamento delle operazioni svolte.
    String logs_path = "C://temp//menu_logs.txt";
  
    //Inizio creazione dei los applicativi
    String logs = "Inizio attività.";
  
    //Referenzio il template dei menù.
    File f = createFileIfNotExists(menu_path, false);
  
    //Traccio nel log il contenuto originale 
    //del file di template
    logs += "\nAperto Template dei Menù: " + menu_path;
    logs += FileFactory.getFileContent(f);
  
    //Preparo il menù del Lunedì: 
    //ogni coppia chiave/valore rappresenta 
    //il token da sostituire/il nuovo contenuto.
    Hashtable<String, String> menuLunedi = 
        new Hashtable<String, String>();
    menuLunedi.put("*PASTA1*", "Spaghetti all'amatriciana");
    menuLunedi.put("*RISOTTO1*", "Risotto ai funghi porcini");
    menuLunedi.put("*MINESTRA1*", "Minestrone di stagione");
    menuLunedi.put("*CARNE1*", "Carne di cavallo ai ferri");
    menuLunedi.put("*CARNE2*", "Fesa di vitello");
    menuLunedi.put("*PESCE1*", "Trota al cartoccio");
    menuLunedi.put("*VERDURE1*", "Insalata mista");
    menuLunedi.put("*VERDURE2*", "Patatine fritte");
    menuLunedi.put("*DOLCI1*", "Tiramisù");
    menuLunedi.put("*DOLCI2*", "Torta Margherita");
  
    logs += "\nCaricato il dizionario dei token "
          + "da sostituire il Lunedì.";
  
    //Creo il file con il menù del Lunedì 
    //sostituendo all'interno del template 
    //tutte le ricorrenze delle chiavi di 
    //<code>menuLunedi</code> 
    //con il relativo valore.
    setFileContent(
        createFileIfNotExists(lunedi_path, false)
        ,FileFactory.getSubstitutedFileContent(f,menuLunedi));

    //Traccio la corretta esecuzione della generazione 
    //del menù del Lunedì.
    logs += "\nSostituzione eseguita."
        + "\nMenù del Lunedì creato: " + lunedi_path;
  logs += "\nAttività terminata correttamente";
  
    //Scrivo il file di logs.
    setFileContent(
        createFileIfNotExists(logs_path, false), logs);
  }
}

Come detto in precedenza, la classe FileFactory permette di fare molte cose, agendo sulle risorse in maniera semplice, intuitiva ed efficace.

E' stata compilata con successo per l'ambiente Java 5 e non fa uso di alcun metodo od oggetto deprecato.

Conclusioni

Come mostrato nell'esempio, con poche righe di codice si creano 2 nuovi files, se ne legge uno e si provvede a sostituirne alcune parti di testo per salvare il tutto in un altro file: mica male :).

Tra l'altro, il codice sorgente è di facile comprensione e ben documentato cosa che rende la classe facilmente implementabile per acquisire nuove funzionalità.

Alla prossima,
MA.

venerdì 9 luglio 2010

BlackBerry: APP ERROR 200/205/403

In questo breve articolo esporrò i pochi punti da seguire per poter riabilitare un BlackBerry device in caso si avesse a che fare con gli errori 200, 205 e 403.

Tali errori si manifestano al momento del reboot e vengono segnalati da un messaggio molto simile a questo: APP ERROR 200 .

Queste serie di errori applicativi si verificano perchè qualche modulo di programma, o dell'OS, si corrompe e quindi al successivo riavvio provoca il blocco totale del device.

Cattivi Eventi

A me è successo che il mio BlackBerry BOLD2 9700 si bloccasse durante l'eliminazione di un evento dal calendario e dopo aver effettuato il pull battery non si è più riavviato!

Dopo un attimo di panico iniziale, mi è venuto in mente che anche un mio amico aveva avuto lo stesso problema e che era riuscito a risolverlo grazie ad una procedura trovata in qualche angolo della rete.

Con un po' di fortuna, ho trovato una ottima procedura per riconfigurare il BB: la ho seguita io stesso e dopo un primo fallimento, dovuto comunque ad una mia disattenzione, il device è ripartito perfettamente.

Il necessario

Sostanzialmente si tratta di formattare e re-installare l'OS e tutte le applicazioni di cui si ha bisogno.

Ciò che serve a tale scopo sono una versione aggiornata del BlackBerry Desktop Manager, il cavetto USB per collegare il device al PC ed il proprio BlackBerry.

Di seguito elenco i passi da seguire fedelmente per riconfigurare il BlackBerry a seguito dell'errore APP ERROR 200.
Raccomando di seguirli attentamente: io l'ho fatto ed in 40 minuti il mio BOLD2 9700 era di nuovo funzionante! :)

Steps Procedurali

  1. Sganciare la batteria dal BlackBerry e tenerla a portata di mano;
  2. Avviare il software BlackBerry Desktop Manager;
  3. Cliccare su Application Loader, o Caricatore di Applicazioni, a seconda della lingua scelta all'installazione;
  4. Scegliere Update Software, o Aggiorna Software;
  5. Connettere il BlackBerry al pc, sempre senza batterie;
  6. Se richiesto inserire rapidamente il PIN del device e premere OK;
  7. Se il Desktop Manager propone più di un sistema operativo, scegliere quello etichettato come Preferred, o Preferito, e se si conosce ciò che ha causato il blocco del device rimuoverlo dalla lista delle applicazioni;
  8. Procedere con l'aggiornamento del software, sempre senza utilizzare la batteria del BlackBerry;
  9. Al momento del reboot, per l'inizializzazione del dispositivo, il led del BlackBerry si accenderà diventando rosso: inserire ora la batteria;
  10. Lasciare terminare l'update;

Questa procedura è realmente risolutiva, infatti il primo tentativo di rianimare il mio device non andò a buon fine proprio perchè sbagliai il momento in cui inserire la batteria.

Rifatto attentamene, al secondo tentativo, tutto si è concluso in maniera eccelsa e il mio BOLD2 9700 è ritornato online.


Alla prossima,
MA

domenica 4 luglio 2010

PHP: Classe per creare Logs Applicativi

In questo articolo PHP esporrò il codice sorgente della classe MaLogger: componente software utile per gestire facilmente la creazione di logs applicativi differenziati a seconda che l'ambiente di runtime sia di produzione o test.

Contesto

Abituato a lavorare in Java, ogni qual volta cambio ambito lavorativo risento di alcune mancanze che inevitabilmente esistono.

In particolare, quando sviluppo codice Java sono abituato a tracciare molte delle operazioni che eseguo con la mitica utility per log Log4J.

Log4J - In breve

Log4J è un prodotto open source della Apache Software Foundation che offre la possibilità di loggare la propria web application non solo in locale, durante la fase di sviluppo, ma anche sul server remoto permettendoci di controllare eventuali bachi e/o problemi di compatibilità derivanti da una differente configurazione del server remoto rispetto alla nostra piattaforma di sviluppo.

Premesse

Ciò che sto per descrivere in questo articolo non è assolutamente il porting di Log4J in ambito PHP, piuttosto si tratta di una semplice classe che permette di eseguire il debug di una PHP Web Application sul server, locale o remoto, in cui sta girando.

Ciò di cui normalmente ho bisogno durante lo sviluppo di una web application
si può riassumere in questi pochi punti:

  • Differenziare i log generati da PHP sul file error.log dai miei;
  • Poter creare file di log diversi per ogni componente della mia applicazione;
  • Gestire a runtime il flusso dei log per controllare gli esiti in modo organico ed ordinato;
  • Eventualmente svuotare i file di log;
  • Interrompere il debug applicativo in maniera centralizzata;

La classe MaLogger

Dunque, per soddisfare le mie esigenze, come al solito, ho messo mano alla mia creatività e ho sviluppato la classe MaLogger.

La classe è abbastanza semplice, molto funzionale e assolutamente stabile: è infatti parecchio tempo che la uso sul server in cui gira il mio sito per poi controllare che il flusso applicativo sia corretto e che i dati in request non abbiano subito dei trattamenti involontari che avrebbero potuto cambiarne la forma e/o la rappresentazione(encoding/decoding in charset non corretti o utilizzo non voluto di entità HTML) o che qualche risorsa di cui faccio uso non sia stata temporaneamente raggiungibile.

La classe è stata pensata sia per un utilizzo smart, ossia per tener traccia di qualche dato o risultato in modo rapido e snello, sia per eseguire un dump di tutte le informazioni utili nell'intero flow della web application.

Qui di seguito il codice sorgente della classe:

class MaLogger{
  private static $DEFAULT_LOG_FILE_NAME = "MaLog.log";
  const OPEN_LOG_FILE_FOR_WRITE = "a";
  const CREATE_NEW_LOG_FILE_FOR_WRITE = "w";
  public static  $DEBUG_ACTIVATED = true;
 
  private $handle = false;
 
  /**
   * Crea un'istanza della classe.
   * 
   * @param $mode     Modalità di creazione del file di log.
   * @param $filename Nome da attribuire al file di log.
   *                  Il parametro è comprensivo di path.
   *                  Se $filename è null verrà utilizzato 
   *                  $DEFAULT_LOG_FILE_NAME.
   */
  public function __construct($mode, $filename = null){
    $fileName = ($filename == null || !isset($filename)) 
                  ? MaLogger::$DEFAULT_LOG_FILE_NAME : $filename;
      
    if($mode != MaLogger::OPEN_LOG_FILE_FOR_WRITE 
          && $mode != MaLogger::CREATE_NEW_LOG_FILE_FOR_WRITE)
      throw new Exception(
        '[MaLogger]:Modalità di apertura file di log inesistente[' 
        . $mode . '].', $fileName);
  
    //Creo il file
    $this->handle = fopen($fileName, $mode);
      
    if($this->handle == null || !$this->handle)
      throw new Exception(
        'Impossibile creare o aprire il File di Log', $fileName);
  }
 
  /**
   * Scrive sul file di Log.
   *
   * @param String $text  Le informazioni da scrivere;
   * @return int          Il numero di byte scritti;
   */
  public function append($text){
    return (MaLogger::$DEBUG_ACTIVATED) 
            ? fwrite($this->handle,$text . "\n") : 0;
  }
 
  /**
   * Chiudo il file di Log
   *
   * @return boolean  true se il file viene chiuso 
   *                  correttamente altrimenti false;
   */
  public function closeLogFile(){
    return fclose($this->handle);
  }
 
  /**
   * Crea un'istanza della classe MaLogger.
   *
   * @param String $mode      Modalità di apertura del file.
   * @param String $filename  Nome opzionale del file di log.
   * @return MaLogger          Istanza di classe.
   */
  private static function initLogFile($mode,$filename=null){
    return new MaLogger($mode,$filename);
  }
 
  /**
   * Modalità smart.
   * Crea un file di log, ci scrive le informazioni
   * e chiude la connessione.
   * 
   * @param  $text      Informazioni da tracciare. 
   * @param  $mode      Modalità di apertura del file di log
   * @param  $filename  Nome del file di log(OPZIONALE).
   */
  public static function logThis($text,$mode,$filename=null){
    if(MaLogger::$DEBUG_ACTIVATED){
      $log = MaLogger::initLogFile($mode,$filename=null);
      $log->append($text);
      $log->closeLogFile();
    }
  }
}

Come preannunciato la classe non è complicata, ma invece è intuitivamente facile da utilizzare e ben commentata. Di seguito alcuni esempi.

Utilizzi della classe MaLogger

Dunque, esposto il codice sorgente della mia utility class, passiamo a vederla in azione con un esempio.

Come spunto creeremo delle istanze della classe MaObject: una classe banale creata apposta per l'esempio che possiede due proprietà pubbliche.
Mostrerò le due modalità di utilizzo della classe MaLogger: utilizzerò una istanza per tracciare tutto il flusso dello script (modalità tradizionale) ed invece attraverso il metodo statico e pubblico logThis($text,$mode,$filename=null) traccerò le informazioni in maniera smart.

Qui il codice dello script di test:

<?php
include './MaLogger.php';

class MaObject{
  public $initialized = false;
  public $value = '';
  
  public function __construct($value = ''){
    $this->value = $value;
    $this->initialized = true;
  }
}

try{
  //Creo un'istanza per appendere informazioni.
  //scrivo su MaLogger:$DEFAULT_LOG_FILE_NAME
  $log = new MaLogger(MaLogger:OPEN_LOG_FILE_FOR_WRITE);
  $log->append('File di debug creato.\nInizio test.\n');

  //Utilizzo di MaLogger in modalità smart.
  //Scriverò su un nuovo file per tracciare i dati
  //su file separati.
  $obj1 = new MaObject('Primo oggetto MaObject.');
  MaLogger::logThis('Stato di obj1: ' . $obj1->initialized 
          ,MaLogger::OPEN_LOG_FILE_FOR_WRITE,'./MaObject1.log');
  $obj2 = new MaObject('Secondo oggetto MaObject.');
  MaLogger::logThis('Stato di obj2: ' . $obj2->initialized 
          ,MaLogger::OPEN_LOG_FILE_FOR_WRITE,'./MaObject2.log');

  //Comunque tengo traccia di tutto il flusso dei dati
  //continuando ad utilizzare $log in modalità tradizionale
  $log->append('obj1 creato. Value = ' . $obj1->value . ';');
  $log->append('obj2 creato. Value = ' . $obj2->value . ';');
  $log->append('Esecuzione script terminata.');
  echo '<p>Hello people ;)</p>';
}
catch(Exception $e){
  die('Esecuzione interrotta. Si è verificata un'eccezione.'
      . '\nMessaggio:\n$e');
}
?>

Conclusioni

OK, tutto quello di cui sentivo di aver bisogno durante le sessioni di sviluppo PHP adesso non mi manca più: la classe MaLogger ha colmato le lacune!!!

In realtà l'esempio non mostra come interrompere il debug delle informazioni come invece nelle premesse avevo affermato: lo spiego ora a parte.

Quando avrete debuggato la vostra applicazione e vi sentirete ormai sicuri è consigliabile disabilitare il debug per migliorare le prestazioni del sistema evitando di esagerare nell'attività di I/O su file system.

Per disabilitare il debug dell'applicazione in maniera centralizzata è sufficiente negare, o rendere falsa, la proprietà $DEBUG_ACTIVATED

public static $DEBUG_ACTIVATED = false;

Alla prossima, MA.

sabato 3 luglio 2010

Condividere fonti con AddThis Share plug-in

In questo articolo parlerò del plug-in AddThis, che io stesso utilizzo in questo blog, grazie al quale i miei visitatori possono facilmente condividere i miei articoli con i loro contatti.

Cos'é AddThis?

Si tratta di un componente software, gratuitamente offerto da www.AddThis.com, che permette di aggiungere al DOM di un documento HTML una pulsantiera per consentire ai propri utenti di scegliere comodamente il miglior canale sul quale condividere ciò che stanno leggendo.

Direttamente a quell'indirizzo è possibile in 4 semplici passi creare la propria share bar: basta infatti selezionare il tipo di CMS(Content Management System) utilizzato per il proprio sito, scegliere il layout che il componente dovrà avere, indicare se si desidera monitorare i click ed infine richiedere il codice HTML da inserire nel proprio blog o sito.

In funzione del modello scelto è possibile modificare il codice HTML personalizzandolo e adattandolo al layout del proprio spazio WEB.

Per esempio, per il modello che ho scelto io, è possibile aggiungere e rimuovere i pulsanti sempre visibili, cambiandone l'ordine ed il numero a proprio piacimento.

Perchè AddThis?

Ho scelto AddThis perchè lo utilizzo anche su un altro spazio WEB e quindi ho avuto modo di conoscere ed apprezzare il servizio.

Il primo motivo per cui ho scelto di utilizzarlo anche su questo blog é dovuto al fatto che circa 3 anni fa ho inserito AddThis in un altro sito e ad oggi non mi è mai capitato di accorgermi di un'eventuale caduta del servizio: quindi per l'affidabilità.

Sebbene utilizzando blogger abbia di default la possibilità di aggiungere una pulsantiera per la condivisione dei miei articoli, ho preferito adottare AddThis proprio per la vasta scelta dei social network e per la completa personalizzazione del layout.

Caso d'uso

Qui di seguito riporto il codice HTML della mia pulsantiera AddThis per mostrare quanto è semplice introdurre nel layout di un sito questo formidabile componente.
<div class="addthis_toolbox addthis_default_style"
    style="float: right;margin-top: 0;font-size: 9pt;
          font-weight:  normal;padding:0;">
<a href="http://www.addthis.com/bookmark.php?v=250&pub=xa-4a4b"
    class="addthis_button_compact">Share</a>
<span class="addthis_separator"> | </span>
<a class="addthis_button_facebook"></a>
<a class="addthis_button_myspace"></a>
<a class="addthis_button_google"></a>
<a class="addthis_button_twitter"></a>
</div>
<script type="text/javascript" 
    src="http://s7.addthis.com/js/250/addthis_widget.js?pub=xa-4a4b"
></script>

Come è facile intuire, basta modificare il valore dell'attributo class di ogni link HTML per modificarne l'immagine ed il target.

Alla prossima,
MA