7. Buone abitudini: indentare il codice

Andrea Pastore 19/03/2020 0

L’indentazione del codice consiste nell’inserire alcuni spazi all’inizio di una riga, ed è usata per aiutare a capire la struttura del codice scritto. Se ad esempio dobbiamo scrivere un if, per indicare il codice da eseguire se la condizione è verificata è buona norma indentare questo codice. Facciamo un esempio, prendiamo questo codice non indentato:

Tutti i caratteri sono scritti uno sotto l’altro e il codice risulta più difficile da leggere. Questo è un codice di poche righe, ma cosa succederebbe se fosse più corposo? Ci costringerebbe a perdere più tempo a capire cosa fa. Vediamo ora un codice ordinato:

Basta una rapida occhiata per capire il codice dove si trova e cosa fa.

 

Le regole dell’indentazione

Dobbiamo indentare il codice delle strutture di controllo (if, switch, for e altri), dei metodi e infine delle classi.

Potrebbero interessarti anche...

Andrea Pastore 19/03/2020

18. Programmazione concorrente

Prima di introdurre questo agomento dobbiamo capire come funzionano i moderni processori: vediamo la foto di un’architettura di un processore intel:

Vediamo che è composto da varie parti: i core (le unità che di elaborazione, il codice che scriviamo viene elaborato da loro) una piccola memoria interna (da non confondersi con la memoria RAM, che non risiede nel processore) e poi una scheda video. Il numero di processi che può essere eseguito contemporaneamente dipende dal numero di core, quindi il processore mostrato in figura può eseguire quattro processi contemporaneamente. Il sistema operativo ha il compito di assegnare le risorse ad un processo: tra le altre cose deve decidere a quale processore assegnare il processo, controllare che non si blocchi, aggiornare la coda dei processi in attesa di essere eseguiti e molto altro ancora. Un processo resta in esecuzione per una frazione di secondo, poi se ha esaurito il compito viene terminato, altrimenti viene reinserito nella coda dei processi che in attesa di essere eseguiti.

I programmi moderni, a meno che non siano programmi molto piccoli sono composti da tanti processi in esecuzione sul proprio computer, ognuno con un compito. Un esempio è rappresentato dai browser web, come Firefox: l’architettura di questo browser prevede attualmente che ci sia un processo deputato a mostrare l’interfaccia (che mostra ad esempio le tab aperte) e altri processi che gestiscono le tab.

 

Lo scheduler del sistema operativo

Per stabilire quale processo debba essere eseguito ogni sistema operativo dispone di un software chiamato scheduler, che gestisce la coda dei processi tenendo conto di una serie di fattori: priorità, stato del processo e molti altri. Se il sistema operativo è progettato per gestire hardware in grado di gestire più thread contemporaneamente (ovvero tutti gli strumenti che utilizziamo maggiormente oggi: computer, telefonini, ma anche centraline di oggetti di uso comune come l’automobile) il suo ruolo si complica perché deve tenere conto anche degli altri thread. Ad esempio un thread di un processo potrebbe dover aspettare che un altro thread termini l’esecuzione.

 

La programmazione concorrente in Java

Java mette a disposizione due modi per creare processi concorrenti: la prima possibilità consiste nella creazione di una classe che estende la classe Thread, la seconda consiste nella creazione di una classe che implementa l’interfaccia Runnable. Le differenze dal punto di vista del codice sono minime, creiamo due classe Trhead_A e Trhead_B per vederle:

 

Classe che estende la classe Thread

public class Thread_A extends Thread {

private int contatore;



public Thread_A() {

this.contatore = 0;

}



public void run() {

this.contatore ++;

System.out.println("Trhead A: contatore= "+contatore);

}

}

 

Classe che implementa l’interfaccia Runnable

public class Thread_B implements Runnable{

private int contatore;

public Thread_B() {

this.contatore = 0;

}

@Override

public void run() {

this.contatore++;

System.out.println("Thread B: contatore="+contatore);

}

}

Notiamo che entrambe le classi hanno un metodo public void run(). Questo è un metodo necessario in quanto descrive le operazioni che deve fare il Thread. Nei nostri esempi qui sopra i thread incrementano un contatore e lo stampano.

 

Lanciare un Thread

A seconda del metodo che abbiamo scelto, i Thread si lanciano in due modi diversi. Se abbiamo scelto di creare le classi che estendono la classe Thread, come nel nostro esempio del Trhead_A, scriveremo:

Thread_A t  = new Thread_A();

t.start();

Se usiamo una classe che estende l’interfaccia Runnable creeremo prima un’istanza di quella classe, e un Trhead a partire da quella:

	Thread_B rc = new Thread_B();

Thread t1 = new Thread(rc);

t1.start();

Nota: in entrambi i casi per far partire un thread bisogna invocare il metodo start().

 

Assegnare la priorità ad un thread

