[UI] Software per la realizzazione di mockup per l’UI presentation

I mockup sono utili per capire cosa effettivamente vogliono i vostri clienti e per farsi una prima idea di progettazione della User Interface, sia essa web o mobile.
Infatti, è partendo da una rappresentazione grafica, magari di impatto, che il cliente riesce a “toccare con mano” ciò che vuole e su cui si può anche condurre una intervista per la raccolta dei requisiti di business.

Spesso si confondono le definizioni di mockup, wireframe e prototype; ecco un ottimo articolo che ne chiarisce le differenze: WireFrame, Prototype e Mockup – Dove sta la differenza.

Dunque, per la presentazione di mockup di una vostra applicazione, vi consiglio di utilizzare alcuni software, semplici ed immediati (alcuni li trovate negli articoli linkati in seguito in “Riferimenti utili”).

Per la realizzazione di un “concept” preliminare della user experience, capire dove posizionare gli elementi grafici sulle vostre pagine e come impostare la navigazione, è consigliabile realizzare un primo prototipo “statico” con Balsamiq Mockup. Questo utile software, free per il primo mese, ma accessibile come prezzo nella sua versione completa, vi permette di creare in pochi passi le varie schermate, mettendovi a disposizione dei widget abbastanza comuni nelle nuove applicazioni, sia web che mobile. Il risultato sarà un mockup statico, da esportare in PDF o in formato immagine.

20140216-204721.jpg

Esiste anche una ricca collezione di template condivisi da altri web designer e che potete consultare qui: MockupToGo Balsamiq.

Se la grafica dell’applicazione non è molto complessa, potete addirittura esportare il tutto in HTML, utilizzando un altro software, ossia Napkee. Quest’ultimo prende in input i sorgenti di Balsamiq ed esporta il tutto in formato HTML, generando anche i CSS e i Javascript e fornendo un minimo di interattività per alcuni componenti (come tab, accordion, select, link, ecc.). I risultati non sempre sono ottimi, anche perché Napkee è ancora in versione alfa. Può essere utile per pagine semplici e potete comunque agire su HTML e CSS/Javascript generati, modificandoli a mano.
Purtroppo, al momento si può soltanto partire dal sorgente statico Balsamiq, importarlo in Napkee e generare gli HTML, ma non il contrario.

Se il mockup statico non basta e vi occorre realizzare un prototipo interattivo più complesso (prototype), allora smanettate a livello di codice. Cercate qualche libreria di stile, come Metro UI, set di widget in stile Windows 8, che utilizza Bootstrap e JQuery.

20140216-205423.jpg

 

Riferimenti utili:

[PrimeFaces&jQuery] Letture consigliate su PrimeFaces e jQuery

Ho finito di leggere due libri ben fatti e molto pratici su PrimeFaces e jQuery, editi da Packt Publishing, e che consiglio a chi vuol imparare ad utilizzare queste due tecnologie web attualmente molto in voga.

Learning jQuery Learning jQuery

 

 

 

 

 

 

Sono corredati ovviamente anche da esempi scaricabili. Le versioni eBook sono economicamente accessibili, ma per Learning jQuery esiste anche una versione online free (disponibile QUI).

Il livello non è sicuramente avanzato, ma penso siano ottimi per chi sta approcciando ad un primo studio di questi framework. Sicuramente occorrono conoscenze di base di Javascript, CSS e, in generale, JSF (o tecnologie simili).

 

[iOs] Upload di immagini da app su server

Come primo post dell’anno, vi scrivo una soluzione per l’upload di foto su un vostro server (valida anche per qualsiasi altro tipo di file). Fino a poco tempo fa era possibile utilizzare il framework ASIHTTPRequest, che permetteva in modo agevole di eseguire questa operazione. Tuttavia, essendo tale framework “no-ARC compatibile”, vi consiglio un metodo nuovo che sfrutta la classe “nativa” NSURLConnection, oppure la libreria di terza parte URLConnection (per inserire una comoda progress bar).

Vi scrivo anche lo script PHP da richiamare lato app per l’upload della foto e che ho utilizzato come test (file image_upload.php):

/* image_upload.php */

<?php

//elenco delle estensioni permesse
$extensions_permitted = array("jpg", "png", "JPG", "PNG");

//path assoluto in cui si trova il file di script upload_image.php
$absolute_current_path = getcwd();

//recupero il nome del file dal parametro di input "filename"
$filename = $_POST['filename'];
$response = array();
$error = false;

//recupero l'estensione del file
$ext = pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION);

//controllo il nome file
if(empty($filename)){
  $error = true;
  $response['code'] = '500';	
  $response['message'] = ('Nome file non valido!');	
  $response['newfile'] = $filename.'.'.$ext;
}

//controllo l'estensione
if (!in_array($ext, $extensions_permitted)) {
  $error = true;
  $response['code'] = '500';	
  $response['message'] = ('Estensione del file non permessa!');	
  $response['newfile'] = null;
}

if(!$error){
	//NOTA: la seguente directory deve esistere sul proprio server.
	//Assicurarsi di avere i chmod di scrittura
	$uploaddir = $absolute_current_path.'/img/';

	//percorso assoluto del nuovo file
	$uploadfile = $uploaddir . $filename.'.'.$ext;

	if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    	$response['code'] = '200';	
  		$response['message'] = ('File valido e correttamente salvato!');	
        $response['newfile'] = $filename.'.'.$ext;
	} else {
    	echo "Errore nell'upload del file!\n";
        $response['code'] = '500';	
  		$response['message'] = ('Errore nell\'upload del file!');	
        $response['newfile'] = null;
	}

//echo 'Alcune informazioni di debug:';
//print_r($_FILES);

}

echo json_encode($response);

?>

Di seguito, una pagina di test PHP per controllare che il vostro script di upload sia stato configurato correttamente sul vostro server. NOTA. Vi troverete le immagini nella directory IMG relativa al file image_upload.php.

<html>
<head>
	<title>Upload a file</title>
</head>

<body>
<!-- Tipo di codifica dei dati, DEVE essere specificato come segue -->
<form enctype="multipart/form-data" action="upload_image.php" method="POST">

    <!-- MAX_FILE_SIZE deve precedere campo di input del nome file -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />

    <b>Nome file:</b>
    <input type="text" name="filename" value="" />

    <br/>

    <!-- Il nome dell'elemento di input determina il nome nell'array $_FILES -->
    <b>File:</b> <input name="userfile" type="file" />
    <br/>
    <input type="submit" value="Invia File" />
</form>

</body>

</html>

Ecco i codici sorgenti degli script PHP su riportati:

PHP upload script

upload
upload.rar (2 KB)

Template doesn't exists. Use default

Passiamo ora al codice Objective-C per la vostra app client. Ho creato la classe UploaderDelegate, che potete comodamente importare nei vostri progetti e che gestirà l’upload della foto. L’interfaccia è quella che segue:

//
//  UploaderDelegate.h
//
//  Created by Fr@nk on 07/01/14.
//  Copyright (c) 2014. All rights reserved.
//

#import <Foundation/Foundation.h>

@protocol UploaderProtocol <NSObject>

@required
-(void)successUpload;

