Javafx 1.2

All'inizio di giugno é uscita la nuova versione di javaFX, la 1.2, che sembra sia un bel passo in avanti rispetto alla precedente 1.1, soprattutto nel mettere a disposizione nuove classi che permettono di gestire più agevolmente le componenti grafiche.

Per maggiori informazioni, vedi il sito ufficiale, javafx.com che, oltre a permettere il download dell'ambiente di sviluppo, mette a disposizione documentazione introduttiva.

In realtà io non ne so ancora abbastanza per commentare il passaggio a 1.2, dato che mi sono appena cominciato a studiare il linguaggio che, per quanto ho visto, mi sembra abbastanza interessante nel suo ambito.

Vedi il blog javafxi.blogspot.com per una introduzione alle feature del linguaggio dal punto di vista di uno sviluppatore con un background in java (la cosa aiuta parecchio, a ben vedere).

Questo é il primo post sul tutorial sun introduttivo alle funzionalità di base di javafx.

E questo é il primo post relativo al tutorial sun introduttivo alla gestione della GUI con javafx.

Desktop profile

Parte finale della prima lezione del corso Oracle a introduzione su come scrivere gui con javaFX.

Per il "desktop", ovvero per gli ambienti che prevedano l'utilizzo di una periferica di output di dimensioni superiori a quelle dei pochi pollici dell'"handy", sono diponibili in ambiente javaFX un altro paio di caratteristiche interessanti: effetti e cursori.

Effetti

Per vedere gli effetti in azione, si scarichi lo script effects.fx.

Dal codice javaFX vediamo che per dare un effetto a un gruppo di oggetti usiamo classi del package javafx.scene.effect e javafx.scene.effect.light semplicemente specificando la proprietà effect dell'oggetto grafico che vogliamo modificare.

L'ombreggiatura applicata ad un elemento grafico gli dà un effetto tridimensionale, come se si librasse, o sprofondasse nel piano su cui é rappresentato.

Si usano due classi per generare una ombreggiatura: DropShadow e InnerShadow

Vediamo ad esempio il primo oggetto ombreggiato definito nello script, un gruppo comprendente un cerchio rosso con due linee che si incrociano al suo interno.

Al gruppo possiamo aggiungere l'effetto ombreggiatura, che possiamo variare in molti modi, ad esempio specificando il suo colore.

Group {
content: [
Circle{centerX: 30 centerY:40 radius:20 fill: Color.RED opacity: 0.8 cursor: Cursor.HAND},
Line {startX: 20 startY: 30 endX: 40 endY: 50 stroke: Color.WHITE strokeWidth: 2},
Line {startX: 20 startY: 50 endX: 40 endY: 30 stroke: Color.WHITE strokeWidth: 2}
]
effect: DropShadow{offsetX:5 offsetY:5 color: Color.BLACKS}
};

E' possibile creare ombreggiature più complesse mescolando diversi oggetti Shadow, usando la classe Blend

L'illuminazione gli dà anch'essa un effetto tridimensionale, ma paragonabile all'agire sull'elemento grafico come per pigiarlo nel piano o farlo saltar fuori.

Per creare l'effetto illuminazione usiamo la classe Lighting specificando il tipo di luce utilizzata nel suo parametro light.

Group {
content:[
Circle{centerX: 30 centerY:20 radius:20 fill: Color.RED opacity: 0.9},
Line {startX: 20 startY: 10 endX: 40 endY: 30 stroke: Color.WHITE strokeWidth: 2},
Line {startX: 20 startY: 30 endX: 40 endY: 10 stroke: Color.WHITE strokeWidth: 2}
]
effect: Lighting {light: DistantLight{azimuth: 90}}
};

E' possibile poi creare un effetto sfocamento usando le classi della famiglia Blur (BoxBlur, GaussianBlur, MotionBlur). Questo esempio mostra un rettangolo riempito con cerchi concentrici bianchi e verde scuro a cui viene applicato l'effetto GaussianBlur:

Rectangle {
x:5 y:25 width: 100 height: 50
fill: RadialGradient {
centerX: 55, centerY: 50, radius: 10, proportional: false
cycleMethod: CycleMethod.REFLECT
stops: [
Stop{offset: 0.3 color: Color.DARKGREEN},
Stop{offset: 1.0 color: Color.WHITE}
]
}
effect: GaussianBlur{radius: 5 }
};

