mardi 14 juin 2011

Premiers pas en HTML 5 – Canvas

L’heure est venu de s’intéresser progressivement à HTML 5, dans la mesure où la spécification semble pouvoir prochainement dépasser le stade du Working Draft.

Donc, par où commencer? HTML 5 propose tout un tas de fonctionnalités hétérogènes. Certaines sont déjà supportées par la plupart des navigateurs, d’autres pas. Elles ne sont d’ailleurs visiblement pas toutes au même niveau d’avancement. Certaines portent sur l’aspect graphique, d’autres sur la communication ou encore sur la validation des formulaires par exemple. De même, les tutoriaux disponibles sont nombreux, mais dispersés. Donc pour démarrer, la façon la plus logique de procéder est de se concentrer sur les parties relativement stables et déjà implémentées par les navigateurs courants :

  • Les fonctionnalités multimédia (audio, vidéo, dessin, etc.)
  • Les fonctions de drag&drop
  • Le storage

Plus précisément, l’idée est ici de s’intéresser en premier lieu au Canvas, une nouvelle balise introduite par HTML 5 qui permet de définir une région dans laquelle on peut dessiner. Après avoir fastidieusement récupéré des bouts de code pour constituer un exemple simple et fonctionnel quelque soit le navigateur client, voici un premier résultat :

<!DOCTYPE html>
<html>
<head>
<title>Bouncing balls demo</title>
</head>
<body>
<section id="wrapper">
<header>
<h1>Bouncing balls</h1>
</header>
<article></article>
</section>
<script>
// global variables
var vSpeedInc = 1;
var hSpeed = 5.0;
var vSpeed = 1.0;
var circleRadius = 20;
var circleXPos = 100.0;
var circleYPos = 100.0;
var width = 800;
var height = 600;
var framerate = 50;

// start animation at startup
startAnimation();

function startAnimation(data) {
// canvas initialization
var canvas = document.createElement('canvas');
canvas.height = height;
canvas.width = width;
document.getElementsByTagName('article')[0].appendChild(canvas);
var ctx = canvas.getContext("2d");

// lauch timer
window.canvasTimer = setInterval(draw, 1000 / framerate);

function draw() {
// draw
ctx.clearRect(0, 0, width, height);
ctx.strokeStyle = "#000000";
ctx.fillStyle = "#FF0000";
ctx.beginPath();
ctx.arc(circleXPos, circleYPos, circleRadius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.stroke();
ctx.fill();

// compute
if (circleXPos + circleRadius >= width || circleXPos - circleRadius <= 0)
hSpeed = -hSpeed;


if (circleYPos + circleRadius + vSpeed >= height) {
vSpeed = -vSpeed;
}
else {
vSpeed = vSpeed + vSpeedInc;
}

circleXPos = circleXPos + hSpeed;
circleYPos = circleYPos + vSpeed;
}
}
</script>
</body>
</html>



Ce code anime une balle qui rebondit et se cogne sur les coins du Canvas. Il fonctionne seul, par simple copier/coller dans une page HTML vierge. Il représente donc un bon point de départ pour des expérimentations diverses, ce qui manque visiblement dans les différents tutoriaux disponibles.

vendredi 3 juin 2011

DbConnectionStringBuilder

Il y a plus de 10000 types définis dans le Framework .NET. Il est donc logique que quelques uns d’entre eux soient à la fois très utiles et méconnus. DbConnectionStringBuilder (et ses classes spécialisées comme SqlConnectionStringBuilder pour SQL Server) est sans doute l’un d’entre eux. Il permet de manipuler des chaines de connexion pour les providers communs par code (propriétés et accesseurs) sans avoir à traiter directement la chaine de caractères. Le code est alors plus lisible et il y a moins de risque d’erreur.

Dans la plupart des cas, les chaines de connexions définies habituellement dans le fichier de configuration n’ont pas besoin d’être modifiées à la volée. Néanmoins, certaines situations peuvent justifier l’utilisation de ces classes :

  • L’application accède à de multiples bases de données et il n’est pas possible de déterminer à la compilation quelle(s) base(s) de données sont sollicitées.
  • L’application accède à une base de données pour laquelle les informations nécessaires à la connexion ne sont pas connues lors de la compilation, par exemple parce qu’elles sont fournies par l’utilisateur.
  • L’application utilise des logins/passwords différents pour la connexion à la base de données en fonction des droits accordés à l’utilisateur connecté.
  • Ecriture de code pour l’industrialisation d’un logiciel automatisant la configuration en fonction des plateformes développement/intégration/préproduction/production.

En l’occurrence, l’utilisation de SqlConnectionStringBuilder s’est imposée pour basculer dynamiquement entre SQL Server et SQL Azure, à l’aide d’un code de ce type :

private string connectionString = null;

private string userIdAzure = "*****";
private string serverAzure = "*****";
bool azureContext = true;

public DataAccess()
{
connectionString = ConfigurationManager.ConnectionStrings["Connexion"].ConnectionString;
if (azureContext)
{
SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(connectionString);
scsb.DataSource = serverAzure;
scsb.UserID = userIdAzure;
connectionString = scsb.ConnectionString;
}
}



On voit que le champ azureContext permet de basculer dynamiquement entre SQL Server et SQL Azure, ce qui est parfaitement envisageable tant que les limitations inhérentes à SQL Azure sont respectées.


Note : Dans mon cas, le mot de passe et le nom de la base de données sont identiques pour la base SQL Server et la base SQL Azure ; seuls l’User Id et le nom du serveur ont eu besoin d’être modifiés.