@optional
-(void)unsuccessUpload;

@optional
-(void)updateProgressBar:(float)progress;

@end

@interface UploaderDelegate : NSObject<NSURLConnectionDataDelegate>{

    NSMutableData *receivedData;

}

//singleton
+ (id)sharedInstance;
-(void)sendImageToServerWithURLPath:(NSString*)pathImage withFilename:(NSString*)filename toServiceURL:(NSString*)serviceURL;

@property (nonatomic, weak) id<UploaderProtocol> delegate;

@end

L’implementazione dell’UploadDelegate è questa:

//
//  UploaderDelegate.m
//
//  Created by Fr@nk on 07/01/14.
//  Copyright (c) 2013. All rights reserved.
//

#import "UploaderDelegate.h"
#import "URLConnection.h"
#import "Configuration.h"

@implementation UploaderDelegate

@synthesize delegate;

static UploaderDelegate *sharedInstance = nil;

// Get the shared instance and create it if necessary.
+ (UploaderDelegate *)sharedInstance {
    if (sharedInstance == nil) {
        sharedInstance = [[super allocWithZone:NULL] init];
    }

    return sharedInstance;
}

- (id)init
{
    self = [super init];

    if (self) {

    }

    return self;
}

-(void)sendImageToServerWithURLPath:(NSString*)pathImage withFilename:(NSString*)filename toServiceURL:(NSString*)serviceURL{

    //controllo se il file esiste
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:pathImage];

    if(!fileExists){
        NSLog(@"Error: file not exists!");
        //richiamo l'errorUpload sul Delegate in caso di success
        if (self.delegate && [self.delegate respondsToSelector:@selector(unsuccessUpload)]) {
            [self.delegate unsuccessUpload];
        }
        return;
    }

    //controllo la grandezza del file
    NSError *AttributesError = nil;
	NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:pathImage error:&AttributesError];
	NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
	long fileSize = [fileSizeNumber longValue];
	NSLog(@"File: %@, Size: %ld", pathImage, fileSize);
    if(fileSize<=0){
        NSLog(@"Error: file size incorrect!");
        //richiamo l'errorUpload sul Delegate in caso di success
        if (self.delegate && [self.delegate respondsToSelector:@selector(unsuccessUpload)]) {
            [self.delegate unsuccessUpload];
        }
        return;
    }

    //se la foto è troppo grande, la comprimo
    UIImage *originalImage = [[UIImage alloc]initWithContentsOfFile:pathImage];

    //NSData *dataImage = [NSData dataWithContentsOfURL:[NSURL URLWithString:pathImage]];
    //NSData *dataImage = [[NSFileManager defaultManager] contentsAtPath:pathImage];

    CGFloat compression = 0.9f;
    CGFloat maxCompression = 0.1f;
    int maxFileSize = MAXFILESIZE_IMAGE_UPLOAD;

    //comprimo l'immagine e la salvo in JPEG, se è troppo grande
    NSData *dataImage = UIImageJPEGRepresentation(originalImage, compression);

    while ([dataImage length] > maxFileSize && compression > maxCompression)
    {
        compression -= 0.1;
        dataImage = UIImageJPEGRepresentation(originalImage, compression);
    }

    NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:serviceURL]];

    [postRequest setHTTPMethod:@"POST"];

    NSString *boundary = @"BVillage";
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
    [postRequest addValue:contentType forHTTPHeaderField: @"Content-Type"];

    NSMutableData *body = [NSMutableData data];

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"filename\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[filename dataUsingEncoding:NSUTF8StringEncoding]];

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Disposition: form-data; name=\"userfile\"; filename=\"tmpFile.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:dataImage]];
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];

    [postRequest setHTTPMethod:@"POST"];
    [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

    // Setting a timeout
    postRequest.timeoutInterval = 60.0;
    [postRequest setHTTPBody:body];

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    /*[NSURLConnection sendAsynchronousRequest:postRequest
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
     */
    [URLConnection asyncConnectionWithRequest:postRequest completionBlock:^(NSData *data, NSURLResponse *response) {

        NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

        NSDictionary *responseJSON = [NSJSONSerialization
                                      JSONObjectWithData:data
                                      options:kNilOptions error:nil];

        NSLog(@"Response JSON: %@",responseJSON);

        //if(!error){
            //richiamo il successUpload sul Delegate in caso di success
            if (self.delegate && [self.delegate respondsToSelector:@selector(successUpload)]) {
                [self.delegate successUpload];
            }
            return;
        /*}
        else{
            //richiamo l'errorUpload sul Delegate in caso di success
            if (self.delegate && [self.delegate respondsToSelector:@selector(unsuccessUpload)]) {
                [self.delegate unsuccessUpload];
            }
            return;
        }*/

    } errorBlock:^(NSError *error) {
        ////richiamo l'errorUpload sul Delegate in caso di success
        if (self.delegate && [self.delegate respondsToSelector:@selector(unsuccessUpload)]) {
            [self.delegate unsuccessUpload];
        }
        return;
    } uploadProgressBlock:^(float progress) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(updateProgressBar:)]) {
            [self.delegate updateProgressBar:progress];
        }

    } downloadProgressBlock:^(float progress) {
        //
    }

    ];

}

@end