Si può creare un riflesso dell'oggetto grafico, usando la classe Reflection. Nell'esempio lo si applica ad un testo:

Text {
x: 10 y: 42 content: "Reflection"
fill: Color.SEAGREEN
font: Font{size:20 name: "Verdana"}
effect: Reflection { fraction: 0.9 topOpacity: 0.9 topOffset: 0.1}
};

Per cambiare la luminescenza di una immagine si usa la classe Glow, come mostrato qui:

ImageView {
image: Image{url:"http://java.sun.com/docs/books/tutorial/images/penduke.gif"}
effect: Glow{level: 1}
};

Per virare in seppia un immagine usiamo l'effetto SepiaTone:

ImageView {
image: Image{url:"http://java.sun.com/docs/books/tutorial/images/penduke.gif"}
effect: SepiaTone {level: 0.8}
};

Si possono cambiare gli attributi del colore di un oggetto grafico con ColorAdjust:

ImageView {
image: Image{url:"http://java.sun.com/im/logo_sun_small_sdn.gif"}
effect: ColorAdjust{brightness: -0.2}
};

O, infine, trasformarlo mettendolo in prospettiva con PerspectiveTransform:

var transformed = ImageView {
image: Image{url: "http://java.sun.com/docs/books/tutorial/images/penduke.gif"}
effect: PerspectiveTransform {
ulx: 40 uly: 20
urx: 104 ury: 20
lrx: 134 lry: 115
llx: 10 lly: 105
}
}

Cursori

E' possibile specificare che forma abbia il cursore sopra una certa regione della finestra di visualizzazione. Vedi lo script cursor.fx per un esempio.

Il cursore é un attributo di un oggetto grafico, quindi lo settiamo come vediamo in questo esempio:

Group {
content:[
Circle{centerX: 30 centerY:40 radius:20 fill: Color.RED opacity: 0.8 cursor: Cursor.HAND},
Line {startX: 20 startY: 30 endX: 40 endY: 50 stroke: Color.WHITE strokeWidth: 2},
Line {startX: 20 startY: 50 endX: 40 endY: 30 stroke: Color.WHITE strokeWidth: 2}
]
effect: DropShadow{offsetX:5 offsetY:5 color: Color.BLACK}
};

I cursori a disposizione sono indicati nella classe javafx.scene.Cursor, e usati come visto sopra (Cursor.HAND).

Common Profile

Continuamo a vedere la prima lezione del corso Oracle a introduzione su come scrivere gui con javaFX. Attacchiamo ora il Common Profile. Questa lezione m'é stata cambiata sotto i piedi, infatti ci stavo lavorando sopra in questi giorni (inizio giugno 2009) proprio in corrispondenza con il rilascio della versione 1.2 di javaFX, che ha aggiunto molta roba in questo contesto.

Partiamo con gli elementi di GUI, lo script che li fa vedere in opera é UIControls.fx si trova sul sito sun. Si tratta di radio button, textbox, toggle button, check box, slider e progress bar che sono definiti nel package javafx.scene.control.

Poi si passa ai grafici. Il supporto ai quali viene fornito tramite il package javafx.scene.chart e sembra veramente notevole. Si possono costruire facilmente grafici con aree, areaChart.fx, a barre, barChart.fx, a bolle, bubbleChart.fx, a linee, lineChart.fx, a torta, pieChart.fx, o a punti, scatteredChart.fx, insomma, ce n'é per tutti i gusti.

E' estremamente semplice costruire un pannello per la gestione dei colori usando la classe javafx.scene.paint.Color, come illustrato nello script colors.fx.

Per la gestione di forme geometriche si fa riferimento al package javafx.scene.shape, e lo script shapes.fx ce ne da un esempio.

Sono a disposizione alcuni stili di riempimento per le forme geometriche, definiti nel package javafx.scene.paint, e che possiamo vedere all'opera nello script fill.fx.

Sono anche disponibili alcuni stili per la visualizzazione delle linee, definite nel package javafx.scene.shape e visibili con un esempio nello script line.fx.

Per la gestione del testo si veda lo script text.fx, che mostra come formattare stringhe di caratteri con diversi stili.

Per vedere come applicare trasformazioni a immagini c'é lo script transform.fx, nota che si fa riferimento a un file, strawberry.jpg che deve essere presente nella stessa directory dello script.

Per avere un esempio di come gestire il layout ci sono due script, hbox.fx e vbox.fx, che usano classi del package javafx.scene.layout.