È possibile impostare la priorità di un thread con il metodo setPriority. Java prevede per la priorità un valore da 1 a 10, se non lo impostiamo manualmente la priorità assegnata di default è 5. La classe Trhead dispone di tre costanti che sono:

MAX_PRIORITY = 10

MIN_PRIORITY = 1

MEDIUM_PRIORITY  = 5

Se ad esempio voglio impostare la priorità massima scriverò:

	t.setPriority(Thread.MAX_PRIORITY);

Per impostare altri valori sulla scala da 1 a 10 possiamo usare i numeri.

 

Mettere in pausa un thread

Può capitare di dover fermare un thread per un certo intervallo di tempo (ad esempio perché deve ripetere una determinata operazione dopo un tempo prestabilito), per questo Java mette a disposizione diversi metodi. Sleep, join e yeld.

 

sleep

prende in input il numero di millisecondi durante i quali il thread deve stare in pausa. Per invocarlo correttamente bisogna utilizzare il costrutto try .. catch, perché dobbiamo prevenire il fatto che un altro thread provi a chiamare il thread dove abbiamo invocato il metodo sleep:

	try {       	  		   

t1.sleep(10);

     } catch (InterruptedException ex) {

       // handle the error

       System.out.println("si è verificata un'eccezione");

     }

 

join

questo metodo serve a mettere in attesa il thread su cui è invocato fino a quando altri trhead al suo interno non abbiano terminato l’esecuzione. Supponiamo di avere un thread t1 che crea un thread t2 per eseguire un’operazione. L’istruzione:

	t2.sleep(10);

metterà in attesa il thread t1 fino a quando t2 non avrà terminato la sua esecuzione.

 

yeld

È un metodo statico che suggerisce allo scheduler di mettere in pausa il tread corrente per lasciare spazio ad altri. Viene invocato in questo modo:

	Thread.yield();
Leggi tutto

Andrea Pastore 19/03/2020

4. La notazione CamelCase

Quando scriviamo un programma e dobbiamo assegnare i nomi alle varie entità (variabili, classi, package ecc) non possiamo usare spazi, ad esempio non scriveremo

int numero oggetti;

ma scriveremo

int numeroOggetti;

la lettera iniziale della parola oggetti è scritta in maiuscolo, per una pratica nata negli anni 70 definita notazione CamelCase. Per facilitare la lettura del codice, i programmatori cominciarono a scrivere le inizali di ogni parola successiva alla prima in maiuscolo, ed è una pratica caldamente consigliata ancora oggi.

 

Leggi tutto

Andrea Pastore 19/03/2020

1. Le origini di Java e le sue caratteristiche

Java è un linguaggio di programmazione ad oggetti tra i più comuni al mondo, utilizzato praticamente in tutti i tipi di dispositivi, dai computer ai telefoni, distributori automatici e molto altro. Fu creato da Sun Microsystem nel 1995 ed è poi passato ad Oracle quando quest’ultima ha acquisito Sun.

 

La macchina virtuale Java

Una caratteristica di Java è quella di girare su tutti i sistemi operativi, senza che il codice venga ricompilato come avviene in altri linguaggi. Questa possibilità ci è data dalla Java Virtual Machine, che si occupa di leggere il codice Java tradurlo nel linguaggio macchina del dispositivo dove si trova.

 

Organizzazione del codice

Il codice Java è organizzato in classi, che sono contenute in package.  Per ora ci basti sapere che una classe è un file contenente codice Java, può richiamare altre classi per fare compiti specifici. Le classi a loro volta sono suddivise in metodi, che possono essere richiamati dalla stessa classe o da altre classi.

Un programma java può avere un numero variabile di classi che può essere anche molto elevato (si pensi per esempio a programmi come Eclipse). Un programma Java deve avere sempre una classe che viene chiamata quando il programma va in esecuzione. Questa classe è chiamata classe main, capiremo più avanti questo concetto.

Un package è una cartella che contiene le classi Java.  I progetti java possono essere molto vasti, quindi è necessario ordinare le classi in modo da essere consultabili. Ad esempio supponiamo di avere un programma di una biblioteca, un package potrebbe contenere tutte le classi Java deputate al salvataggio dei dati e un altro potrebbe contenere tutte le classi deputate alla gestione dell’interfaccia grafica.

 

Commenti

I commenti sono delle stringhe di testo che vegono utilizzate per spiegare il codice che si sta scrivendo. Quando scriviamo un programma non è detto che lo utilizzeremo solo noi, può darsi che quel codice vada in mano ad un collega. È bene quindi commentarlo per far capire a chi legge il codice (anche a noi stessi, se lo rileggiamo dopo un po’ di tempo!) cosa abbiamo fatto.I commenti in java si fanno in due modi:

 

// commento su singola riga

/*

 * commento su più righe

 * lo utilizziamo quando dobbiamo spiegare qualcosa di più elaborato

 */
Leggi tutto

Cerca...