Come potete vedere, ho utilizzato la libreria URLConnection, per poter mostrare durante il caricamento del file una “progress bar” (come spiegato in questo post: http://messagesenttodeallocatedinstance.wordpress.com/2012/04/10/nsurlconnection-with-blocks/).

Per poter usare la classe UploaderDelegate e procedere all’upload della foto, basta inserire nel vostro codice la seguente chiamata:

//chiamata al wrapper per l'upload dei file sul server
UploaderDelegate *uploaderDelegate = [UploaderDelegate sharedInstance];
uploaderDelegate.delegate = self;

NSString *pathFile = ABSOLUTE_PATH_OF_YOUR_PHOTO;
NSString *photoName = FILENAME_OF_YOUR_PHOTO;

    [uploaderDelegate sendImageToServerWithURLPath:pathFile withFilename:photoName toServiceURL:UPLOAD_IMAGE_URL];

NOTA. E’ importante settare che il pathFile sia il percorso assoluto alla vostra foto (comprensivo di nome del file e di estensione). La variabile photoName è il nome della foto (senza estensione) così come verrà salvata sul vostro server. Al posto dell’etichetta UPLOAD_IMAGE_URL ricordatevi di sostituire la URL del vostro servizio PHP di upload (per esempio, http://www.francescoficetola/upload/image_upload.php)

Ricordatevi di importare la classe suddetta e di settare la “delega” nel vostro ViewController, inserendo l’UploaderProtocol. Come ad esempio:

//
//  MyViewController
//
//  Created by Fr@nk on 07/01/14.
//  Copyright (c) 2014. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "UploaderDelegate.h"
#import "KKProgressToolbar.h"

@interface MyViewController : UIViewController<UploaderProtocol, KKProgressToolbarDelegate>{

    IBOutlet UIImageView *imageView;
    IBOutlet UIButton *imageUploadButton;
    KKProgressToolbar *progressBar;
}

/* metodi di delegate */
-(void)successUpload;
-(void)unsuccessUpload;
-(void)updateProgressBar:(float)progress;
-(IBAction)startProgressBarLoading;
-(IBAction)stopProgressBarLoading;

-(IBAction)sendPhotoToServer:(id)sender;

@property (nonatomic, strong) IBOutlet UIImageView *imageView;
@property (nonatomic, strong) KKProgressToolbar *progressBar;
@property (nonatomic, strong) IBOutlet UIButton *imageUploadButton;

@end

Per poter gestire gli eventi relativi all’upload, occorre definire nel vostro ViewController i seguenti metodi di delegate:

  • successUpload: richiamato dall’UploaderDelegate in caso di upload con successo
  • unsuccessUpload: richiamato dall’UploadDelegate in caso di errore nell’upload
  • updateProgressBar: richiamato dall’UploadDelegate durante l’upload per aggiornare la percentuale di caricamento sulla progress bar
  • startProgressBarLoading: da richiamare, lato app, per inizializzare la progress bar
  • stopProgressBarLoading: da richiamare, lato app, per stoppare la progress bar

NOTA. Per gestire la progress bar ho utilizzato la seguente libreria: KKProgressToolbar

#pragma mark Uploader methods

-(void)updateProgressBar:(float)progress{
    self.progressBar.progressBar.progress = progress;
}

-(void)successUpload{
    NSLog(@"successUpload");
    //in caso di successo aggiorno rimuovo la progress bar
    [self stopProgressBarLoading];

}

-(void)unsuccessUpload{

    NSLog(@"unsuccessUpload");
}

#pragma StatusBarLoading

-(void)addProgressBar{

    //aggiungo la progress view:
    CGRect progressBarFrame = CGRectMake(0, self.view.frame.size.height-100, self.view.frame.size.width, 44);
	self.progressBar = [[KKProgressToolbar alloc] initWithFrame:progressBarFrame];
	self.progressBar.actionDelegate = self;
    self.progressBar.progressBar.progress = 0;
    self.progressBar.statusLabel.text = @"Loading from server...";
	[self.view addSubview:self.progressBar];

    [self startProgressBarLoading];

}

- (void)didCancelProgressBarButtonPressed:(KKProgressToolbar *)toolbar {
    [self stopProgressBarLoading];
    //TODO: eliminare la richiesta di upload...
}

- (IBAction)startProgressBarLoading  {

    [self.progressBar show:YES completion:^(BOOL finished) {
        //Code
    }];

}

- (IBAction)stopProgressBarLoading {
    [self.progressBar hide:YES completion:^(BOOL finished) {
        //code
    }];

}

Creative Commons License
This work by Francesco Ficetola is licensed under a Creative Commons Attribution 4.0 International License.
Based on a work at www.francescoficetola.it.
Permissions beyond the scope of this license may be available at http://www.francescoficetola.it/2014/01/06/ios-upload-di-immagini-da-app-su-server/.

[JSF] PrimeFaces: una tecnologia di front-end che si sta imponendo nel mercato Enterprise

Logo Prime FacesMi è capitato di leggere un pò di articoli interessanti su PrimeFaces, tecnologia JSF che si sta imponendo in modo esponenziale nello scenario delle tecnologie web lato presentation. Ho utilizzato il suo antagonista Rich Faces, ma devo dire che Prime mi ha colpito particolarmente per tutta una serie di motivi che spiegherò in questo post.

In generale, i pregi delle tecnologie Java Server Faces (JSF) si possono riassumere nei seguenti punti:

  • rispetto del pattern architetturale Model-View-Controller (MVC), per separare la logica di presentazione dei dati da quella di business;
  • supporto alla realizzazione di una Rich Internet Application (RIA), in grado di offrire una user experience tipica di una Desktop application;
  • velocità nella presentazione dei dati e nella risposta alle interazioni utente, grazie al supporto asincrono AJAX di chiamata ai servizi e all’aggiornamento di porzioni di pagina (refresh parziale);
  • dinamicità ed interattività delle componenti grafiche, con possibilità di interazioni utente complesse, come, ad esempio, drag&drop, ridimensionamento e trascinamento;
  • facilità e velocità nello sviluppo dell’interfaccia utente, grazie al riuso di componenti già distribuite nel framework e alla semplicità nella loro customizzazione;
  • accessibilità delle pagine web generate e supporto alla presentazione su dispositivi mobile;
  • compatibilità con gli attuali web browser, ma anche supporto per quelli più datati.

Sulla base dei punti su riportati, ho provato il seguente set di tecnologie, tra loro compatibili, per lo sviluppo di un front-end di una Rich Internet Application:

  • Prime Faces: implementazione dello standard Java Server Faces – JSF 2.2;
  • JQuery/JQuery UI: framework javascript per la facile implementazione di componenti grafiche dinamiche ed interattive. Sono supportati nativamente da Prime Faces;
  • HTML 5: nuovo linguaggio di markup per l’implementazione di pagine web (in corso di standardizzazione);
  • CSS 3: evoluzione di CSS 2 per la definizione dello stile delle pagine web e della struttura dell’interfaccia utente.

Prime Faces è una implementazione dello standard “server-side” Java Server Faces (JSF 2.2). Fornisce un approccio “component-centric” per lo sviluppo di interfacce utente in tecnologia JEE, facilmente manutenibili, con modello di progettazione architetturale Model-View-Controller (MVC). Prime Faces permette di aggiungere funzionalità AJAX, sfruttandone le sue potenzialità come il meccanismo di chiamata asincrona a servizi, il refresh parziale delle pagine, le notifiche push, ecc. Esistono diverse implementazioni di JSF e le più diffuse sono le seguenti: Rich Faces, Ice Faces, MyFaces e Prime Faces. Quest’ultima sta riscontrando grande successo nella comunità di sviluppatori di front-end JEE, come si evidenzia dal seguente grafico di Google Trends:

Google Trend Prime Faces

Ecco i vantaggi che si traggono dall’utilizzo di Prime Faces:

  • Ricca suite di componenti. Prime Faces offre una suite open source di componenti UI avanzate (widget) per l’integrazione di funzionalità Ajax in applicazioni RIA (Rich Internet Application). Esistono, ad esempio, componenti per la realizzazione di tabelle con funzionalità avanzate (ordinamento, filtraggio, drag&drop, ecc.), menù ad albero, finestre a comparsa, calendar, picklist, widget per il file upload multiplo e tante altre (vedi Prime Faces – ShowCase);
  • Struttura multi-layout. Si può implementare in modo agevole una struttura multi-colonna con Prime Faces, utilizzando e customizzando i temi di cui dispone il framework e personalizzandone i fogli di stile, con l’utilizzo dei flexible box in CSS 3 (aree della pagina web con dimensioni flessibili).
  • Navigazione dinamica tra le pagine e finestre multiple con sessioni separate di lavoro. Grazie a JSF è possibile definire in modo semplice la navigazione tra le pagine, sia in modo predefinito che attraverso logiche di business. Inoltre, attraverso la definizione di opportuni “scope” si può rendere possibile la lavorazione su finestre multiple del browser, ciascuna con una sessione separata di lavoro.
  • Performance e supporto. Prime Faces è una libreria leggera e ciascuna componente in esso distribuito è piuttosto semplice da customizzare. Essendo una tecnologia piuttosto recente, è ottimizzata per il funzionamento sui browser di nuova generazione. Il grado di maturità delle componenti grafiche è alto, essendo il framework arrivato alla versione stabile 4.0. Inoltre, esistono una ricca documentazione e una attiva community online, per la risoluzione di comuni problematiche.
  • Compatibilità con i web browser recenti. Prime Faces garantisce la compatibilità con i browser più recenti, come Internet Explorer 9+, Google Chrome 17+  e Firefox 13+. Si dichiara il supporto anche per browser meno recenti, come Internet Explorer 7/8, sui quali viene rispettata l’interattività delle componenti (non di tutte però!), ma non il “look-and-feel” (per cui occorrerà agire manualmente modificando i CSS).
  • Notifiche push. Prime Faces consente di aggiungere funzionalità di push notification, utili per esempio per notificare cambiamenti di stato o aggiornamenti delle informazioni, in modo automatico ed asincrono, senza il refresh manuale delle pagine web.
  • Predisposizione al mobile. Grazie all’utilizzo di JQuery Mobile, è possibile realizzare, con l’estensione Prime Faces Mobile, pagine web con un “look-and-feel” simile alle app native (come quelle per iOs o Android)
  • Accessibilità e grafica responsive. Contrariamente ad altri framework AJAX-based, Prime Faces implementa le linee guida ARIA (Accessible Rich Internet Application) del W3C, garantendo per le componenti più comuni (tabelle, accordion, menù ad albero, componenti di input, …) la piena accessibilità. Inoltre, con l’ausilio di librerie Javascript (come BootStrap.js), è possibile realizzare con Prime Faces anche pagine in grafica “responsive”, ossia adattabile ai vari dispositivi (anche mobile).
  • Supporto a HTML 5. La maggior parte delle nuove componenti di Prime Faces sono sviluppate con HTML 5. Comunque, lo standard JSF 2.2 dichiara la possibilità di integrazione con tag HTML 5, utile per inserire nuove feature nelle pagine web, come i tag semantici.

 

Altri riferimenti utili:

 

[iOs] Idee e codici per menù ed altri componenti grafiche con effetti e transizioni su Code4App

Condivido qui un sito interessante, Code4App, dove vengono proposti menù ad effetto con transizioni:

In realtà, sul sito di Code4App troverete anche tante altre idee per la vostra app, come tab bar, animazioni, calendar, tabelle, ecc. ecc. Ovviamente troverete anche i codici sorgenti da scaricare e provare in xCode.

Ecco le categorie attualmente disponibili:

CodeApp - Category

Devo dire che è davvero una bella idea quella di raccogliere su un sito tutti i progettini utili ed interessanti condivisi da utenti di GitHub, BitBucket ed altri. Spesso, infatti, è difficile cercare quello che serve sui social network per programmatori, perché non mettono a disposizione una “vetrina” immediata che consente di individuare il componente desiderato.

Ecco i menù che ho trovato interessanti su Code4App e che ho usato per una mia app:

ios_menu popupscroll_menu ios

Il Freemium: Le app economiche potrebbero uccidere l’App Store

Condivido la posizione di Lex Friedman (grande contributor su MacWorld) sulle app economiche pubblicate sui mobile store (non solo di Apple). Eccovi la traduzione e ringrazio il mio amico Marco per avermela segnalata:

freemium-vs-premium

Le applicazioni economiche potrebbero uccidere l’App Store (di Lex Friedman)

Più si abbassano i prezzi per il software dell’iPhone, più la situazione per noi consumatori potrebbe peggiorare. Lo smartphone è probabilmente una delle cose più costose che abbiamo in tasca quotidianamente. Eppure molte persone sono decisamente avare quando guardano gli scaffali virtuali dell’App Store. Come mai? Ironicamente le cose che sono economiche nel breve periodo tendono a diventare costose a lungo andare.

Non sorprende che le applicazioni gratuite siano decisamente più popolari delle applicazioni a pagamento: piace a tutti avere qualcosa senza spendere un centesimo. Ma la cosa strana è che la gente consideri un’applicazione da tre euro decisamente costosa, ed una da dieci euro dal prezzo addirittura esorbitante. Conosco gente che gioca allo stesso gioco gratuito ogni singolo giorno, sorbendosi tutti i banner pubblicitari, piuttosto che spendere cinque euro una volta sola ed andare avanti per sempre senza alcun banner pubblicitario.
Nel momento in cui scrivo, tra le prime venti applicazioni più vendute dell’App Store 15 costano un euro e la più costosa viene sette euro. Il prezzo medio delle top 100 app a pagamento è inferiore ai due euro.
Mi colpisce che così tanti possessori di dispositivi iOS non capiscano che non stanno agendo nel loro interesse né a breve né a lungo termine quando sorridono al pensiero di spendere soldi sull’App Store. I clienti che spendono un sacco di soldi per l’hardware di dispositivi iOS si puniscono poi risparmiando sulle app.

Ottieni ciò per cui paghi.

Le applicazioni a pagamento tendono ad essere migliori delle alternative gratuite. Sono in pochi gli utenti Twitter che pensano che l’applicazione ufficiale offra la miglior esperienza utente, ma molti rimangono su questa semplicemente per evitare di confron- tarsi con le alternative a pagamento come Tweetbot oppure Twitterrific.

Molte applicazioni gratuite sono buone. Ma quando paghi per un’applicazione premium, spesso paghi per una esperienza utente più profonda, una per la quale tu sei il cliente più importante e non sono gli inserzionisti i responsabili del supporto dietro le quinte alla app “gratuita”.

La ragione per cui gli sviluppatori fanno pagare per le proprie applicazioni è che sviluppare un’applicazione ha un costo. Con quello che lo sviluppatore guadagna dalla vendita della sua applicazione può rientrare nell’investimento iniziale di tempo e risorse ed investire nello sviluppo futuro dell’applicazione. I clienti beneficiano di questo ottenendo applicazioni migliorate o nuove applicazioni da questi sviluppatori, invece di applicazioni gratuite abbandonate e di qualità inferiore.

Per un’applicazione da un euro uno sviluppatore guadagna circa 70 centesimi. Di questo passo uno sviluppatore deve vendere più di 70 mila copie per guadagnare almeno 50 mila euro. Per uno sviluppatore indipendente questi servono a coprire le spese, il costo di sviluppo e di progettazione, e poi vivere di quello che resta. Ma se l’applicazione da un euro viene sviluppata da una piccola società di tre persone, è necessario venderne almeno 300 mila affinché il business sia sostenibile. Ovviamente se gli sviluppatori mettono in vendita la loro app per un euro non dobbiamo sentirci in colpa acquistandole. Ma gli sviluppatori mettono in vendita le loro applicazioni a costi così bassi perché sanno che è il prezzo massimo per cui i clienti pagherebbero. E se questo è vero le applicazioni a basso prezzo stanno avendo un impatto negativo su parecchie aziende reali e potenziali.

L’ascesa del Freemium

Gli sviluppatori, comunque, sono ricchi di risorse. Così, visto che molti utenti detestano dover pagare per le applicazioni, abbiamo visto l’ascesa del modello Freemium: puoi scaricare l’app o il gioco gratuitamente, ma per poter continuare a giocarci dovrai fare uno o più acquisti in-app. E questi micropagamenti non sono solamente fastidiosi, ma a lungo andare possono costare all’utente molto di più. Ad esempio: EA Real Racing 2 inizialmente costava poco meno di sette euro. Poi è uscito con il modello Freemium, che costa agli utenti decisamente di più sul lungo periodo, semplicemente per ottenere lo stesso diverti- mento che anche Real Racing 2 offriva.

Fino a quando i clienti dell’App Store non mostreranno volontà a spendere soldi per ottime applicazioni, gli sviluppatori dovranno continuare su questa strada semplicemente per rimanere a galla.

Non è poi così caro.

Un iPhone 5 senza contratto costa di listino 729 euro e se si sceglie un iPhone con contratto di due anni alla fine si arriva a pagare almeno la stessa cifra. A confronto, un’app di quelle “care” può arrivare a costare circa l’uno per cento del prezzo dell’iPhone. E lo vale.

Non si compra un Kindle solamente per leggere il dizionario ed il manuale di istruzioni precaricato. E così non si dovrebbe comprare un iPhone solamente per utilizzare le applicazioni gratuite. Equivale a mentire a se stessi, solamente perché ognuno è ormai condizionato pensando che spendere cinque euro per un app sia troppo. Non è sbagliato pagare per prodotti di qualità.

Spendere soldi per buone applicazioni significa anche investire in ottime applicazioni che verranno create in futuro. Sistemiamo l’economia dell’App Store e iniziamo a pagare per le applicazioni senza rabbrividire quando ne vediamo una per quattro euro.

Tanti possessori di dispositivi iOS non capiscono che non stanno agendo nel loro interesse né a breve né a lungo termine quando sorridono al pensiero di spendere soldi sull’App Store.

 

Un altro articolo interessante (più vecchiotto) sull’argomento: App Store: con i prezzi troppo bassi è la fine?

 

Ecco quello che penso:

Sono in parte d’accordo con l’articolo di Friedman, perché sono ancora piuttosto scettico sulla politica del business via app. La concorrenza è spietata ed è difficile essere all’altezza nello sviluppare un’app in grado di vendere tanto sullo store.
Secondo me, ci si guadagna quando c’è un progetto di marketing vincente e strutturato dietro. La politica del guadagno tramite advising stanca l’utente, ma può risultare vincente nel breve periodo. Il freemium è davvero una bella trovata e un’ancora di salvezza (Vedi: Freemium VS. Premium)
Nel piccolo si può guadagnare vendendo l’idea e l’app a clienti o investitori. Purtroppo, l’app business non fa girare molti soldi in Italia, perché i clienti non hanno la concezione dello sforzo che si fa nel realizzarle e non comprendono ancora le potenzialità e l’utilità che possono offrire agli utenti finali. In Italia facciamo ancora ben poco tramite mobile (vedi anche i pagamenti online o la disponibilità di servizi a distanza utili al cittadino…).

Guardate un po’ i guadagni che si traggono dal modello Freemium:
freemium-percent

[iOs] Link Maker: generazione dinamica dei link di Apple Store

Per la generazione dei link di tutti gli articoli (ebook, musica, app, podcast, audiolibri, ecc.) disponibili su iTunes, iBook ed App Store, Apple mette a disposizione la pagina di iTunes Link Maker:  http://linkmaker.itunes.apple.com

Link Maker Apple

Esistono, in realtà, vari strumenti utili per la generazione dei link (creare link ad iTunes), utili però solo per la creazione di widget e link statici. Ad esempio, in questo Q&A si spiega come generare link a propri item (come, ad esempio, alla pagina delle app sviluppate da uno sviluppatore o da una società: Creating easy-to-read short links to the App Store for your apps and company).

Tuttavia, non esiste un vero e proprio framework che consenta di recuperare dinamicamente tali link. Occorre richiamare una URL di servizio, fornita proprio da Apple, così come si legge dalla Search API Documentation.

Ho così realizzato uno “scriptino” PHP in grado di restituirvi i risultati della pagina di iTunes Link Maker in formato JSON. Per fare ciò, mi sono aiutato con uno sniffer e ho recuperato tutte le URL richiamate dopo aver lanciato una ricerca sulla pagina di Link Maker. Le URL generate “dietro le quinte” dalla ricerca sono un bel po’ e cambiano in base alla combinazione tra “media” selezionato (categoria di item: audio, video, app, ebook, ecc.) e relative entity (sottocategorie di item non selezionabili, ma impostate da Apple come ulteriori keyword di ricerca, in base al media selezionato).

Potete provare la ricerca dalla form di esempio disponibile qui:

Nello script PHP che ho realizzato, non faccio altro che richiamare la stessa URL di Apple, passando una combinazioni di parametri (essenzialmente cambiano “media” ed “entity“):

http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/wsSearch?term=%s&country=%s&media=%s&entity=%s&limit=%s&genreId=%s&version=2&output=json

Al posto di %s occorre inserire dei valori ammissibili (la lista completa la trovate sulla documentazione ufficiale – Search API Documentation):

  • term: contiene la keyword di ricerca (ad esempio, “Oasis what’s the story morning glory”)
  • country: identificativo del Paese (IT, US, UK, ecc.). La ricerca restituirà gli item disponibili sugli Apple Store del paese selezionato. La lista completa dei Paesi è disponibile qui: http://www.francescoficetola.it/link-maker/countries.json
  • media: deve contenere la categoria di item. I valori ammissibili sono: audiobook (per gli AudioLibri), shortFilm (per i Cortometraggi), movie (per i Film), software (per le iOs app), ebook (per i Libri), macSoftware (per le Mac Apps), music (per i brani audio), podcast (per i PodCast), musicVideo (per i Video).
  • limit: numero massimo di risultati di ricerca da restituire;
  • entity: contiene le sottocategorie dei prodotti. Questo valore dipende dal parametro media impostato (le varie combinazioni sono elencate di seguito);
  • genreId: (opzionale) contiene il codice relativo al genere di media desiderato. Esistono varie combinazioni, disponibili al seguente link:

Ecco le combinazioni di media e relative entity, così come mappate nel mio script PHP:

//AUDIOLIBRI
if($media=='audiobook'){
   $entity = array('audiobookAuthor','audiobook');
}

//CORTOMETRAGGI
if($media=='shortFilm'){
   $entity = array('shortFilmArtist','shortFilm');
}

//FILM
if($media=='movie'){
   $entity = array('movieArtist','movie');
}

//iOS Apps
if($media=='software'){
   $entity = array('softwareDeveloper','software','iPadSoftware');
}

//LIBRI
if($media=='ebook'){
   $entity = array('ebookAuthor','metaEbook,textbook,ebook');
}

//Mac Apps
if($media=='macSoftware'){
   $entity = array('softwareDeveloper','macSoftware');
}

//MUSICA
if($media=='music'){
   $entity = array('musicArtist','song','album','musicVideo');
}

//PODCAST
if($media=='podcast'){
   $entity = array('musicArtist','podcastAuthor','podcast');
}

//VIDEO
if($media=='musicVideo'){
   $entity = array('musicVideoArtist','musicVideo');
}

Se volete richiamare direttamente il mio script PHP, senza passare dalla form di esempio su linkata (magari per farvi restituire un JSON da utilizzare nelle vostre app), eccovi la URL diretta:

  • http://francescoficetola.it/link-maker/linkmaker.php?term=%s&country=%s&media=%s&limit=%s&genreId=%s

I valori ammissibili da passare sono quelli espressi precedentemente e di seguito riassunti:

  • media: audiobook, shortFilm, movie, software, ebook, macSoftware, music, podcast, musicVideo
  • country: IT, US, UK, ecc.
  • term: la vostra query di ricerca (ad esempio, Oasis what’s the story morning glory”)
  • limit: (opzionale, di default è impostato a 50) determina il numero massimo di risultati che occorre restituire per ognuna delle combinazioni di URL di ricerca richiamate da Apple, in base al media impostato.
  • genreId: (opzionale) codice del genere degli item, il cui valore ammissibile è disponibile nel dizionario lmMediaTypeAndGenreDictionaries fornito da Apple.

Le combinazioni di entity sono definite direttamente nello script e non occorre specificare il parametro in input.

Ecco un esempio di ricerca:

http://francescoficetola.it/link-maker/linkmaker.php?term=jovanotti+bella&country=IT&media=music&limit=50&genreId=14

[iOs] Aggiornamento ad xCode 5: novità e how-to ai problemi post-upgrade

xCode 5Dopo gli upgrade di xCode, si hanno gli ormai inevitabili problemi di compatibilità o di change configuration di progetti scritti con una versione precedente. Sono passato al nuovo xCode 5 da quando è stato rilasciato per gli sviluppatori iOs, imbattendomi in alcune problematiche, e ho pensato di scrivere una sorta di “how-to” per la loro risoluzione, riportandolo in fondo a questo articolo.

Novità di xCode 5. Vediamo prima quali sono le novità introdotte in xCode 5:

  • Configurazione automatica: i progetti vengono automaticamente configurati per supportare i servizi Apple come iCloud, Passbook Game Center. Inserendo il proprio Apple ID, è possibile gestire anche il proprio team, i certificati e gli entitlements, il tutto direttamente da IDE (cosa che prima si effettuava connettendosi al Provisioning Portal). In base ai servizi richiesti, xCode importa anche i framework necessari e crea gli appropriati provisioning profiles, “firmando” l’app ogni volta che viene “buildata”.
  • Test Navigator: il test-driven development diventa più semplice, utilizzando il nuovo Test Navigator, editor in cui creare, modificare e lanciare gli unit tests. Si possono lanciare singoli test o gruppi di test, grazie ad Assistant Editor.
  • Bots per il Continuous Integration: xCode si integra (integrerà) con l’OS X Server del Sistema Operativo OS X Mavericks, permettendo la creazione di “bots” che “buildano” continuamente l’app ed eseguono i test e lo static analyzer per scovare potenziali bug. I bots possono essere lanciati su qualsiasi Mac presente in rete, monitorando l’integration work su macchina locale.
  • Auto Layout: l’auto-layouting permette di “aggiustare” automaticamente la dimensione delle view grafiche, il loro orientamento e la localizzazione (internazionalizzazione), direttamente da Interface Builder. Introdotti a tale scopo il free-form canvas e i constraints (in realtà già presenti nelle versioni precedenti di xCode).
  • Asset Management: grazie agli Asset Catalogs (salvati su file compressi con estensione .xcassets) si possono gestire le immagini inserite nelle app. Le diverse versioni della stessa immagine (per le differenti risoluzioni dei device) vengono collezionate tutte in un singolo file. L’Asset Catalog sceglie quale immagine renderizzare in base al device su cui si testa e permette anche di scalarla dinamicamente.
  • Debug deeper analysis: con il nuovo strumento di debug è possibile misurare anche il consumo dei dati, la memoria CPU occupata, l’energia in uso, e altri valori prestazionali (deeper analysis), allertando lo sviluppatore in caso di overhead.
  • Visual Debugger: il debugger utilizzato è l’LLDB engine (nelle precedenti versioni c’era anche GDB, adesso completamente rimosso). Resa più leggibile e chiara la visualizzazione dei messaggi di debug ed inseriti “data tips” più esplicativi. Finalmente, si può “ispezionare” con un singolo click la variabile/oggetto e stampare le sue proprietà direttamente sulla debug console.
  • Source Control: migliorato il sistema di versioning che visualizza anche i branch attivi di progetto e permette agevolmente di switchare, creare e mergiare i branch stessi. E’ possibile gestire in un singolo punto tutte le repository (Accounts preferences) e l’OS X Server su OS X Mavericks permette (permetterà) di “hostare” anche repository GIT per il team di sviluppo.

 

Problemi post-upgrade ad xCode 5. Riporto di seguito le anomalie riscontrate (e corrette) dopo l’aggiornamento ad xCode 5, su progetti scritti su versioni precedenti.

Nota. Questo articolo sarà costantemente aggiornato, man mano che mi si presenteranno anomalie su “vecchi” progetti nel nuovo ambiente di xCode 5.

  • Impossibile debuggare, visualizzazione del messaggio “Attaching appname” con schermata nera sul vostro Simulatore iOs. Se non riuscite più a debuggare le vostre app, vi viene mostrato continuamente il messaggio “Attaching <appname>” e lo screen del Simulatore vi rimane nero, senza dar minimo segno di visualizzazione della vostra app, nelle precedenti versioni di xCode bastava switchare dal debugger LLDB a GDB (Scheda Product>>Edit Scheme). Adesso, avendo eliminato il debugger GDB, tale procedura non funziona più e vi conviene seguire il seguente “how-to”: http://stackoverflow.com/questions/15174282/why-does-the-lldb-debugger-constantly-fail-to-attach. Occorre cioè assicurarsi che sul vostro file di hosts (presente al patch /private/etc/hosts del vostro Mac) si faccia lookup” di localhost su 127.0.0.1. Nel mio file di hosts, invece, vi erano mappati altri valori (colpa di Adobe Professional!).

(continua…)

 

Principi di buon design per progettare oggetti semplici e di facile uso

Caffettiera del masochista

“Quando cose semplici hanno bisogno di istruzioni per l’uso, è segno di un cattivo design.”

Una frase tratta da un saggio di scienze umane e un manuale indispensabile per il progettista. Questo è il libro di Donald A. NormanLa caffettiera del masochista – psicopatologia degli oggetti quotidiani“. Una riflessione sulla cattiva progettazione di oggetti che utilizziamo nella vita quotidiana, ma che ormai siamo abituati a maneggiare nel modo in cui ci è stato imposto e che spesso creano ripetute frustrazioni. Consigli su come evitare di commettere gli stessi sbagli quando li si realizza. Lettura indispensabile e mattone fondamentale per chi si occupa di design, di qualsiasi tipologia di oggetto, tangibile e non, reale o virtuale che sia. Si parla di psicologia dell’interazione tra persone e oggetti e di quella che è detta filosofia dei sistemi centrati sull’utente, di cui trovate un’altra mia riflessione qui: User-centered design: progettare considerando i bisogni degli utenti.  

La progettazione è l’applicazione successiva di vincoli e limitazioni finché quello che rimane è un prodotto unico.

La tesi centrale del libro è, appunto, quella di propugnare un design centrato sull’utente, una filosofia progettuale basata sui suoi bisogni edi interessi, che miri alla realizzazione di prodotti usabili e comprensibili.

“La gente si sente in colpa quando non riesce a usare le cose semplici, colpa che non è sua ma piuttosto dei progettisti e produttori degli oggetti”

Comics Easy to use

La colpa di una cattiva progettazione è dell’industrializzazione. Secondo Norman, lo studio del design degli oggetti è indissolubilmente legato a quello del funzionamento della mente umana (human information processing). Spesso vengono trascurati gli aspetti “naturali” e la rilevanza pratica, considerando soltanto quelli legati al fattore economico, alla semplicità nella produzione (come avviene in ambito industriale) e alla velocità di distribuzione sul mercato.  La maggior parte della colpa di una cattiva progettazione è dovuta proprio all’industrializzazione: le aziende vogliono qualcosa che possa essere prodotto in poco tempo e a basso costo.

Un progettista che si lascia influenzare da tali aspetti, si perde in dettagli inessenziali, dimentico dell’obiettivo a cui l’oggetto è destinato e “violenta” il normale processo di comprensione ed interpretazione delle procedure d’uso da parte degli utenti finali.

La colpa all’incentivazione della mal progettazione è anche nostra, perché se la gente continua ad acquistare prodotti progettati male, industriali e progettisti penseranno di aver fatto bene e continueranno a produrre le cose allo stesso modo.

 

Tenere conto di vincoli, condizioni ed istruzioni semplici. Quando si costruiscono gli oggetti occorre tenere imprescindibilmente in conto i vincoli ambientali e le condizioni d’uso, rendere le istruzioni semplici per l’utilizzatore finale, in modo da creare un prodotto pratico e semplice. E ancora, secondo Norman, la maggior parte degli errori che vengono commessi dall’uomo quotidianamente è dovuta ad una cattiva progettazione degli oggetti che utilizzano.

Un esempio emblematico è quello della porta: per capire come aprire una porta, le parti giuste devono essere visibili e devono trasmettere un giusto messaggio (i cosiddetti “segnali naturali“), come i cardini, la maniglia e il sostegno. Dove l’oggetto non è semplice da utilizzare, le istruzioni devono essere comprensibili e semplici. Inoltre, l’attenzione all’estetica può rendere cieco il progettista (e l’acquirente) alla scarsa funzionalità.

Affordance

Affordance degli oggetti. Indica le proprietà reali e percepite delle cose materiali che determinano come si potrebbe verosimilmente usare un oggetto in questione. Per esempio, quando vediamo una porta in vetro, è dallo spessore della maniglia che possiamo percepire quanta forza occorre applicare per poterla aprire.

Altra regola fondamentale: le cose complesse possono richiedere spiegazioni, ma quelle semplici non dovrebbero averne bisogno. Quando una cosa semplice esige figure, scritte o istruzioni, vuol dire che il design è sbagliato. E’ il progettista che deve essere abile a rendere chiaro il funzionamento della sua “creatura”, tenendo in considerazione la psicologia umana, ossia come un utente può desumere per proprio conto come “muoversi” (grazie ad una esperienza personale di come funzionano le cose del mondo esterno).

 

Principi di design per la comprensibilità e l’usabilità. Due sono i principi fondamentali per una buona progettazione:

  1. fornire un buon modello concettuale, grazie al quale possiamo prevedere gli effetti delle nostre azioni mentre utilizziamo un oggetto
  2. rendere visibili le cose. Il principio di visibilità è, secondo Norman, continuamente contraddetto negli oggetti quotidiani e, in molti schemi costruttivi, le parti cruciali sono accuratamente occultate.

Rendere le parti di un oggetto visibili, per renderne facile l’utilizzo. Ma non inserire troppe di queste parti, altrimenti l’oggetto stesso diventerebbe troppo complesso. Inoltre, l’affidamento eccessivo agli automatismi, può annullare la capacità di cavarsela in loro assenza.

Conceptual Models NormanPer capire la figura precedente, riporto la didascalia riportata nel libro, che ci fa ben capire qual è il “gap” che separa il progettista dall’utente finale.

“Il progettista deve costruire preventivamente un modello concettuale dell’oggetto, che dal suo punto di vista è detto modello progettuale, immaginando gli effetti e come gli utenti potrebbero utilizzare il suo prodotto e trarne beneficio. Il modello dell’utente è il modello mentale sviluppato attraverso l’interazione con il sistema. L’immagine del sistema risulta dalla struttura fisica che è stata costruita (compresa documentazione, istruzioni, etichette, ecc.). Il progettista si aspetta che il modello dell’utente sia identico al modello progettuale. Ma non parla direttamente con l’utente, visto che la comunicazione avviene attraverso l’immagine del sistema. Se l’immagine del sistema non rende chiaro e coerente il modello progettuale, l’utente finirà per formarsi un modello mentale sbagliato. ”

 

Mapping e feedback. Ecco altri principi a cui occorre rifarsi per una buona progettazione:

  • Mapping: indica la relazione fra i comandi previsti per un oggetto e i risultati che ne derivano nel mondo esterno. In pratica, occorre stare attenti a non inserire troppi comandi nel nostro oggetto e fare in modo che ad ognuno di essi sia associato un determinato comportamento/effetto. Evitare le combinazioni di comandi, altrimenti all’utente risulterà complicato eseguire determinate operazioni. Infatti, quando il numero delle funzioni e operazioni richieste eccede il numero dei comandi, il progetto diventa arbitrario, innaturale e complicato. Si rende così il dispositivo più difficile da usare ed imparare.
  • Feedback: indica l’informazione di ritorno che dice all’utente quale azione ha effettivamente eseguito, quale risultato si è realizzato, dandogliene un effetto e riscontro immediato e facendolo entrare in sintonia con l’oggetto.

Rispettando tali principi, l’utente può: 1) indovinare il da farsi, 2) capire che cosa sta succedendo, interpretando lo stato del sistema.