Introduzione alle GUI - cellulare o desktop

Secondo tutorial per javaFX disponibile sul sito della sun. Mentre il primo era rivolto al core delle funzionalità di javaFX, qui vedremo meglio come costruire applicazioni con una GUI. La prima lezione ci serve per avere una introduzione alla materia.

javaFX é pensato per lavorare sia su un computer propriamente detto, con svariati pollici di spazio a disposizione per visualizzare il proprio output, sia su periferiche mobili, come a dire su telefoni cellulari dove lo spazio a disposizione é molto più modesto.

Ci sono due profili javaFX a disposizione, il common profile che include classi per operare in entrambi gli ambienti, e il desktop profile dedicato esclusivamente a funzionalità pensate per migliorare le applicazioni cosiddette desktop.

Per vedere l'effetto che fa un applicazione javaFX su un telefono, é possibile utilizzare l'emulatore incluso nel javaFX SDK. Se si sta usando netbeans, si può impostare nelle proprietà del progetto il modello di esecuzione in modo che l'eseguibile in fase di testing corra sul emulatore di cellulare (il tutto si trova nelle proprietà del progetto, sotto la categoria "run")

Come primo esempio per vedere come gira un applicazione javaFX é reso disponibile sul sito sun un semplice script, ball.fx, che mostra per l'appunto una palla.

Package e accesso

Ultime due lezioni, numero 10 sui package e 11 sui modificatori d'accesso, del corso Sun introduttivo a javaFX.

Niente da dire a commento aggiuntivo sui package, tutte cose che chi ha usato java conosce già. E quindi passiamo direttamente all'ultima lezione.

Accesso default

Se non specifichiamo nessun accesso intendiamo utilizzare l'accesso di default (come pare ragionevole), noto anche in javaFX come script-only, nel senso che tutto ciò che é definito in questo modo é visibile solo nel file corrente.

Questa modalità d'accesso é evidentemente specifica per javaFX, dato che in java non c'é questa interpretazione di un singolo file come unità a sé stante.

Accesso package

E' in javaFX quello che é per java l'accesso default, creando probabilmente qualche confusione. Anche perché per dichiarare che una variabile ha in javaFX un accesso package devo scrivere qualcosa del genere:

package var x;

Che può confondere le idee rispetto al concetto di package come unità contenente classi (e script).

In ogni caso: una variabile, classe o funzione dichiarata di accesso package é visibile dal codice presente nello stesso package.

Come esempio di uso della visibilità a livello package, creamoci un paio di file, nel primo, one.fx, scriviamo questo codice:

// tutorial/one.fx
package tutorial; // (1)

package var message = "Hello from one.fx!"; // (2)

// (3)
package function printMessage() {
println("{message} (in function printMessage)");
}

1: dichiariamo che il file é nel package tutorial.
2: definiamo una variabile con visibilità limitata al package corrente
3: definiamo una funzione con visibilità limitata al package corrente

Creiamo quindi un altro file, two.fx, che usa quanto definito in one.fx:

// tutorial/two.fx
package tutorial; // (1)

println(one.message); // (2)
one.printMessage(); // (3)

1: dichiariamo che il file é nel package tutorial.
2: usiamo la variabile message definita nell'oggetto one package corrente
3: definiamo la funzione printMessage() definita nell'oggetto one del package corrente

Questo modo di accedere variabili e fuzioni definite in one.fx ci spiega anche come funziona il trucco che permette a javaFX di farci definire codice e funzioni in un file all'esterno di classi: viene evidentemente definito un oggetto implicito che ha lo stesso nome del file.

Quindi per accedere la funzione printMessage() definita nel file one.fx scriviamo semplicemente:

one.printMessage();

Accesso protected

Qui siamo nel terreno conosciuto delle modalità di accesso java: l'accesso protected fa in modo che quanto definito sia accessibile all'interno del package corrente e da tutte le classi derivate da ogni classe del package stesso.

Riscriviamo l'esempio precedente dando, in one.fx, visibilità protected a un membro di classe pubblica:

package tutorial;

public class one {
protected var message = "Hello!";
}

La classe one sarà accedibile da ovunque, essendo pubblica, e message sarà accedibile da tutte le classi derivate da one, essendo protected. Per veder ciò, riscriviamo two.fx in questo modo:

import tutorial.one;

