Travaillant essentiellement sur Windows Presentation Foundation et Windows Workflow Foundation, j'effectue quelques recherches et tests en ce moment sur les langages déclaratifs. Ces deux technologies partagent en effet une nouveauté en matière de développement : l'utilisation intensive de programmation déclarative qui vient le plus souvent en complément de programmation impérative.
Un langage déclaratif permet de représenter sous forme d'un document XML un programme qui pourrait être développé de la même manière sous forme impérative en C# ou en VB.net. On peut citer l'exemple du XAML utilisé par WPF afin de définir des interfaces graphiques. Comme indiqué ci-dessous, la création d'un bouton peut se faire comme auparavant avec du code C# ou VB.net en instanciant un objet Button et en définissant les propriétés souhaitées (comme le fait le designer Windows Forms de Visual Studio) ou alors sous forme de balises XML ou l'on représente une instance de bouton via une balise Button en définissant ses propriétés grâce à des attributs ou à des sous-éléments XML.
La même représentation est possible avec Workflow Foundation puisque les workflows peuvent être représentés sous forme de documents XOML complétés ou non par du code impératif :
<StateMachineWorkflowActivity x:Class="WorkflowLibrary1.Workflow2" Name="Workflow2" InitialStateName="Workflow2InitialState" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StateActivity Name="Workflow2InitialState" />
</StateMachineWorkflowActivity>
Bien evidemment, la réalisation technique de cette implémentation sous forme déclarative des objets proposés par Workflow Foundation et WPF ne s'est pas fait en réimplementant la logique de ces classes une seconde fois mais uniquement en effectuant une sérialization d'objets au format XML.
Le premier avantage direct de l'utilisation d'un tel style de développement est que le code impératif est beaucoup plus facilement outillable que du code impératif. Ceux d'entre-vous qui utilisent ou ont utilisé des générateurs de code en créant des templates pour CodeSmith ou encore des templates T4 pour des packages GAT savent que générer du code C# et/ou VB.net demande réflexion et n'est pas aussi simple qu'il n'y parait.
La génération de documents XML est beaucoup plus simple et cela permet donc d'ouvrir la génération de code au plus grand nombre. On peut citer l'exemple de WPF qui disposait avant sa sortie d'un petit nombre d'outils capable de générer du XAML tels que des éditeurs graphiques 2D comme Expression Design ou encore Expression Blend, des éditeurs 3D comme Aurora Mobiform et XAM3D, mais également des plug-ins pour des outils existants comme 3D Studio MAX, Illustrator qui leur permettent d'exporter leurs documents sous forme de document XAML et donc directement exploitable dans des applications WPF.
Il en est de même avec Windows Workflow Foundation avec notamment l'outil Sharepoint Designer qui permet de réaliser de manière visuelle des workflows, ces même workflows étant en réalité générés sous forme déclarative. De même si vous avez l'habitude de générer du code, vous pouvez très bien imaginer générer des interfaces graphiques ou encore des workflows directement depuis votre outil de génération de code préféré.
Le second avantage est que si l'on ne souhaite pas utiliser la représentation (le schéma) proposée par Microsoft, il est techniquement possible de créer sa propre représentation tout en continuant d'utiliser le framework existant. Il est par exemple possible d'utilise sa propre représentation sous forme XML afin de définir des workflows et de créer son loader afin de charger le workflow et d'utiliser tout le reste du framework proposé par Workflow Foundation afin d'héberger ses instances de workflow, les persister, etc. Ainsi penser utiliser les capacités de Drawing ML proposé (entre autres) par Visio afin de permettre à des utilisateurs finaux de représenter des Workflows sous forme de diagramme et charger le document OpenXML ainsi produit par Visio afin d'en faire un réél programme n'est pas illusoire et peut être tout à fait réalisable.
Cette programmation déclarative est relativement nouvelle et fait son apparition avec le framework.net 3.0 grâce aux implémentations proposées par WPF et WF mais également grâce à l'apparition d'un nouveau namespace : System.Windows.Markup. Ce namespace est très interessant puisqu'il vous permet ni plus ni moins de créer votre propre langage déclaratif de manière très simple !
Ainsi si vous souhaitez être capable de représenter sous forme déclarative du code utilisant votre framework interne afin d'être par exemple capable de créer un designer graphique permettant de générer du code utilisant votre framework révolutionnaire, vous pouvez le faire en utilisant deux classes de ce namespace : XamlReader et XamlWriter.
Prenons un exemple concre bien qu'ayant peu d'intéret en représentant un objet Guy (personne) capable d'effectuer une action et notamment de parler (grâce aux capacités de synthèse vocales fournies par le framework .net 3.0).
Un tel programme peut se représenter sous cette forme :
<Guy xmlns="http://schemas.wygwam.com/guy">
<Guy.Action>
<Speak Message="Test Message"></Speak>
</Guy.Action>
</Guy>
Afin d'être capable d'exécuter ce code, la première opération à réaliser est de définir un namespace au document afin d'indiquer à la CLR quelle assembly et quel namespace utiliser pour exécuter ce code. Une solution possible est utilisée par exemple par WPF est d'utiliser une notation du type xmlns="clr-namespace:guy;assembly:guy". La deuxième solution plus propre et plus portable est définir le namespace sous forme d'uri http et d'effectuer le mapping du coté de votre framework en utilisant un attribut assembly : [assembly:XmlnsDefinition("http://schemas.wygwam.com/guy","guy")]
Après avoir effectué ce "mapping" vous devez maintenant implémentez vos classes utilisées dans le document XML afin d'être capable de les instancier :
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Markup;
using System.Speech.Synthesis;
[assembly:XmlnsDefinition("http://schemas.wygwam.com/guy","guy")]
namespace guy
{
public interface IExecutable
{
void Execute();
}
public class Guy : IExecutable
{
private IExecutable m_test;
public IExecutable Action
{
get { return m_test; }
set { m_test = value; }
}
public Guy()
{
}
public void Execute()
{
m_test.Execute();
}
}
public class Speak : IExecutable
{
private string m_test;
private SpeechSynthesizer m_synth;
public string Message
{
get { return m_test; }
set { m_test = value; }
}
public Speak()
{
m_synth = new SpeechSynthesizer();
m_synth.Volume = 50;
m_synth.Rate = 5;
}
public void Execute()
{
m_synth.SpeakAsync(m_test);
}
}
Il ne nous reste plus qu'à créer un loader capable de charger le document XML cité ci-dessus et de l'exécuter. Pour cela rien de plus simple, une simple utilisation de la classe XamlReader suffit pour charger le programme et ensuite l'exécuter :
public class Program
{
static void Main(string[] args)
{
IExecutable executable = XamlReader.Load(File.OpenRead("test.xaml")) as IExecutable;
if (executable != null)
{
executable.Execute();
}
}
}
Vous voilà donc à présent en face de votre premier "langage" déclaratif !
Pour aller plus loin il vous est tout à fait possible de créer un designer graphique afin de générer ce code XML grâce à la classe XamlWriter...
Avec un peu de réflexion et d'abstraction, on se rapproche des fameux DSL introduits par Microsoft avec Visual Studio 2005. Cette idée de créer des Domain Specific Languages capable de représenter sous forme textuelle ou graphique des programmes tout en utilisant son propre vocabulaire (par exemple graphique).
Nous sommes en effet capable de créer un modèle représenté sous forme de document XML et d'exécuter de manière simple ce modèle. A noter qu'il est également possible de définir le comportement de ce modèle grâce aux capacités de LINQ et ainsi traiter le code comme de la donnée mais c'est une autre histoire que je vous détaillerais dans un post dans les prochaines semaines..