Per semplificare il processo di apprendimento ed interpretazione, avrebbe senso standardizzare tutta una serie di procedure che l’utente è abituato ad eseguire quotidianamente quando utilizza oggetti destinati allo stesso compito. Purtroppo, quest’ultimo punto è di difficile attuazione, visto che occorrerebbe mettere d’accordo i vari produttori.

 

Come può il design segnalare le azioni appropriate? Un insieme importante di segnali ci arriva attraverso i vincoli naturali degli oggetti, vincoli fisici che limitano le possibilità di azione. Un altro insieme di segnali viene da quelle che abbiamo chiamato affordance, gli inviti forniti dagli oggetti, che trasmettono messaggi circa i loro possibili usi, azioni e funzioni. Gli inviti d’uso suggeriscono la gamma delle possibilità, i vincoli limitano il numero delle alternative. L’uso intelligente di inviti e vincoli d’uso combinati nella progettazione fa sì che l’utente possa determinare prontamente il corso esatto delle azioni anche in una situazione del tutto nuova.

Dunque, per far sì che l’utente sappia cosa fare quando utilizzare l’oggetto occorre “imporre” i seguenti vincoli:

  • Vincoli fisici: sono i più utili ed efficaci perché sono facili da vedere e interpretare, e limitano l’insieme delle azioni prima ancora di eseguirle.
  • Vincoli semantici: si affidano al significato della situazione per circoscrivere l’insieme delle azioni possibili, basandosi sulla conoscenza del mondo e della situazione stessa.
  • Vincoli culturali: sono vincoli “imposti” da convenzioni culturali accettate. Ogni cultura ha un insieme di azioni permesse in varie situazioni sociali e gli oggetti devono rispettare degli “obblighi” culturali.
  • Vincoli logici: quando si crea un rapporto logico fra la disposizione spaziale o funzionale dei componenti e le cose da questi controllate (o da cui queste dipendono).

 