class two extends one {
function printMessage() {
println("Class two says {message}");
}
};

var t = two{};
t.printMessage();

Da notare, oltre a quanto detto per protected, un paio di cosettine: in javaFX la convenzione sui nomi é decisamente più rilassata (almeno in questo tutorial), e le classi hanno nomi che cominciano con lettere minuscole. Inoltre l'oggetto di tipo two viene costruito qui con la sintassi specifica di javaFX, ovvero, e non con quella java (var t = new two();).

Accesso public

Come per il public in java, massima accessibilità garantita per chi ha questo livello di accesso.

Accesso public-read

Altra interessante estensione di javaFX alle modalità di accesso proprie di java. Con public-read diciamo che una variabile é accedibile in lettura a tutti, ma può essere modificata solo nello script corrente.

E' possibile cambiare i privilegi in scrittura a questa variabile abbinando a public-read il modificatore di accesso package o protected.

Accesso public-init

Estende ulteriormente la public-read, rendendo la variabile anche inizializzabile da tutti. Ma, dopo l'inizializzazione, accedibile solo in lettura a livello public. L'accesso in scrittura, dopo la creazione, é gestito come nel caso public-read, ovvero solo nello script corrente per default.

Scrivere classi

Con la lezione numero 9 del corso Sun introduttivo a javaFX, torniamo a vedere cose che, per chi abbia un background java sono piuttosto scontate, si parla infatti, con un po' più di dettaglio di quanto si sia fatto precedentemente, di classi e oggetti in javaFX.

La differenza fondamentale tra java e javaFX, é che é stato rimossa la limitazione sul nome del file che dove corrispondere al nome della classe principale contenuta nel file stesso. E quindi si possono mettere tutte le classi che vogliamo in un unico file. Questo rende probabilmente la struttura di un progetto FX meno lineare di un java classico ma permette una più semplice scrittura di script.

Approfitteremo di questa feature di javaFX per scrivere tutto il codice di cui parliamo in questo post in un unico file fx.

Prima cosa, definiamo la classe Address in questo modo:

class Address {
var street: String;
var city: String;
var state: String;
var zip: String;
}

In pratica un indirizzo viene definito come un aggregato di quattro stringhe: via, città, stato, e cap.

Un poco più interessante la classe Customer, che definisce come suo dato membro un oggetto di tipo Address e tre funzioni che usano i dati della classe:

class Customer {
var firstName: String;
var lastName: String;
var phoneNum: String;
var address: Address;

function printName() {
println("Name: {firstName} {lastName}");
}

function printPhoneNum(){
println("Phone: {phoneNum}");
}

function printAddress(){
println("Street: {address.street}");
println("City: {address.city}");
println("State: {address.state}");
println("Zip: {address.zip}");
}
}

Per costruire un oggetto di tipo Customer, facciamo come si vede qui a seguire. In questo caso l'oggetto é costante (visto il def che lo introduce) ma sarebbe ovviamente potrebbe essere variabile:

def customer = Customer {
firstName: "John";
lastName: "Doe";
phoneNum: "(408) 555-1212"
address: Address {
street: "1 Main Street";
city: "Santa Clara";
state: "CA";
zip: "95050";
}
}

Definito customer di tipo Customer possiamo ora chiamare le funzioni definite per esso in questo modo:

customer.printName();
customer.printPhoneNum();
customer.printAddress();

Gerarchie di classi

E' possibile scrivere gerarchie di classi, dove classi figlie ereditano il comportamento di una classe madre. Se marchiamo una classe come astratta intendiamo che non siano creati oggetti di quel tipo. Vediamo qui un esempio:

abstract class Account {
var accountNum: Integer;
var balance: Number;

function getBalance(): Number {
return balance;
}

function deposit(amount: Number): Void {
balance += amount;
}

function withdraw(amount: Number): Void {
balance -= amount;
}
}

Data questa classe base possiamo definire ora una classe che la estende, aggiungendo dati e funzioni:

class SavingsAccount extends Account {
var minBalance = 100.00;
var penalty = 5.00;

function checkMinBalance() : Void {
if(balance < minBalance){
balance -= penalty;
}
}
}

Ed é possibile anche fare in modo che una classe figlia abbia un comportamento diverso dalle madre, possiamo infatti ridefinire una funzione nella classe figlia usando la parola chiave override:

class CheckingAccount extends Account {
var hasOverDraftProtection: Boolean;

override function withdraw(amount: Number) : Void {
if(balance-amount < 0 and hasOverDraftProtection){
// code to borrow money from an overdraft account would go here
}
else {
balance -= amount; // may result in negative account balance!
}
}
}

Visualizzare un riassunto

Una semplice modifica al template di blogger per far sì che sulla pagina principale del proprio blog venga visualizzata solo la prima parte del post.

Scopo di questo cambiamento é dare a chi accede il blog su blogspot una vista complessiva di quanto é pubblicato, lasciandogli la possibilità di andare sulla pagina che gli interessa per vedere il post nella sua interezza.

Questo dovrebbe rendere la home del blog più pulita e leggibile.

Per far questo, creo una nuova class per il tag span e la uso nel testo del nostro post.

In pratica ogni nostro post sarà strutturato in questo modo:

Qui il riassunto che voglio sia visualizzato:
  • nella home del mio blog,
  • nella pagina specifica del post
<span class="fullpost">
Qui il corpo del post, visibile solo nella sua specifica pagina.
</span>

Il template del mio blog dovrà essere cambiato per riflettere l'utilizzo di questa nuova classe:

Subito prima della fine della sezione head nel mio template, aggiungo questo pezzo di codice:

<!-- riassunto o completo -->
<style>
<b:if cond='data:blog.pageType == "item"'>
span.fullpost {display:inline;}
<b:else/>
span.fullpost {display:none;}
</b:if>
</style>
<!-- riassunto o completo -->

Potrebbe bastare così, ma aggiungiamo sulla home del mio blog anche un link al post completo subito dopo il riassunto, per renderne più semplice l'accesso al lettore.

Vado quindi a cercarmi nel template la fine della sezione dedicata al testo del post pubblicato, che sarà questo tag:

<data:post.body/>

Subito dopo metterò il mio codice, che genererà un link all'URL della pagina specifica per il mio post:

<!-- riassunto o completo -->
<b:if cond='data:blog.pageType != "item"'>
<p><a expr:href='data:post.url'>Leggi il post completo</p>
</b:if>
<!-- riassunto o completo -->

Il risultato di queste modifiche lo si vede sulla pagina principale di questo blog.

Data Binding e Trigger

La lezione numero 8 del corso Sun introduttivo a javaFX é invece piuttosto interessante, si parla qui di due funzionalità utili che sono implementate in modo elegante.

Per prima cosa parliamo di binding, ovvero della possibilità di correlare dati in modo che il cambiamento di uno si rifletta immediatamente nell'aggiornamento dell'altro.

E' ad esempio una funzionalità utilissima per codice progettato secondo i principi del MVC (Model View Controller), dove il Controller deve tenere in sincronia Model e View. La possibilità di stabilire esplicitamente un legame tra diverse variabili rende il codice molto più leggibile e manutenibile.

Vediamo ora esempi piuttosto banali di binding, giusto per prendere confidenza con l'implementazione javaFX del concetto.

Dichiariamo una variabile x e poi creiamo una costante y definita come connessa a x. Il fatto che sia costante ci impedisce di modificarla direttamente, il fatto che sia definita come "bind x" fa sì che sia in pratica un alias di x, ogni cambiamento di x si riflette in una cambiamento di y:

var x = 0;
def y = bind x;
x = 1;
println(y); // 1
x = 47;
println(y); // 47

E' possibile legare dati membro di una classe a variabili indipendenti:

var myStreet = "1 Main Street";
var myCity = "Santa Clara";
var myState = "CA";
var myZip = "95050";

def address = Address {
street: bind myStreet;
city: bind myCity;
state: bind myState;
zip: bind myZip;
};

println("address.street == {address.street}");
myStreet = "100 Maple Street";
println("address.street == {address.street}");

E' possibile creare un legame tra variabili usando una funzione, specificando la parola chiave bound:

var scale = 1.0;

bound function makePoint(xPos : Number, yPos : Number) : Point {
Point {
x: xPos * scale
y: yPos * scale
}
}

class Point {
var x : Number;
var y : Number;
}

var myX = 3.0;
var myY = 3.0;
def pt = bind makePoint(myX, myY);
println(pt.x); // 3

myX = 10.0;
println(pt.x); // 10

scale = 2.0;
println(pt.x); // 20

