Visualizzazione post con etichetta programmazione orientata agli oggetti. Mostra tutti i post
Visualizzazione post con etichetta programmazione orientata agli oggetti. Mostra tutti i post

venerdì 15 giugno 2012

Java ecologico: le variabili d'ambiente e il CLASSPATH


Quando si parla di compilazione di codice Java sicuramente vi sarà capitato di sentir parlare di variabili d'ambiente e CLASSPATH. Il classpath si riferisce al percorso sul tuo file system dove i tuo file .class sono salvati. Il classpath è definito dalla variabile d'ambiente CLASSPATH. Il CLASSPATH specifica le directory e i file JAR dove il compilatore e la JVM troveranno il bytecode. Attraverso l'utilizzo del CLASSPATH si permette di memorizzare il bytecode in directory a nostra scelta o in archivi Java (JAR File).

Rendi ecologico il tuo pc con le variabili d'ambiente..


Per esempio supponiamo di avere la classe com.bustapaga.Impiegato. Il compilatore e la JVM cercheranno la directory \com\bustapaga basandosi sulla variabile d'ambiente CLASSPATH. Quindi se per esempio il file Impiegato.class si trova nella directory

c:\Documents and Settings\Alex\workspaces\build\com\bustapaga

allora la variabile CLASSPATH deve includere la directory

c:\Documents and Settings\Alex\workspaces\build

La variabile CLASSPATH può contenere un qualsiasi numero di directory e file JAR.

Ma come settare questa variabile d'ambiente? Dipende ovviamente dal sistema operativo.

Sotto un sistema Windows: aprire il prompt dei comandi e settare la variabile classpath con questa istruzione (separando i multi valori con il punto e virgola)

set CLASSPATH=”c:\Documents and Settings\Alex\workspaces\build”;
c:\myproject\build;c:\tomcat\lib\servlet.jar;.;

Sotto un sitema Unix: usare il comando setenv per separare valori multipli

setenv CLASSPATH /usr/build:/myproject/build:/tomcat/lib/servlet.jar

Attenzione! Un errore comune da evitare è quello di includere parte del nome del percorso del package nella variabile CLASSPATH. Da evitare ad esempio un errore simile:

set CLASSPATH=c:\myproject\build\com\bustapaga;

mercoledì 13 giugno 2012

Che tipi! Primitive Types vs. Reference Types


Le applicazioni Java prevedono due tipi di dati: primitivi e referenziati. I tipi primitivi sono i classici tipi di dati che si imparano sin dalle prime lezioni di programmazione e sono riassunti nella tabella qui sotto.



La tabella mostra anche i diversi range di valori permessi per ogni tipo. Difficile ricordare ogni singolo range mentre può essere molto utile ricordare la dimensione in bits prevista per ogni tipo.

Un Reference type invece, sono variabili che sono tipi di classe, tipi di interfacce o tipi di array. Una "reference" fa riferimento a un oggeto (un istanza di una classe). A differenza dei tipi primitivi che mantengono i loro valori im memoria dove la variabile è allocata, le referenze non mantengono il valore dell'oggetto a cui si riferiscono. Una referenza "punta" ad un oggetto memorizzando l'indirizzo dove l'oggetto è collocato. Tutto questo può essere ricondotto al conetto di "puntatore". Tuttavia Java non permette al programmatore di accedere direttamente ad un indirizzo fisico di memoria. Quindi anche se le referenze sono simili ai puntatori, è possibile solo usare una referenza per accedere ad un campo o un metodo dell'oggetto a cui fa riferimento. Risulta impossibile quindi determinare il reale indirizzo di memoria della variabile referenziata.
Vediamo un esempio ora. Dichiariamo due referenze:

java.util.Date today;
String greeting;

La variabile today è una refernza di tipo Date e può puntare solo a un oggetto di tipo Date. La variabile greeting invece è una referenza che può puntare solo ad un oggetto di tipo String. Un valore può essere assegnato ad una referenza in due modi:
- Una referenza può essere assegnata ad una referenza dello stesso tipo
- Una referenza può essere assegnata ad un nuovo oggetto usando la parola chiave "new"

Ad esempio assegnamo le due precedenti referenze a due nuovi oggetti:

today = new java.util.Date();
greeting = “How are you?”;

Ecco come queste due referenze sono rappresentate in memoria:

lunedì 9 aprile 2012

Riflettiamo con la Java Reflection

L'idea di questo post nasce da un test preselezione che ho fatto per un'azienda inglese. Dato un pezzo di codice veniva chiesto quale caratteristica del linguaggio Java era utilizzata. Si trattava della reflection.

La reflection è quella caratteristica del linguaggio Java che permette ad un programma  in esecuzione di accedere a proprietà interne del programma stesso. Tutto ciò ovviamente in contro tendenza con il paradigma orientato agli oggetti. Ad esempio con questa caratteristica è possibile per un classe Java ottenere e accedere al nome di tutti i suoi metodi e attributi ed eventualmente mostrarli.

Perché la reflection?

