vendredi 29 février 2008

Techdays 2008 : GreenPepper

Retour d'expérience Méthodes agiles

Session présentée par François Beauregard (GreenPepper Software) et Messaoud Oubechou (Octo Technology)

Un constat simple: beaucoup de documents produits à chaque étape de la vie d'un projet par des personnes différentes avec une compréhension différente entre les spécifications générales, fonctionnelles détaillées, techniques détaillées, les test d'intégration, de non regression...
Comment garder ce volume de documents synchronisés dès lors qu'il y a des modifications? Par un seul référentiel documentaire.
Comment lever l'ambiguité des spécifications? Par l'exemple.
Comment synchroniser ces documents avec le code? En testant ces exemples .

Voici quelques points qu'essayent d'adresser les spécifications exécutables, que ce soit Greenpepper ou d'autres outils comme Fitnesse.
Lever l'ambiguité par l'exemple est une pratique d'eXtreme Programming: fournir au développeur les tests fonctionnels plutôt que de les réserver aux testeurs, qu'il s'agisse de tests de non régression, de tests aux limites, ..
Un seul référentiel documentaire, un wiki en l'occurence, est donc utilisable à la fois par des développeurs, des testeurs, des fonctionnels. Pour cela, il faut avoir une syntaxe utilisable par ces profils différents mais également par un framework de tests.

Les tests peuvent être plus complexes que de simples tables, notamment avec des séquences d'actions ou des collections.

Le wiki en tant qu'outils permet de générer de la documentation, de versionner, de faire des exports à mettre dans un controleur de version type subversion.

Ces outils adressent une autre pratique XP au travers l'intégration continue, que j'avais déjà testé avec Fitnesse. Le bénéfice est de pouvoir livrer souvent une version intègre fonctionnellement.

Nous n'avons pas eu le temps d'avoir une démo de GreenPepper pendant la session mais on peut en trouver une sur le site.
Comme on l'a vu, ces outils s'inscrivent dans une démarche agile en focalisant plus spécifiquement sur la couche spécifications et tests fonctionnelles:
Cette approche améliore la collaboration dans l'équipe. Cependant le retour d'expérience des speakers montre qu'un outils de communication est pertinent lorsqu'il y a déjà de la communication au sein de l'équipe sinon il peut au contraire desservir l'équipe.
Les spécifications executables ne supplantent pas les tests unitaires, elles les complètent.

Les méthodes agiles remettent toujours sur le tapis la question de la contractualisation d'un tel mode de fonctionnement: la réponse principale est de ne pas contractualiser un coût mais un mode de fonctionnement puis une enveloppe budgetaire basé sur une nombre de sprints avec des clauses de sortie à chaque livraison. On peut également lire la présentation d'Aubry Conseil sur le mode forfait et l'agilité.

Cette approche permet de partager les risques entre le client et le fournisseur.
Il est important que comprendre que passer sur des méthodes agiles est impactant et doit s'accompagner d'une conduite du changement et doit lui aussi se traiter par étapes.

Et .Net dans tout ça?
Il existe un pluggin GreenPepper pour valider les tests depuis Visual Studio et pour suivre les résultats via un portail SharePoint.

Quelques livres sur le sujet:
user stories applied - Mike Cohn
Fit for developping software - ward cunningham

un autre retour sur insideIt.

dimanche 24 février 2008

Scrum

Un bon livre pour découvrir et surtout comprendre la méthode Scrum. Ce n'est pas le meilleur pour rentrer simplement dans cette méthode agile. Pour la mettre en pratique, je vous conseille un excellent livre blanc de Henrik Kniberg Scrum And Xp From The Trenches de plus de 140 pages. Je l'ai utilisé pour démarrer une équipe Scrum, vraiment très utile. Pour revenir au livre, il apporte une compréhension plus profonde de cette méthode et des valeurs qui lui sont associées. Ken Schwaber, un des auteurs, fait partie des pionniers de Scrum. Il est vraiment intéressant de comprendre pourquoi et comment il est arrivé à mettre en place, il y a déjà plus de douze ans, ses premières équipes Scrum. Et que depuis cette méthode a fait ses preuves sur des projets importants.

vendredi 22 février 2008

Techdays 2008 : Facebook et Popfly

Session Facebook par Thomas Conté


Aujourd'hui avec 13000 applications hébergées sur Facebook, ce réseau social devient le plus grand référentiel d'applications. Créer une application Facebook permet de profiter de l'effêt viral de ce réseau et créer le buzz (46 millions d'utilisateurs actifs quand même).


Mais quel rapport avec .Net?


Facebook pour développeur est une plateforme ouverte. Même s'ils proposent toujours leur grammaire propriétaire FBLM, une sorte de custom HTML, on peut en passant par des iframes appeler n'importe quel site web. Le serveur Facebook fait alors office de proxy et donc votre propre site asp.net.