Evitare gli errori. I progettisti devono essere attenti affinché gli errori possibili non comportino gravi conseguenze.

Se un errore è possibile, qualcuno prima o poi lo farà. Il progettista deve partire dal presupposto che tutti i possibili errori saranno commessi e impostare il progetto in modo da ridurre al minimo le probabilità di errore in primo luogo, o i suoi effetti una volta che esso sia verificato. Gli errori devono essere facili da individuare, devono avere conseguenze minime e, se possibile, i loro effetti devono essere reversibili.

Per far ciò, occorre focalizzarsi sullo scopo dell’oggetto, sugli effetti che realizzerà nel mondo esterno e verificare tali effetti. In sintesi, occorre effettuare una esecuzionevalutazione degli effetti (ciclo dell’azione).

Human Error

Progettare in vista dell’errore. Il progettista fa lo sbaglio di non tener conto dell’errore. Ma ecco la prassi che dovrebbe seguire:

  1. Capire le cause di errore e impostare il progetto in modo da ridurle al minimo
  2. Rendere le azioni reversibili – dare la possibilità di annullare il già fatto – o rendere più difficili le azioni irreversibili
  3. Facilitare la scoperta degli errori che comunque avvengono e renderne più facile la correzione
  4. Cambiare l’atteggiamento verso gli errori. Pensare l’utente come una persona che cerca di eseguire un compito e che ci arriva attraverso approssimazioni. Non pensarlo come un soggetto che commette errori: pensare piuttosto le azioni che esegue come approssimazioni di quanto richiesto.