La violazione del principio di incapsulamento dei linguaggi object oriented può essere pericoloso ma se trattato con le giuste accortezze diventa uno strumento potentissimo. In particolare può essere utile nei framework e in casi in cui si necessità di un forte riutilizzo di codice. Consideriamo ora un esempio di codice Java (fonte sito ufficiale della Oracle):


   import java.lang.reflect.*;
 
   public class DumpMethods {
      public static void main(String args[])
      {
         try {
            Class c = Class.forName(args[0]);
            Method m[] = c.getDeclaredMethods();
            for (int i = 0; i < m.length; i++)
            System.out.println(m[i].toString());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }


Per usare la reflection occore effettuare l'import del package java.lang.reflect.Ora richiamando la classe DumpMethods e passando come input la stringa "java.util.Stack" l'output che otteniamo è il seguente:


 public java.lang.Object java.util.Stack.push(
    java.lang.Object)
   public synchronized 
     java.lang.Object java.util.Stack.pop()
   public synchronized
      java.lang.Object java.util.Stack.peek()
   public boolean java.util.Stack.empty()
   public synchronized 
     int java.util.Stack.search(java.lang.Object)



otteniamo quindi l'elenco dei metodi della classe Stack compreso di parametri e il tipo restituito da ogni metodo.

Un ottimo esempio di come sia utile la reflection è nella conversioni di documenti XML in oggetti Java (più facilmente manipolabili all'interno di un applicazione scritta in linguaggio Java). Trovate un ottimo esempio di codice qui.

Infine per una illustrazione completa dei diversi usi della reflection date anche un'occhiata qui.

giovedì 26 gennaio 2012

Perché le interfacce?

Molti si saranno chiesti a cosa servono e se sono realmente utili le interfacce software. Cercheremo di spiegarlo brevemente in questo post.

Un'interfaccia altro non è che una porzione di software che permette di interagire con le risorse hardware (memoria, CPU e cosi via) che si trovano ai livelli sottostanti. L'accesso a queste risorse se lasciato libero e indiscriminato può portare a diversi incovenienti. Per questo si può permettere l'accesso a tali risorse solo attraverso precisi entry point, ad esempio le interfacce.

Ma cosa è un'interfaccia nel campo della programmazione ad oggetti? Altro non è che una classe che non contiene dati, quindi di tipo astratto, e può contenere quindi solo metodi d'istanza astratti ( non può contenere né costruttori, né variabili di istanza, né metodi statici ecc.). Tuttavia una classe può implementare più interfacce. Una volta che una classe implementa un'interfaccia, il compilatore sà che un'istanza della classe conterrà lo specifico insieme di metodi. Per spiegare meglio cosa sia un'interfaccia usiamo un'analogia: un interfaccia seriale su un computer definisce un insieme di pin assegnati e il controlo dei segnali che saranno usati; il dispositivo può essere usato per differenti task: mouse, modem, ecc. e questi saranno tutti controllati attraverso lo stesso meccanismo di istruzioni digitali. Per cosa può essere utile un'interfaccia? Se una classe ha bisogno di due differenti insiemi di metodi cosi che il suo comportamente sia  quello di due cose differenti, può ereditare un insieme dalla classe A e usare un'interfaccia B per specificare l'altro!

mercoledì 16 novembre 2011

Interview question: SOLID

Questo è il primo di una lunga serie di post dove parleremo di possibili domande a cui un informatico potrebbe andare incontro.

  • Cos'è SOLID?
SOLID sta per Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion. Il termine è stato introdotto per la prima volta da Robert C. Martin agli inizi dell'anno 2000 per indicare un nuovo principio di programmazione e design object-oriented. Quando è applicato il principio permette di avere un sistema facile da manutenere e da estendere col tempo. Andiamo ad analizzare ogni singolo concetto di questo nuovo principio.

  • Single responsibility principle (SRP)
Ogni oggetto dovrebbe avere un sola singola responsabilità. In pratica ogni classe dovrebbe concentrarsi sul fare una sola cosa.

  • Open/closed principle (OCP)
Le entità software dovrebbero essere aperte per l'estensioni ma chiuse per le modifiche. Supponiamo di avere la classe OrderValidation con il metodo Validate (Order order) che contiene tutte le regole per validare un'ordine. Se tali regole cambiano siamo costretti a modificare la classe violando il principio OCP. Se avessimo invece l'oggetto IValidationRule contenente tutte le regole, allora potremmo basare il metodo Validate su questo oggetto e nel caso di cambio di regole basterà creare un nuovo IValidationRule e passarlo all'istanza di OrderValidation al run time.

  • Liskov substitution principle (LSP)
Gli oggetti in un programma dovrebbe essere rimpiazzati con instanze del loro sottotipo senza alterare la correttezza del programma. In pratica le sottoclassi dovrebbero comportarsi correttamente quando usate al posto delle loro classi base.


  • Interface segregation principle (ISP)
Diverse interfacce client specifiche sono meglio di una interfaccia con scopo generale. In pratica mantenere le interfacce piccole e coese.



  • Dependency inversion principle (DIP)
Dipendere dall'astrazione, non dipendere dalle concrezioni. Il metodo di Dependency injection è un modo per seguire questo principio. Tale metodo è un design pattern per la programmazione orientata agli oggetti per cui una classe o un sistema non è responsabile circa l'inizializzazione delle proprie dipendenze. Per maggiore informazioni dare un'occhiata su questo blog.



Per maggiori approfondimenti consultare il seguente link.