Pour aller plus loin et interagir avec le backoffice Facebook (récupération d'info, inviter des amis,...) il faut passer par leur API Facebook via du REST, avec certaines limites.
Plutot que d'essayer le FBLM dont la learning curve est importante, plusieurs SDK propose des API Facebook .Net.

FaceBookToolKit par Clarity Consulting hébergé sur CodePlex, sponsorisé par Microsoft (voir le showcase de Microsoft ici). C'est un framework actif avec plus de 300000 pages vues.

Facebook.Net par Nikhil, API de meilleure qualité mais pilotée par une seule personne, donc moins réactive avec quand même 130000 pages vues, toujours hébergé sur CodePlex.

Ce ne sont pas les seuls, toute la liste des framework se trouve sur la page wiki de facebook.

Les API Facebook évoluent souvent, donc votre application peut rapidement ne plus fonctionner. Il est, dans ce contexte, plus intéressant de s'appuyer sur FaceBookToolKit car le framework sera plus synchronisé avec l'API Facebook.

La difficulté de développer avec des API internet est le débuggage: Il faut exposer la machine de développement car Facebook doit y accéder, sinon il faut déployer sur un hébergeur et tracer les buggs. C'est ce que j'ai fait sur mon application de test FaceBook TalentExpo pour mettre en pratique la session.

Facebook permet d'avoir un mode développeur afin de n'exposer une application qu'une fois finalisée.

Puisqu'il va falloir livrer un certain nombre de fois avant d'avoir quelque chose qui tourne, autant se simplifier la vie avec l'add-on Web deployement project.

Les étapes pour créer une application FaceBook sont bien décrites ici. Je vous conseille de télécharger plutôt les nightlybuild que la release car il y a plus d'exemples. Dans tous les cas, il faut récupérer les sources comme nous allons le voir.

Une fois le framework téléchargé, pour faire votre première page Facebook, il suffit de créer une page aspx puis de la faire hériter de CanvasIFramebasePage qui cache toute la plomberie d'authentification et de renseigner les clefs:

public partial class fb_Default : CanvasIFrameBasePage
{
protected void Page_Load(object sender, EventArgs e)
{
base.Api = MyAPIKey;
base.Secret = MyAPISecret;
base.Page_Load(sender, e);
}
}
Et c'est tout.

Pour manipuler des données issues de FaceBook il suffit alors d'appeler des méthodes de l'objet this.FBService, par exemple:

Facebook.Entity.User u = this.FBService.GetUserInfo();
FriendList1.Friends = this.FBService.GetFriends();
Important, pour pouvoir inviter vos amis FaceBook à s'abonner à votre application il faut un peu de manipulation comme décrit ici, que je vais résumer:

1/ ajouter au projet Facebook (d'ou l'interêt de downloader les sources), sous components\FaceBookService.cs, la méthode suivante

public string MultiFriendSelector(Uri actionUri, string markup, string actionText, string excludeList, string requestType, bool isInvite)

(voir la méthode dans le lien précédent). Re-compiler.

2/Dans votre page aspx, faire un hyperlien "add a friend" pointant sur l'URL suivante:

HlAdd.NavigateUrl = this.FBService.MultiFriendSelector(new
Uri("http://apps.facebook.com/VotreAppli/"), "Un texte sympa ici'
fb:req-choice label="Ajoutez Moi!" url="http://www.facebook.com/add.php?apikey=VotreClef">", "Ajoutez Moi!", "", "request", true);

Pas possible d'utiliser les méthodes d'extension pour ne pas avoir à recompiler les sources car on appelle la méthode GenerateSignature de l'API qui est internal.

Attention si vous utilisez de l'Ajax, ça ne marche que si votre serveur web est en FK3.5, ce qui ne court pas encore les rues chez les hébergeurs... J'ai pu vérifier que ça ne marchait pas....

A chaque appel de méthode Facebook un roundtrip est effectué entre votre serveur et celui de Facebook. Il faut donc mieux éviter des appels dans des boucles et utiliser les méthodes par batchs.

Publier une story (Feeds)

J'ai voulu utiliser la méthode

PublishTemplatizedAction
Afin d'afficher des mini feeds que je n'ai pas testé car la fonction semble avoir été modifiée récemment côté FaceBook, lire ici. L'idée est de créer des chaînes de caractères templatées, exemple:
{actor} s'est abonné à {code} ...

Pour mettre à jour le profil de l'utilisateur, il faut cette fois faire du code FBLM via la méthode

SetFBML

Session PopFly par christophe Lauer


Popfly un éditeur en ligne de Mashup web pour les non développeurs.

La création de bloc peut se faire par copier/coller pour utiliser des modèles existants, comparer à netvibes ou il était difficile de trouver des exemples de code (ca a peut être changé depuis un an).
Les mashup peuvent être créés graphiquement, c'est très intuitif et assez ludique. Ils sont batis sur des blocs pré existants (basés sur les API ou flux rss) ou sur des customs blocs (descripteur XML et fichier Javascript contenant la logique de traitement). Par contre, pour mettre au point ces fichiers javascript un seul moyen le console.write!

Pour aller plus loin un bon article en français pour créer ses propres blocs de services et le blog de Christophe. Sur l'article MSDN, on trouve les sources de la démo en ligne.

Les blocs peuvent être créés en ligne mais également via Visual Studio 2008 grâce au plugin Popfly Explorer.

Tout c'est bien jolie mais un exemple!

J'ai d'abord essayé la fonctionnalité assez séduisante de créer un bloc à partir d'un fichier wsdl. J'ai mis le fichier en place sur un des fichiers wsdl de TalentExpo. Le bloc a bien été créé par contre la mise en place du mashup ne s'est pas bien passée car l'appel du service web ne ramène rien via le bloc. J'ai abandonné la création au bout d'une heure de tests.

Par contre, j'ai créé un mashup à base d'un de mes flux Rss et d'un carousel assez simplement. Le rendu est sympa mais avec un problème de taille: pour voir ce mashup correctement il faut soit IE7 soit FireFox2.0. Avec mon IE6 la page plante. C'est assez dommage car ils proposent une version iFrames pour mettre dans un blog. Ils travaillent sur ce problème de compatibilité.

Du coup, j'ai fait le même Mashup avec un fader d'images et là ça marche (sauf sur blogger... les iframes ne passent pas, du coup je ne l'ai pas affiché).

Cet outil est plein de promesses car après la prise en main, c'est assez simple!!

Un autre retour d'InsideIt et une présentation powerpoint ici.

mardi 19 février 2008

Techdays 2008 : Nom de code Rosario

Nom de code Rosario
Session présentée par Florent Santin et Mathieu Szablowski de Winwise

Toutes les infos pour télécharger la dernière CTP du futur Visual Studio Team System sur le blog de Florent.

Les versions Team Architecte, Team Developper, Team Tester et TFS server ont été présenté pendant cette session.

Team architecte

Arrivée des software factories via DSL et de nouveaux designers dont les diagrammes de séquence.

Team Developper

Améliorations sur le débugger avec un debug history (stack des appels avec également les exceptions qui ont été catchées que l'on peut consulter après debuggage) et un debugger stand alone: version packagée du débugger et de l'application à mettre sur une machine ne possédant pas Visual Studio: vsdebug.exe: On peut débugger l'application, ouvrir les sources, mettre des points d'arrêts... Imparrable pour tester sur des environnements différents.

L'analyse de code a été également améliorée avec la définition de rules set selon la phase de développement : on n'appliquera pas forcément les mêmes règles de développement sur la version Debug que sur la version Release, par exemple. Il y a des builtin rules set mais on peut en faire des customs.

L'amélioration des tests unitaires porte essentiellement sur la productivité mais est très efficace: lorsqu'on modifie un ou plusieurs fichiers, tous les tests unitaires ne sont pas impactés: VSTS propose donc deux vues Not Impacted et Recommanded qui liste les tests unitaires a redérouler (Recommanded) car potentiellement impactés par les dernières modifications.

Team Tester

Là encore un gros effort pour réunir testeurs et développeurs en proposant un outils CAMANO connecté à TFS pour le testeur qui organise sa campagne de tests sans avoir Visual Studio sur son poste. Lorsqu'un test est déroulé via CAMANO, un screen cast est enregistré et attaché au test. Lorsque le test échoue, le développeur a la possibilité de visionner la vidéo du test. Fini l'excuse de la non reproductabilité des buggs.

lundi 18 février 2008

Techdays 2008 : ADO.Net Sync Services

Solutions Online/OffLine avec ADO.Net Sync Services
Session présentée par
Sébastien Pertus de Bewise

Sébastien est très interessant, connait très bien son sujet, session très agréable et instructive.
Successeur du Remote Data Access, ce framework, développé sur MSF, permet la synchronisation de données, et peut se décliner en plusieurs thèmes : Cache local/Mode Deconnecté/Synchronisation/Collaboration.

On trouve la V2 du framework en CTP ici.

Côté Serveur, on a un provider ADO.NET (donc potentiellement de l'Oracle, SQL Serveur, MySQL, ...)
Côté Client, on a SQL Server CE ou d'autre DB embarquée
Sync Designer est un concepteur graphique, n'est pas obligatoire mais permet, quand on travaille avec SqlServeur, de gagner en productivité.

Cache local

Cela se fait simplement en récupérant les data sur une base de data locale (Local Database Cache), en fait un SQL Server Compact 3.5 et gère le cache et la synchronisation des données.

Synchronisation

L'idée est de remplacer le classique DataAdapter par un SyncAdapter. Il comporte les mêmes méthodes que le DataAdapter plus des méthodes de commandes incrémentales et de gestion de conflit. Voir l'article de sébastien pour le détail.
Le travail est déporté sur une base locale, le SyncAdapter faisant la liaison avec le DataBase server.
SyncDesigner génère le code pour SQL Server 2000/2005. On peut se servir du code généré et l'adapter pour d'autres providers. Sync Designer ne sait pas gérer les relations entre entités, il faut le faire directement dans le xsd.

Au premier appel client, le serveur génère une ancre (un TimeStamp ou un DateTime) qu'il envoit au client. Puis la synchronisation s'appuie de part et d'autre à cette ancre.

Par défaut la synchronisation ne se fait que du serveur vers le client. Pour avoir du bidirectionnel il suffit de rajouter une ligne de code par table à synchroniser

SqlSyncAdapterBuilder builder = new SqlSyncAdapterBuilder();
builder.SyncDirection = SyncDirection.Bidirectional;

Personnalisation

On peut se passer du Sync Designer et écrire tout à la main. Comme par exemple créer la base locale à la volée,... Tout est retranscrit ici.

Sync Services & WCF

Une info en passant wcfsvchost permet de hoster les services WCF sans passer un site web pour l'hébergement.
Sync Services s'appuie sur une archicture WCF, le Sync Agent côté client prenant comme paramètre du constructeur le proxy du service XCF.

SQL Serveur 2008 & ChangeTracking

Pour permettre la synchronisation de bases, il faut mettre un peu de plomberie dedans via le wizard de Visual Studio: des triggers, des tables tombstone. Ou de s'en affranchir en utilisant le change tracking de la nouvelle version de SQL Serveur 2008.
Des benchmarks ont été fait sur le change tracking et l'impact en performance semble de même ordre de grandeur que l'ajout d'un index secondaire et donc moins que des triggers.

On également peut lire une introduction par Microsoft ici et un webcast sur Channel9.

Techdays 2008 : DDD

Domain Driven Design

Session présentée par sami jabert de DNG Consulting dans le carde du symposium DNG

Sami, créateur de DotNetGuru, s'essaye à partager sa perception du DDD dont on peut trouver un livre résumé (de 100 pages quand même) du livre référence d'Eric Evans sur le sujet.

Sa session assez pragmatique est intéressante car il tente d'apporter son point de vue sur une approche complexe et pour laquelle il n'adhère pas à 100% mais qui fait son chemin. Sami s'en est expliqué ici.

InsideIt a fait un bon retour de la présentation sans polémique de cette partie et on retrouve le slideshow de la présentation .

Je voudrais quand même faire un focus sur la seconde partie de la présentation dédiée à la couche présentation.
Un constat d'abord, beaucoup de temps passé sur la couche présentation pour la partie contrôle de surface, le binding, la conversion de format et les erreurs (80% de temps en moyenne).
Le contrôle de surface peut être porté par la couche domaine du DDD en s'appuyant sur des customs attributs et les formats par des converter.

Exemples de customs attributes du Validation Block:

[IgnoreNulls]
[ValidatorComposition(CompositionType.Or, Ruleset = "RuleSetA", MessageTemplate = "Address line 2 must be empty, or between 5 and 50 characters")]
[StringLengthValidator(0, Ruleset = "RuleSetA")]
[RegexValidator(@"\d{5}(-\d{4})?", MessageTemplate="\"{0}\" is not a valid US zip code", Ruleset = "RuleSetA")]
[RangeValidator(0, RangeBoundaryType.Inclusive, 1000000, RangeBoundaryType.Inclusive, Ruleset = "RuleSetA", MessageTemplate="Rewards points cannot exceed 1,000,000")]

Cette approche est relativement intéressante car elle permet de factoriser ces contrôles sur l'objet métier et d'automatiser le best practice de redondance de ces contrôles (côté client pour l'expérience utilisateur, côté serveur pour valider la règle).

Elle nécessite aujourd'hui un peu de développement autour d'un mini framework ou d'intégrer le Validation Application Block de pattern & practices (voir le webcast). Et promettent un gain de productivité.
Un petit mot également sur la perte de temps sur le binding mais sur lequel j'ai un peu de mal à adhérer car le binding asp.net permet déjà d'aller assez loin.

Le mot de la fin, les technos .Net avec WCF pour les services métiers, Linq pour la DAL, WPF pour l'autobinding promettent aujourd'hui de faire du RAD clean plutôt que quick & dirty.

dimanche 17 février 2008

Techdays 2008 : Linq avancée

Linq avancée
Une session présentée par Mitsuru furuta

Une session pas simple sur LinqToObject avec des méthodes à la volée, de la métaprogrammation, de l'extension de méthodes et un peu d'architecture.

Méthodes à la volée

L'idée de cette présentation est de créer des méthodes à la volée et de les exécuter.

On commence simplement par une expression lambda sur un délégué multipliant un entier par 2. L'expression lambda donne un arbre d'expression que l'on compile en du code exécutable. Il suffit ensuite d'appeler la méthode avec un paramètre:

Expression<func<int,int>> MultiplyBy2 = (paramToMultiply) => 2 * paramToMultiply;
var FuncMultiplyBy2 = MultiplyBy2.Compile();
string result1 = FuncMultiplyBy2(12).ToString(); ///return 24

On peut écrire cette même expression directement en expression lambda, sans passer par un délégué:


var param = Expression.Parameter(typeof(int),"param1");
Expression mult = Expression.Multiply(
param,
Expression.Constant(2, typeof(int)));
var lambda = Expression.Lambda<func<int,int>>(mult, param);
var f = (Func<int,int>)lambda.Compile();
string resutl = f(12).ToString(); // return 24

IEnumerable/IQueryable

Quelle différence fondamentale entre IEnumarable et IQueryable?
Ils servent à délimiter ce qui est du code ou de l'expression.

IQueryable créé de l'expression plutôt que du code. Cette expression est analysable et modifiable (interception, factoring de code) et peut aussi être évaluée. On peut l'appeler avec

.AsQueryable()

IEnumerable est un reader. Il renvoit donc un curseur sur les enregistrements. On peut l'appeler par

.AsEnumerable()

On verra une conséquence de cela dans la partie Architecture.

MetaProgrammation

Pour faire de la métaprogrammation, on peut s'en sortir avec de la réflexion, ce qui n'est pas toujours conseillé car cela ajoute un overhead.
L'idée est ici de passer par une expression et d'intercepter la navigation dans l'arbre d'expression (lire l'article Implémenter un visiteur de l'arborescence de l'expression) afin de remplacer dans l'arbre le bout de code qui nous intéresse en surchargeant ExpressionVisitor (lire l'article modifier une arborescence d'expression).

Les expressions permettent donc une première approche de la métaprogrammation (et donc un premier niveau de dynamicité) mais qui a ses limites (pas de créations d'instances,...).

Tri de DataGrid dynamique

Trier des DataGrid sur des colonnes que l'on ne connait pas a priori (au niveau objet) mais dont on a le nom (chaine de caractère via le ColumnHeaderMouseClick) n'est pas simple avec du databinding sur des providers Linq. En effet, il faut ajouter à la requête un orderby sur une propriété:

var myProcess = from a in Process.GetProcesses()
orderby a.ProcessName descending
select new { a.ProcessName, a.ProcessorAffinity };

Une première manière de faire consiste à récupérer la propriété par reflexion puis en utilisant un MemberExpression:

Type process = typeof(Process);
PropertyInfo prop = process.GetProperty("ProcessName");
Expression exp = Expression.Parameter(process,"Process");
MemberExpression memb = Expression.Property(exp, prop);
var myProcess = from a in Process.GetProcesses()
orderby memb descending
select new { a.ProcessName, a.ProcessorAffinity };

Ou sinon on peut étendre l'API avec des méthodes d'expressions basées sur des chaines de caractères avec Dynamic Query Library.

Architecture

Question: Dans la couche métier, faut-il renvoyer des List<> ou des IEnumerable?
IEnumerable, on l'a vue, est un reader. Il ne créé donc pas de collection. On renvoyant à chaque couche des List<>, on créé autant de collections intermédiaires qui n'ont pas de plus value si ce n'est faire office de passe-plat.
En exposant un IEnumarable, on passe un curseur au travers des couches ce qui produit un gain en consommation mémoire par rapport aux collections. La limitation est le manque d'accès aux propriétés par index xxx.Prop[i] mais la plupart du temps on utilise les boucle while ou foreach.

IQueryable/IEnumarable et enjeux de sécurité:
1er cas:

UIMétierData
Expose IQueryable
Var q = from x in table...
from c in table
where c.StartWith()
=> la requête est modifiée par une demande
de la couche
UI

Dans ce cas simple, on n'a pas d'isolation entre les couches


2ème cas

UIMétierData
Expose IEnumerable
Var q = from x in table...
from c in table
where c.StartWith()
=> filtre des réponses dans la couche métier=> la requete n'est pas modifiée
from c in (IQueryable)table
where c.StartWith()
=> la requete est modifiée par une demande
de la couche UI

Un Cast côté UI permet de modifier la requête directement dans la couche Data. On a toujours un problème de sécurité entre couches.

3ème Cas

UIMétierData
Expose IEnumerable
Var q = from x in table.AsEnumerable()...
from c in table
where c.StartWith()
=> filtre des réponses dans la couche métier=> la requête n'est pas modifiée

Cette fois en exposant IEnumerable avec .AsEnumerable() l'expression ne peut pas être castée en IQueryable. On gagne donc en performance sans perdre en sécurité.

Interception de requête

Le IQueryable étant une expression, on peut l'intercepter afin de composer une nouvelle requête on ajoutant simplement une clause where par exemple dans un but de factorisation de code.

On peut trouver un article complet sur linq ici par Thomas Lebrun.

samedi 16 février 2008

Techdays 2008: Nom de code VLinq

VLinq, nom de code pour Visual Linq

présentée par Simon Ferquel et Mitsuru Furuta

On peut retrouver des webcasts sur cet outils ici et ici.

Visual linq est un constructeur de requêtes pour LinqToSql développé en France par deux stagiaires et piloté par Mitsuru Furuta. Le résultat est plutôt surprenant par l'ergonomie du builder.
On ne le trouve pas encore en ligne, la release sera annoncée sur le blog de Mitsuru.

Une info tout de même, le builder devrait être livré avec les sources, un vrai plus pour les éditeurs d'add-in pour Visual Studio...

C'est un designer éditable basé sur WPF avec un choix de persistance de type XAML. Le builder permet un preview du résultat de la requête, du code SQL généré et du code C# ou VB généré.
Voir le code SQL généré est très important pour les requêtes complexes pour vérifier la pertinence de celles-ci et pouvoir décider facilement de basculer sur des procédures stockées.

Les requêtes générées sont encapsulées dans des methodes statiques prenant le DataContext comme paramètre. Elles peuvent être paramétrées, le prototype de la méthode se contruit en même temps.

Trick : Avec linqToSql, lorsqu'un lien existe entre deux tables pas besoin d'ecrire la jointure dans linq, elle est fait automatiquement.

Le builder construit les jointures, y compris les left outer join qui ne sont pas simples lorsqu'elles sont explicites en linq, par exemple:

var q =
from s in db.Suppliers
join c in db.Customers on s.City equals
c.City into sc
from x in sc.DefaultIfEmpty()
select new {
Supplier =
s.CompanyName,
Customer = x.CompanyName,
City = x.City
};

Les requêtes imbriquées sont également supportées avec une ergonomie top grâce à WPF.

Chaque requête porte les propriétés suivantes

  • autopagination => créer deux méthodes surchargées dont une pour la pagination en ajoutant simplement

.Skip(PageIndex*PageSize)

.Take(PageSize)

  • Compiled: pré compile la requête dans le cache et créé des fonctions déléguées
  • Distinct

Custom query

Si l'on veut ajouter des requêtes non construites par le designer au querybag pour bénéficier de son interface et de la validation de requête, il suffit de rajouter un simple attribut:

[Browsable(true)]

Validation de requête

Linq permet de s'assurer à la compilation que la requête est bonne d'un point de vue statique et par rapport au mapping décrit dans le DataContext. Si celui-ci n'est plus synchronisé à la base de donnée, la requête se plantera à l'exécution. Ils proposent donc de valider ces requêtes par batch testing, très simplement.

Un outil prometteur de productivité et/ou d'appropriation de la syntaxe Linq, dommage qu'il n'y ait pas encore de version beta pour le tester.

Techdays 2008: Nom de code Volta

Volta session présentée par Erik Meijer himself


La webcast de cette session n'est pas encore en ligne, on peut voir une vidéo en attendant ici (Part I) et ici (Part II). Pour suivre l'actualité de ce framework, on peut lire le blog de l'équipe Volta.

Résumé de la session

S'appuyant sur sa propre expérience et en l'étayant avec le livre The Change Function: Why Some Technologies Take Off and Others Crash and Burn, Erik introduit le concept de Volta par sa facilité d'adoption : Minimiser la learning curve en réutilisant au maximum l'existant.

Bon ok, mais qu'est-ce que c'est Volta?

Des outils pour le développeur pour décider a posteriori de la séparation logiques des couches, mais également du mode synchrone/asynchrone, d'un mode Ajax ou classique.

Les exemples de la session sont assez similaires au starter du site Volta.

Commencez par créer une application Volta après avoir installé la version beta.

Notez une première différence avec une application classique, si vous dépliez la page .cs par défaut, elle contient une page Html.

Petite digression pour comprendre la structure d'une fichier Volta: Les classes héritent de la classe Page qui a un getter sur un Document qui donne accès aux éléments DOM de la page HTML:

public abstract class
Page{

protected Page();

public Document Document { get; }

public Window Window { get; }
}

Grace à cette propriété, on accède donc directement aux objets de la page Html:

Button button2 = Document.GetById<>("Button1");
Button button1 = (Button)Document["Button1"];
Comme nous allons le voir, Volta, par soucis de simplicité, fonctionne principalement par attribut, ce qui est une tendance générale. Ainsi pour spécifier la page de départ et le fichier css par exemple, on écrit:
[assembly: StartPage("Page.html")]
[assembly: VoltaFile("favicon.ico")]
[assembly: VoltaFile("main.css")]
public partial class VoltaPage1 : Page

Une fois terminée l'application appelant une page Html et une classe business, on passe en mode Client/Serveur en faisant tourner l'application non plus dans le process du navigateur mais dans celui du WebServer Volta, et ce, juste en posant un attribut sur la classe business:

[RunAtOrigin()]
Pour cela il faut avoir coché la case Enable Volta tier splitter dans les propriétés du projet, onglet Volta et ajouté

using Microsoft.LiveLabs.Volta.MultiTier;

En ouvrant le Volta WebServer, on peut tracer les logs. Pour le premier appel d'une simple page Html, plus d'une centaine de request Get... Erik nous a bien prévenu qu'il manque une phase d'optimisation...

Cette approche me rappelle un peu Mozilla Prism pour transformer le web en application.

Second Exemple

Passer d'un mode d'appel synchrone à un mode asynchrone sans utiliser le pattern classique Begin/End Invoke avec l'attribut

[Async()]
sur la méthode à appeler, puis on remplace l'appel en mode synchrone

greetingElement.InnerText = greeter.Greet(name);

en mode asynchrone :

greeter.Greet(name, message => { greetingElement.InnerText = message; });

Cependant, Volta étant encore en béta, le pattern de gestion des exceptions en mode asynchrone n'est pas encore clair.

Trick Asynchrone: dans le cas de demandes asynchrones successives, les réponses peuvent être incohérentes si l'une d'elles a été plus longue. Erik utilise un séquenceur dans lequel il timestamp les demandes et vérifie dans le callback de l'asynchrone si la réponse est celle de la dernière demande, sinon elle est supprimée.

Autre exemple, passer d'un mode compilé à un mode javascript: pas de problème, le javascript est produit par le framework. Ce tour de force est réalisé en plaçant une couche intermédiaire entre le code source et l'IL, le MSIL Volta qui traite les attributs et fourni l'IL correspondant.

Passer à l'ajax, c'est faire une application single tier avec un peu de refactoring, et donc d'abord ce concentrer sur le besoin métier avant de contruire une architecture répondant à un seul besoin technique.

Exemple d'un appel linq sur des tables clusters

Linq for MapReduce. On peut compiler linq pour des appels en parallèles vers des bases partitionnées. Je n'ai pas trouvé d'informations sur ce sujet.

Mais allons encore plus loin dans le 3-tier splitting façon Volta:

Pourquoi mettre la définition d'une fonction SQL dans la base quand on peut la mettre dans notre assembly .Net avec un simple attribut

[Server.SqlFunction()]

Le custom attribut s'occupe du reste!!
Et encore

[import()]

pour accéder au javascript via .Net et

[Export()]

pour exposer .Net au javascript.
La version est en beta mais on parle déjà de publier des services web aussi simplement que

[PublishAsService()]

Un autre avantage: le profiling end-to-end de l'application par une simple case à cocher des propriétés du projet "Enable End-to-end profiling" et tout ça en s'appuyant sur Microsoft service trace viewer de WCF, qui d'ailleurs s'execute automatiquement.

Conclusion

Erik est un personnage haut en couleur (tout comme sa chemise) passionnant (co-créateur de Linq) et porteur d'un projet intéressant par son approche: repousser la décision de l'architecture ou plutot partir sur une architecture simple et pouvoir la faire évoluer selon les besoins par simples attributs, et surtout ré utiliser l'existant, mais qui pose de sérieuses questions d'architecture.

Pour lire un autre point de vue sur la session sur le blog d'InsideIt.

vendredi 15 février 2008

Techdays 2008: Nom de code Astoria

Astoria: nom de code d'ADO.Net Data Services
Présentée par Mitsuru furuta et pierre lagarde

La webcast de cette session n'est pas encore disponible, c'est dommage car Mitsuru est très interessant.

Ce framework fait partie d'asp.net futures disponible en CTP1. La release est prévue pour mi 2008. Lire le blog de l'Astoria Team pour suivre leur actualité.

Résumé de la session

L'idée de départ est d'exposer sur le web des sources de données requêtables au lieu d'exposer un nombre important de services web.
La réponse technique est de distribuer des expressions Linq par http en s'appuyant sur une architecture REST, rien que ça. Comme on va le voir, cela suppose de pouvoir faire du select/insert/update/delete via une expression Linq dans l'url sur des sources de données...

Côté serveur, Astoria utilise un service WCF générique se branchant sur l'interface IQueryable et s'appuie sur le framework Linq. Les sources de données peuvent donc être de tout type, il suffit d'utiliser le bon provider (LinqToObject, LinqToXml, LinqToSql, LinqToEntities).

Le service implémente IRequestHandler, qui porte les attributs WCF:

[ServiceContract]
public interface
IRequestHandler
{
[WebInvoke(UriTemplate = "*", Method =
"*")]
[OperationContract]
Message ProcessRequestForMessage(Stream
messageBody);
}

Pour le transfert, on s'appuie sur une architecture REST avec les formats ATOM et JSON. JSon est natif depuis le FK3.5 pour WCF.


Côté client, c'est la fête car on s'adresse aussi bien au client léger via le navigateur qu'au client riche type silverlight, WPF, winforms.


Astoria s'occupe de générer les classes proxies pour accéder au service, de même que lorsque l'on ajoute une référence à un web service. Dans ce cas, on peut manipuler la source de données côté client exactement de la même manière que côté serveur via du "LinqToHttp" avec un WebDataContext (au lieu du DataContext de linqtosql ou de l'ObjectContext d'entity framework). On code de la même manière dans les deux couches.

Le paramètre du service générique, pour pouvoir répondre à toutes les requêtes possibles sur un modèle donnée, prend comme paramètre l'expression Linq, qui est donc sérialisée/désérialisée.

L'architecture REST permet de faire du CRUD selon les types de requêtes HTTP:

POSTCreate/Update/Delete
GETRead
PUTCreate/Update
DELETEDelete


On peut appeler le service par javascript, une bibliothèque est fournie afin de simplifer la vie du développeur. Les appels cross domain sont interdits par javascript, le service astoria doit alors être exposé dans le même domaine pour que ça marche.

L'appel peut également être fait via le code behind.


Pour des questions de sécurité, on a un mécanisme d'interception des requêtes côté serveur par attribut :

[QueryInterceptor("Products")]

L'idée est d'intercepter l'expression linq (donc non encore exécutée côté source de données puisqu'on échange du IQueryable) et de la modifier pour filtrer les données sensibles, par exemple en implémentant du Membership. Cette notion d'interception est reprise dans la session "linq avancée" mais sous un angle de factorisation de code.


En plus du schéma, on peut également exposer des méthodes métiers simplement avec l'attribut:

[WebGet()]

tant que la méthode retourne du IQueryable. On peut donc appeler des méthodes métier par URL.
Ou encore exposer des types customs qui ne sont pas forcément persistés avec des requêtes s'appuyant sur LinqToObject et en les exposant avec la méthode AsQueryable(). La démo montrait comment exposer les process actifs de la machine.

Pour modifier les données, il faut implémenter l'interface IUpdatable.

La version CTP a encore quelques limites, pas de Group By par exemple, mais l'équipe y travaille.


La mise en pratique


Lorsque l'on installe la CTP, chose amusante, on le retrouve sous le répertoire

Microsoft ASP.NET 3.5
Extensions\MicrosoftAjaxLibrary\System.Web.Extensions\3.6.0.0

On est donc en présence du framework 3.6 et non 3.5 donc attention dans le web.config à pointer sur les bonnes versions de l'assembly System.Web.Extensions.

Après avoir installé la CTP, on peut se laisser guider par le starter du site (lire "ADO.Net Data Service" au lieu de "web data service").

Bien que tout repose sur du WCF, il n'est pas nécessaire de spécifier le paramétrage WCF dans le web.config car par défaut il prend un endpoint de binding HTTP.

Pour un premier test, exposez toutes les sources en utilisant "*":

public static void InitializeService(IWebDataServiceConfiguration
config)
{
config.SetResourceContainerAccessRule("*",
ResourceContainerRights.AllRead);

}

Appelez enfin l'URL de la classe .svc crée et ensuite allez lire ce document pour des exemples de syntaxe de requêtage.

vendredi 8 février 2008

Techdays 2008

Les Techdays 2008 de Microsoft approchent.
Pour ma part, j'y serais les trois jours.
Au menu:
Domain Driven Design, Volta, Astoria, Linq (bien sur), Open Source .Net, ADO Sync, Popfly, Rosario, GreenPaper, Facebook, MySpace et IIS7.0.

J'essayerais de faire Je prépare des notes sur les sessions auxquelles j'ai participé.

Premier retour de mes Techdays, ma certification Microsoft Technical Specialist.

Pistes pour migrer sous Visual Studio 2008 - Part II

Suite de ma première note sur ce thème,

Part II : Utiliser du code SQL existant

La migration d'un parc applicatif vers du .Net peut se traduire pour certaines applications stratégiques par une réécriture complète de l'Ihm et de la couche métier.
Dans ce cas, bien réutiliser le code SQL (procédures stockées, fonctions), qui peut porter le coeur de métier, peut devenir un enjeux stratégique.

La réponse peut se trouver encore du côté de LinqToSql ou de l'entity Framework même si celui-ci n'est encore aussi abouti (Beta 3) et dans lequel on retrouve moins de possibilités aujourd'hui (tables, vues, proc).

Ces framework permettent un wrapping déclaratif entre l'applicatif (qui génère une fonction typée avec un nom anglais) et du code sql (une procédure stockée par exemple avec un nom français). Le développeur a ainsi accès à une méthode métier sans avoir à connaitre son implémentation SQL. Le mapping est alors fait dans la phase de conception avec le modeleur graphique.
Il ne s'agit pas ici de savoir s'il est plus intéressant d'avoir une procédure stockée ou bien une requête linq, on peut lire la note suivante sur ce sujet Maximilian Beller's Blog: Performance comparison between Linq, NHibernate and ADO.NET / Stored Procedures mais bien de réutiliser un existant.

L'idée est encore de bénéficier des apports d'un ORM sans s'y investir lourdement dans des contextes particuliers ou l'on a un existant à gérer.

Laurent Morisseau, auteur de ce blog, pour me contacter