e-tef, la version électronique du
Test d'Evaluation de Français
Test des compétences en compréhension et
●
expression en français général
Exigé dans certains cas par Citoyenneté et
●
Immigration Canada (CIC)
Lancement de la version électronique en mars
●
2005
De nombreux challenges dans sa mise au
●
point !
Architecture e-tef
Serveur
d'examens
Client Flash + Zinc SI
TEF
Site web
e-tef
Dans quels cas utiliser une solution
type RDA ?
Gestion de médias lourds (audio/vidéo)
●
Besoin d'une capacité de déconnexion et/ou
●
d'accéder au système de fichiers local
Besoin d'une UI plus riche (ex : traitements
●
graphiques, cartographie, etc...)
Plus d'efficacité pour l'utilisateur :
●
moins de distractions
–
interface plus productive
–
moins de temps d'attente ?
–
Rich Desktop Applications :
(tentative de) définition
Applications client / serveur
●
fortement connectées (web services)
–
mais tirant partie des ressources locales
–
Cross-platform (+ ou -)
●
Déployables par HTTP
●
installation initiale d'un CLR
–
déploiement et mises à jour faciles
–
RIA RDA
Librairies AJAX Google Gears
XUL + CSS + JS Prism XulRunner
Flash/Flex Adobe AIR
Silverlight .NET (WPF)
Applets Java Java Web Start
Les plateformes les plus accessibles aux talents
des développeurs web (et les plus cross-
platform) : Adobe AIR et XulRunner
Adobe AIR
Windows / Mac OS X (bientôt Linux)
●
Flash + Actionscript ou Flex + Actionscript ou HTML + CSS +
●
Javascript
Moteur WebKit
●
Support audio / vidéo / PDF
●
IDE : Aptana, Flex Builder
●
Runtime commun à toutes les applications
●
Installation et mise à jour des applications
●
Signature d'applications
●
Propriétaire...
●
Pourquoi AIR peut séduire les
développeurs Ajax...
Mêmes compétences requises
●
Frameworks JS directement exploitables
●
(jQuery, extjs, dojo, ...)
Réutilisation du code
●
Prototypage rapide
●
Intégration OS via une API JS
●
Adobe AIR : API Javascript
Windows et Chrome SQLLite
● ●
Système de fichiers Monitoring de
● ●
connexion
Drag n' Drop
●
Requêtes HTTP
●
Copier/coller
●
(classe URLRequest)
var file = new air.File();
file.addEventListener(air.Event.SELECT, dirSelected);
file.browseForDirectory();
function dirSelected(event) {
alert(file.nativePath);
}
XulRunner
Plateforme de développement d'applis XUL
●
Version stable : 1.8.4 (-> Firefox 1.5)
●
Windows, Mac, Linux
●
Moteur Gecko
●
XUL + CSS + Javascript
●
IDE : XulBooster (plugin Eclipse)
●
Open Source
●
XUL
XML-based User interface Language
●
Ensemble de balises correspondant à des éléments
●
d'interface graphique :
Contrôles de formulaires
●
Grilles, arbres
●
Barres de menus
●
Barres d'outils
●
Démo : XUL périodic table
●
http://www.hevanet.com/acorbin/xul/top.xul
Hello world – part 1
application.ini
[App]
Vendor=R2
Name=demo
Version=0.1
BuildID=20070330
Copyright=Nonsense
ID=xxx
[Gecko]
MinVersion=1.8.1
MaxVersion=1.9
Hello World : part 2
/chrome/content/start.xul
<?xml version=quot;1.0quot;?>
<?xml-stylesheet href=quot;chrome://global/skin/quot; type=quot;text/cssquot;?>
<?xml-stylesheet href=quot;chrome://project/skin/main.cssquot;
type=quot;text/cssquot; title=quot;Skinquot;?>
<!DOCTYPE window SYSTEM quot;chrome://project/locale/start.dtdquot;>
<window
title=quot;&window.title;quot;
xmlns:html=quot;http://www.w3.org/1999/xhtmlquot;
xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.x
ulquot;
style=quot;width:900px;height:700px;margin:0px;padding:0px;quot;
onload=quot;Application.init();quot;>
<h1>Hello World !</h1>
</window>
XulRunner : quoi d'autre ?
Localisation facile
●
XBL : définition de composants d'interface
●
réutilisables
XPCOM : création de composants métiers
●
réutilisables en JS, C, C++, Python
API JS :
●
Manipulation d'images
–
Système de fichiers
–
Drag n' Drop, clipboard
–
SQLLite dans la version 1.9
–
XulRunner
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes[quot;@mozilla.org/filepicker;1quot;]
.createInstance(nsIFilePicker);
fp.init(window, __(quot;chooseDir.filepicker.titlequot;),
nsIFilePicker.modeGetFolder);
if (fp.show() == nsIFilePicker.returnOK) {
this.prefs.setComplexValue(quot;project.userDirquot;,
Components.interfaces.nsILocalFile, fp.file);
this.userDir = fp.file;
this.start();
}
RDA : recommandations
Indicateurs d'activité ! (loading...)
●
Raccourcis-clavier, surtout les basiques (tab,
●
enter, ...)
Implémenter le copier/coller
●
(et le drag n' drop)
Survol des boutons
●
Adopter le look & feel des applis desktop
●
Support des Web Services
AIR::Flex AIR::Ajax XulRunner
XML-RPC + (non-natif) - +
SOAP ++ - ++
REST +++ +++ +++
REST en résumé
Utilisation du plein potentiel de HTTP
●
Ressources et URIs
●
GET, POST, PUT, DELETE, HEAD, OPTIONS
●
Codes d'état : 200 OK, 201 Created, 400 Bad
●
Request, etc...
Représentations des ressources : XML, JSON,
●
Atom, RSS, ical, CSV...
Penser ressources plutôt qu'actions
GET /posts
POST /posts/add
GET /post/get/123
POST /posts/update/123
POST /posts/delete/123
vs
GET /posts
POST /posts
GET /posts/123
PUT /posts/123
DELETE /posts/123
REST et PHP
Difficile de trouver des outils RESTful en PHP !
●
ZF : Zend_Rest_Server n'est pas RESTful...
●
Symfony, CakePHP, CodeIgniter : pas de réel
●
support, même si cela reste possible de
l'implémenter soi-même
2 frameworks RESTful : Konstruct et Tonic,
●
mais encore bien jeunes...
Faut tout faire soi-même ;)
●
http://www.stato-framework.org
The Rails way : contrôleurs RESTful
$router = new My_Controller_Router_Rewrite();
$router->addResource('bookmarks', new
My_Controller_Router_Resource(
'/users/:username/bookmarks', array('controller' =>
'bookmarks',)
));
return $router;
http://monservice.com/users/raf/bookmarks/xxx.js
-> retourne JSON
http://monservice.com/users/raf/bookmarks/xxx.xml
-> retourne XML
http://monservice.com/users/raf/bookmarks/xxx
-> retourne HTML
class BookmarksController extends My_Controller_Action
{
// GET /users/raf/bookmarks
public function indexAction() {...}
// GET /users/raf/bookmarks/add
public function addAction() {...}
// GET /users/raf/bookmarks/edit
public function editAction() {...}
// POST /users/raf/bookmarks
public function doPostAction() {...}
// GET /user/raf/bookmarks/xxx
public function doGetAction() {...}
// PUT /user/raf/bookmarks/xxx
public function doPutAction() {...}
// DELETE /user/raf/bookmarks/xxx
public function doDeleteAction() {...}
}
?>
Mais attention :
class BookmarksController extends My_Controller_Action
{
// GET /user/raf/bookmarks/xxx
public function getAction()
{
$this->view->bookmark
= Bookmarks::find($this->__getParam('id'));
switch ($this->getRequest()->getFormat())
{
case 'xml':
$this->renderXml(
$this->view->bookmark->toXml()
);
break;
case 'atom':
...
break;
}
}
}
Mais attention :
class BookmarksController extends My_Controller_Action
{
// GET /user/raf/bookmarks/xxx
public function getAction()
{
$this->view->bookmark
= Bookmarks::find($this->__getParam('id'));
switch ($this->getRequest()->getFormat())
{
case 'xml':
$this->renderXml(
$this->view->bookmark->toXml()
);
break;
case 'atom':
Les contrôleurs peuvent
...
break;
devenir lourds !!!
}
}
}
Responsabilités des contrôleurs
Création d'objets associés (multiples INSERTs) ?
●
Validation des paramètres ?
●
Transactions ?
●
Envoi de mail, notifications ?
●
Est-ce vraiment le rôle des contrôleurs ?
Couche Services Ressources
class Bookmarks extends SResource
{
public function get() {...}
public function post() {...}
public function put() {...}
public function delete() {...}
}
Possibilité d'offrir des points d'entrée SOAP, XML-RPC et REST
●
<methodName>bookmarks.put</methodName>
Utilisation de l'API de Réflexion :
●
● Typage et validation des paramètres (type hinting)
● Génération automatique des fichiers WSDL et WADL