Si deve progettare il sistema in modo tale che ci sia un margine di errore, consapevoli che il comportamento normale non è sempre esatto. Il progetto dev’essere tale che gli errori siano facili da scoprire e suscettibili di correzioni.

Spesso per attuare quanto detto poc’anzi è indispensabili prevedere delle funzioni obbliganti, ossia una forma di vincolo fisico che “guidano” le azioni in modo tale che la mancata esecuzione di un passaggio impedisca il successivo, come per esempio:

  • interlock: obbliga le varie operazioni ad essere eseguite nella sequenza corretta
  • lockout:  dispositivo che impedisce certi comportamenti, come l’entrata in un ambiente pericoloso
  • lockin: mantiene in funzione un apparecchio, impedendo che qualcuno lo fermi prematuramente.

Un buon design esige spesso una funzione obbligante per minimizzare gli errori.

Consiglio. Partire dal presupposto che prima o poi ogni possibile contrattempo accadrà, e quindi prendere le giuste contromisure. Occorre far sì che le azioni siano reversibili.

 

L’evoluzione naturale del design. Un progetto non rimane inalterato durante il suo ciclo di vita. Anzi, si scoprono e si modificano suoi problemi e difetti in corso d’opera, a seconda del tempo, dell’energia e delle risorse a disposizione. E’ ovvio che l’obiettivo dell’evoluzione è quella di correggere gli aspetti negativi e di lasciare inalterati quelli positivi (“ascensione“).