Nota che si crea un legame tra le variabili locali passate come parametri alla funzione e i dati membro dell'oggetto creato dalla funzione stesso. Una funzione bound é usata in pratica come un costruttore di oggetto che mantiene un legame con i parametri passati.
Nota inoltre che anche quando viene cambiato un valore globale utilizzato dalla funzione bound (nel nostro caso scale) i valori dell'oggetto creato dalla funzione bound vengono ricalcolati.

E' possibile anche usare bind in congiunzione con for per generare una nuova sequenza:

var seq1 = [1..10];
def seq2 = bind for (item in seq1) item*2;
printSeqs();

function printSeqs() {
println("First Sequence:");

for(i in seq1){
println(i);
}
println("Second Sequence:");
for(i in seq2){
println(i);
}
}

Come ci si può aspettare, la seq2 contiene dieci elementi, ognuno del quale é il doppio del corrispondente elemento della prima sequenza.

Trigger

Un trigger é, in pratica, una funzione che viene eseguita quando accade un certo evento su dei dati. In javaFX é possibile scrivere del codice che viene eseguito quando una certa variabile viene modificata usando il costrutto on replace, come esemplificato a seguire:

var password = "foo" on replace oldValue {
println("Old Value: {oldValue}");
println("New Value: {password}");
};

password = "bar";

Il trigger mantiene in oldValue, o come la voglio chiamare, il valore prima del replace, e quindi esegue il codice. Se facciamo correre il codice, vediamo che il trigger é eseguito due volte: quando la variabile su cui é posto viene inizializzata a "foo", e quando il suo valore viene cambiato in "bar".

Operatori ed espressioni

Coppia di lezioni piuttosto noiose, la sei e la sette, all'interno del tutorial sun introduttivo a javaFX.

Gli operatori sono in pratica gli stessi di java/c++, con qualche piccola variazione per far diventar matto il programmatore, vediamoceli rapidamente.

Per l'assegnamento si usa un'uguale (=)

result = num1 + num2;

Gli operatori aritmetici sono +, -, *, /, mod:

result = 10 mod 7; // 10 / 7 = 1 col resto di 3, dunque result sarà 3.

E' possibile combinare gli operatori aritmetici con l'assegnamento, con l'eccezione del modulo:

result += 1; // equivalente a result = result + 1;

Gli operatori unari sono -, --, ++, not (negazione booleana)

var success = false;
println(success); // false
println(not success); // true

Non ci sono sorpese negli operatori di uguaglianza e relazione: ==, !=, >, >=, <, <= Mentre gli operatori condizionali sono and, or Anche l'operatore per il confronto dei tipi é una vecchia conoscenza (per chi conosca java, si intende): instanceof

Espressioni

Un blocco é, a tutti gli effetti, equivalente a una funzione inline: circondato da parentesi graffe, "ritorna" il valore dell'ultima espressione inclusa. Se non c'é alcuna espressione inclusa, il blocco é di tipo Void

var nums = [5, 7, 3, 9];
var total = {
var sum = 0;
for (a in nums) {
sum += a
};
sum;
}

println("Total is {total}."); // 24

Il flusso condizionale di esecuzione é solitamente implementato usando la solita struttura if - else if - else:

if (age < ticketprice =" 0;"> 65) {
ticketPrice = 5;
}
else {
ticketPrice = 10;
}

Ma in javaFX é disponibile anche questa scorciatoia che appare molto concisa ed elegante:

ticketPrice = if (age <> 65) 5 else 10;

Le sequenze, che aevamo visto qui, sono, parlando tecnicamente, delle espressioni di ambito (in inglese: range) di cui é possibile specificare la distanza tra i vari elementi usando la parola chiave step:

var odds = [1..10 step 2];
var down = [10..1 step -1];

I loop su una sequenza sono implementati elegantemente con un for, iterando sugli elementi:

var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];

for (day in days) {
println(day);
}

Nota che la variabile day é generata al volo dal compilatore per esistere solo per la durata del ciclo for.

Il ciclo while ha invece una costruzione più tradizionale:

var count = 0;
while (count < count ="=">

Per modificare il flusso di esecuzione all'interno di un ciclo sono disponibili le espressioni continue e break:

for (i in [0..10]) {
if (i > 5) {
break;
}

if (i mod 2 == 0) {
continue;
}

println(i);
}

La gestione delle eccezioni avviene secondo lo schema stabilito dalle espressioni throw (per lanciarla) catch (per gestirla) finally (per specificare cosa fare in ogni caso, dopo aver gestito l'eccezione, o se non c'é stata eccezione)

...
if(somethingWeird) {
throw new Exception("Something weird just happened!");
}

...

try {
foo();
}
catch (e: Exception) {
println("{e.getMessage()} (but we caught it)");
}
finally {
println("We are now in the finally expression...");
}

Virtualizzazione - Iniziative di AMD

Terzo capitolo di Virtualization for Dummies di Bernard Golden e Clark Scheffy che può essere scaricato gratuitamente, nell'edizione speciale Sun AMD, dal sito della sun.

Nei processori Quad-Core AMD Opteron viene implementata una ulteriore ottimizzazione hardware per la gestione della memoria, detta Rapid Virtualiztion Indexing.

Per migliorare il supporto della virtualizzazione nel campo delle connessioni di rete e della gestione della memoria di massa, AMD introduce il concetto di IOMMU: I/O Memory
Management Unit.

Virtualizzazione - La tecnologia AMD

Secondo capitolo di Virtualization for Dummies di Bernard Golden e Clark Scheffy che può essere scaricato gratuitamente, nell'edizione speciale Sun AMD, dal sito della sun.

Quattro risorse di un computer sono cruciali per la virtualizzazione:
  • Processore: La capacità di coordinare l'accesso alla CPU da parte dei diversi sistemi operativi ospitati dalla macchina é una delle sfide principali per la virtualizzazione, anche in considerazione del fatto che l'architettura hardware dei processori x86 non é stata progettata per il supporto di molteplici ospiti.
  • Memoria RAM: Neanche l'uso di questa risorsa é stato progettato per x86 avendo in mente il supporto multi-ospite.
  • Rete: Non si può pensare ai computer contemporanei se non in connessione via Internet
  • Memoria di massa: ogni sistema ospite virtuale deve avere la propria memoria di massa e il software di virtualizzazione deve mantenere isolata la memoria di massa di ogni sistema ospite.
In un ambiente virtualizzato é vitale salvare e gestire correttamente lo stato di ogni sistema ospite. L'hypervisor di virtualizzazione deve essere capace di gestire bene e velocemente gli stati dei vari sistemi ospite.

E' da molto che si adopera il concetto di memoria virtuale. La memoria RAM viene salvata sulla memoria di massa e ripristinata all'occorrenza, simulando una maggior quantità di memoria RAM a disposizione.

La CPU dell'Opteron di AMD é disegnata per permettere ottimizzazioni che velocizzano il passaggio di contesto tra i vari sistemi ospite, inoltre usano meno energia adattandosi a quelli che sono le richieste di carico di lavoro correnti.

Virtualizzazione - concetti base

Nonostante il titolo, mi sto leggendo Virtualization for Dummies di Bernard Golden e Clark Scheffy che può essere scaricato gratuitamente, nell'edizione speciale Sun AMD, dal sito della sun.

Alcuni concetti chiave che rendono la virtualizzazione un tema interessante:
  • normalmente l'hardware é sottoutilizzato, spesso le macchine usano solo il 10-15% della loro capacità di calcolo.
  • il numero di server utilizzati é cresciuto drammaticamente negli ultimi anni. La virtualizzazione permette di sfruttare meglio le macchine esistenti, riducendo la necessità di nuove macchine.
  • una nuova coscienza ecologica spinge a utilizzare meglio l'hardware esistente.
  • i costi per l'amministrazione dei sistemi aumentano.
Sono tre i principali tipi di virtualizzazione del server:
  • virtualizzazione del sistema operativo: la virtualizzazione di un sistema operativo é in esecuzione su un altro sistema operativo. Le applicazioni in esecuzione sul sistema operativo virtualizzato hanno l'illusione di avere l'intera macchina a disposizione.
  • emulazione hardware: il software di virtualizzazione (detto hypervisor) presenta un emulazione hardware della macchina su cui lavora il sistema operativo ospite. Questo ambiente viene detto VMM (Virtual Machine Monitor). In questo modo diversi sistemi operativi possono coesistere sulla stessa macchina.
  • paravirtualizzazione: in pratica l'idea é quella di permettere la coesistenza di diversi sistemi operativi sulla stessa macchina limitandosi ad arbitrare l'accesso alle risorse fisiche da parte dei diversi sistemi che sono quindi in competizione tra loro.
E questo direi che é quanto, per il primo capitolo.