Una forza negativa è esercitata dalle esigenze di tempo: i nuovi modelli sono già in progettazione prima ancora che i vecchi siano stati consegnati. Inoltre, raramente esistono meccanismi per raccogliere le esperienze della clientela e farne tesoro. Un’altra forza è il bisogno di distinguersi, di creare modelli che appaiano diversi da tutto quanto c’è stato prima. Sono rarissime le aziende che si accontentano di mantenere in produzione così com’è un prodotto valido, o che lo lasciano perfezionare lentamente dall’evoluzione naturale. No, ogni anno deve uscire un modello “nuovo, migliorato”, di solito corredato di nuove caratteristiche che non prendono le mosse dal modello precedente. In troppi casi i risultati sono disastrosi per il consumatore.

Una volta ottenuto un prodotto soddisfacente, ulteriori cambiamenti possono essere controproducenti, specialmente se il prodotto ha successo così com’è. Bisogna sapere quando è il momento di fermarsi.

 

Il progettista: un utente atipico. Spesso il progettista considera se stesso un utente tipico del suo oggetto. Tuttavia, spesso non “vede” tutti gli aspetti degli utenti reali, o meglio, conosce già come funziona il suo oggetto, dando per scontato che anche gli altri possano comprenderlo. Una regola di base della progettazione è di conoscere e studiare i reali utenti, a partire dalle prime fasi del progetto stesso, alfine di evitare di apportare cambiamenti radicali all’oggetto alla fine dello sviluppo. C’è differenza tra la competenza richiesta per progettare un oggetto e quella necessaria ad usarlo.

“Nel loro lavoro, i progettisti spesso finiscono per diventare degli esperti del dispositivo al quale stanno lavorando. Gli utenti spesso sono invece esperti del compito da eseguire mediante quel dispositivo”

Altra difficoltà è data dal fatto che spesso i clienti del progettista possono non essere gli utenti del prodotto. In tal caso, un cattivo design è spesso sintomo dell’attenzione ai costi, senza prendere in considerazione la facilità di uso.

 

Sette principi per trasformare compiti difficili in compiti facili. Ricapitolando, sulla base di quanto su scritto, ecco i 7 principi per una buona progettazione degli oggetti quotidiani:

  1. Usare sia la conoscenza presente nel mondo esterno che la conoscenza interiorizzata
  2. semplificare la struttura dei compiti
  3. rendere visibili le cose
  4. impostare bene le correlazioni
  5. sfruttare i vincoli, sia naturali che artificiali
  6. lasciare un margine di errore
  7. quando tutto il resto non serve, standardizzare

La caffettiera del masochista

Cosa l’utente realmente voleva…la metafora dell’altalena

Chi ha studiato ingegneria del software si sarà sicuramente imbattuto in almeno una delle seguenti figure:

tireSwing-altalena la cruda realtà

 

La metafora dell’altalena dà bene l’idea del “gap” tra le esigenze dell’utente e quello che effettivamente viene realizzato da un progetto, quando le figure coinvolte diventano troppe e poco coordinate. Vi consiglio di leggere i seguenti articoli: