| Prise en main du Framework Enterprise Library par Laurent Desmons (1ère Partie) | ||
Dans son encyclopédie, le Journal du Net définit le terme "framework" de la façon suivante : "Littéralement charpente, ossature. En programmation orientée objet, désigne l'infrastructure logicielle qui facilite la conception des applications par l'utilisation de bibliothèques de classes ou de générateurs de programmes."
Les frameworks facilitent le développement en fournissant des services déjà tout préparés et directement réutilisables. Disposer d'un framework d'entreprise est un avantage décisif pour le développement:
Toutefois, le développement d'un framework .NET interne à l'entreprise est une tâche longue, ardue et qui réclame un très gros investissement humain et financier :
Il va sans dire que le retour sur investissement est (très) long à se mettre en place. D'où l'intérêt d'utiliser des frameworks déjà prêts, souples, évolutifs, optimisés et ayant fait ses preuves. Le Framework Enterprise Library (aussi appelé EntLib) est la proposition gratuite et intégrée de Microsoft pour répondre à ce besoin.
Cet article est la 1ère partie d'une série de cinq articles destinés à guider le lecteur pendant la prise en main complète de ce framework. Je vais suivre une approche volontairement synthétique et pragmatique, sur la base d'exemples WinForms standalone simples. J'espère ainsi encourager le lecteur à s'immiscer dans les arcanes de ce framework assez complexe en apparence (la première fois) mais finalement très simple à exploiter au quotidien.
Le sommaire de cette série de cinq articles est le suivant:
Cette première partie est donc une vue d'ensemble dont le sommaire est le suivant :
Passons donc sans plus attendre à la présentation des EntLib.
Le Framework Enterprise Library est l'héritier de ce qui s'appelait anciennement les "Application Blocks". Fruit de la collaboration entre Microsoft et Avanade (sur la base de leur framework interne ACA .NET), il s'agit d'un ensemble de classes regroupées en "Blocks" et livrées gratuitement - avec en prime le code source complet disponible et librement modifiable.
Les blocks constituant les EntLib sont les suivants :
Les principales caractéristiques marquantes des EntLib sont (à mon avis) les suivantes :
Le schéma suivant (tiré du site de Ron Jacobs) synthétise bien les relations entre les différents blocks :

Nous allons maintenant aborder les procédures d'installation des EntLib.
La dernière version des EntLib date de Janvier 2005. On accède aux informations générales depuis le site principal, mais il faut obligatoirement s'enregistrer pour pouvoir télécharger, et notamment disposer d'un passeport .NET valide:

Après l'enregistrement on peut enfin accéder à la page de téléchargement. Une fois l'EXE téléchargé il suffit juste de l'exécuter pour installer les EntLib:

L'installation procède ensuite automatiquement à la compilation complète des sources du framework et à sa configuration. Par défaut le framework est installé dans "C:\Program Files\Microsoft Enterprise Library", avec les sources dans le sous-répertoire "\src" et les DLL et lex EXE dans "\bin".
Il faut également s'enregistrer auprès du Workspace GotDotNet pour disposer des dernières Release, notamment les patchs. Le dernier patch en date est le N° 1475, qui contient les instructions nécessaires :
remplacement du (ou des) fichier(s) source (en l'occurence : "ConfigurationManager.cs")
recompilation complète de la solution "EnterpriseLibrary.sln", puis vérification
copie des fichiers bin générés : dans le menu "Démarrer", retrouver le répertoire "Enterprise Library" et exécuter le script "Copy assemblies to bin directory".
mise à jour des fichiers bin (s'ils existent ailleurs)
recompilations des applications qui utilisent les EntLib
Remarque : cette manipulation anodine est une bonne occasion pour (plus tard) effectuer une petite exploration des arcanes des EntLib, afin de se rendre compte du travail accompli d'une part, et de s'inspirer des bonnes pratiques mises en oeuvre d'autre part.
Les EntLib mettent en oeuvre tout un arsenal d'instrumentation : compteurs de performance, event logs et events WMI. Hormis le fait que cela ralentit naturellement un peu les performances, cela oblige surtout à installer les services nécessaires, car sinon les performances sont encore plus fortement pénalisées, du fait que les EntLib recherchent des composants inexistants et génèrent donc des exceptions et des traitements très coûteux en temps d'exécution.
Je reviendrai sur les performances dans la deuxième partie de cette série d'articles, quand j'évoquerai le "Logging and Instrumentation Block", notamment sur les comparaisons (justifiées ou non) avec le framework Log4Net.
En attendant il suffit d'exécuter le script "InstallServices" qui se trouve dans le menu "Démarrer" et le répertoire "Enterprise Library". Notez bien que cela doit donc être exécuté sur n'importe quelle machine qui doit exécuter les EntLib (donc, les machines de production notamment):

Après avoir installé les EntLib, nous allons procéder à leur mise en oeuvre.
Pendant la mise en oeuvre de l'exemple concret à la fin de cet article nous verrons que l'un des intérêts des EntLib est de pouvoir générer et maintenir un fichier de configuration à l'aide d'une simple IHM.
En pratique cela signifie que cet outil modifie le fichier app.config de façon à y ajouter une section destinée à configurer les différents blocks. Concrètement tout repose par défaut sur l'exploitation d'un fichier appelé dataconfiguration.config, qui doit se trouver dans le même répertoire que le fichier app.config. L'exemple suivant montre comment le fichier app.config est modifié pour spécifier le fichier dataconfiguration.config :

Ce fichier dataconfiguration.config contient les paramètres de configuration déterminés par l'IHM de configuration propre aux EntLib, par exemple les chaînes de connections aux sources de données (voir plus loin avec l'exemple concret).
Le problème est que ce fichier dataconfiguration.config n'est pas pris en compte par Visual Studio .NET, à la différence du fichier app.config qui est systématiquement recopié dans le répertoire de génération du projet (et renommé en tant que fichier de config propre à l'application).
Afin de pouvoir par exemple debugger facilement une application exploitant les EntLib, il est nécessaire de s'assurer que ce fichier dataconfiguration.config se trouve bien dans le même répertoire que le fichier app.config (bin\debug en l'occurrence). Pour cela, en C# le moyen le plus facile consiste à ajouter un événement de génération post-build dans les propriétés du projet qui utilise les EntLib, de façon à copier ce fichier de configuration dans le répertoire de sortie du projet :
copy $(ProjectDir)\dataconfiguration.config $(TargetDir)
Remarque : le problème se pose donc également dans tous les cas où il s'agit de déployer une application basée sur les EntLib, et il ne faut donc pas oublier d'intégrer ce fichier de configuration dans les packages MSI d'installation. En cas d'exploitation d'un environnement de développement automatisé à base de NAnt par exemple, il suffit aussi simplement d'ajouter une tâche supplémentaire qui viendra copier ce fichier au bon endroit. Raison de plus s'il en est de disposer d'un processus d'industrialisation plus ou moins élaboré (basé par exemple sur NAnt ou MSBuild) pour couper court à ce genre de problèmes...
Tout dépend en l'occurrence de la stratégie de déploiement et de maintenance que vous voulez mettre en oeuvre pour gérer les EntLib, mais il est cependant généralement conseillé de :
Il est possible de faire en sorte que l'instrumentation dans les EntLib soit désactivée, pour plusieurs raisons : inadéquation avec l'infrastructure cible, performances impactées... heureusement cette instrumentation est rendue "optionnelle" par l'utilisation de trois paramètres de compilation conditionnelle : USEWMI, USEEVENTLOG et USEPERFORMANCECOUNTER
Par exemple dans le fichier "ApplicationData.cs" on trouve le code suivant :

Pour désactiver l'instrumentation il faut donc:
Les EntLib sont accompagnées d'une batterie de tests unitaires NUnit. Ces tests sont implémentés dans des classes que l'on trouve dans les sous-répertoires "Tests" de chaque projet. Par défaut ces classes de tests ne sont pas compilées : tout dépend en effet d'un paramètre de compilation conditionnelle appelé UNIT_TESTS : s'il est défini dans les propriétés des projets alors les tests unitaires correspondants seront activés.
Ces tests sont évidemment surtout destinés à assurer que les modifications (éventuelles !) apportées au code source initial des EntLib par vos équipes de développement ne provoquent pas de régressions.
Pour activer les tests unitaires il faut donc:
Il est temps maintenant d'aborder un exemple concret de mise en oeuvre des EntLib.
Afin de vous mettre l'eau à la bouche je vous propose un petit tutorial express dont je dois (très!) largement l'inspiration et le contenu au walkthrough proposé par Ron Jacobs sur son site. J'anticipe un peu sur la suite des articles mais l'objectif est bien de reprendre la démarche générale pour mettre en oeuvre les EntLib.
Cet exemple propose une WinForm qui contient un DataGrid qui affiche simplement le contenu d'une table. Les étapes que nous allons suivre sont les suivantes :
Suivons donc ce scénario, qui pourra également nous servir de trame de base pour toute la série d'articles.
Cet exemple (et d'autres) se fonde sur l'exploitation des tables d'une base de données SQL Server fournie avec les QuickStarts des EntLib. Cette base de données s'appelle EntLibQuickStarts; elle s'installe en exécutant le script "Setup QuickStart Database" qui se trouve dans le répertoire "DataAccess Application Block" des "Application QuickStarts" du répertoire "Enterprise Library" du menu Démarrer.

Les tables de cette base de données sont alors accessibles depuis l'explorateur de serveurs dans Visual Studio .NET (nous allons nous intéresser par exemple à la table Products).

Remarque : la version gratuite MSDE 2000 de SQL Server suffit bien entendu pour cet exemple (on peut la télécharger depuis le site officiel).
La création d'un projet WinForms/C# appelé "EntLibIntro" ne devrait normalement pas poser de problème. Il suffit juste d'ajouter un DataGrid nommé "dataGridProducts" et un bouton nommé "buttonFill" dans la forme principale :

Il s'agit maintenant d'ajouter les références nécessaires en allant chercher les DLL dans le répertoire d'installation des EntLib :

Pour rappel, accessoirement, une autre possibilité est de copier les DLL dans le répertoire "C:\Program files\Microsoft Visual Studio .NET 2003\Common7\IDE\Public Assemblies" et de relancer Visual Studio pour faire apparaître les assemblies dans l'onglet .NET de la boîte de dialogue d'ajout d'une référence :

Ensuite, dans le fichier Form1.cs du projet WinForms, il est bien entendu préférable d'ajouter les "using" relatifs aux blocks qu'on souhaite mettre en oeuvre, pour se faciliter la vie :

Nous allons maintenant créer le fichier de configuration utilisé par les blocks des EntLib. Pour cela, il faut d'abord ajouter un fichier app.config à notre projet WinForms en tant que nouvel élément à la solution :

Ensuite il faut :

Pour notre exemple, l'intérêt de cet outil est de pouvoir stocker ici les chaînes de connexion (éventuellement cryptées!) aux bases de données. Pour cela, il suffit de modifier les valeurs de la section "Sql Connection String" en affectant à "database" la valeur "EntLibQuickStarts" et à "server" le nom de la machine sur lequel se trouve la base de données. Le fait d'enregistrer cette configuration provoque deux choses :
Dans notre exemple, on retrouve donc nos paramètres dans le fichier de configuration dataconfiguration.config :

L'outil de configuration permet ainsi uniquement de faciliter la saisie des paramètres dans les différentes sections de ce fichier de configuration propre aux EntLib.
Ensuite, comme indiqué au chapitre précédent, on ajoute l'event de post-build pour copier ce fichier de configuration dataconfiguration.config ainsi produit au même niveau que le fichier app.config:

Cette étape, paradoxalement, est la plus simple de toutes ! En effet les blocks se servent des paramètres issus de la configuration précédente, ce qui permet d'alléger le code à écrire pour les mettre en oeuvre.
Dans l'événement "click" du bouton "buttonFill", nous allons donc écrire le code qui alimente le DataGrid avec le contenu de la table "Products" de la base "EntlibQuickStarts". Le grand principe ici est le même quel que soit le block : on utilise des factories pour créer les objets permettant d'accéder aux fonctionnalités des blocks. Pour le DataAccess Block on utilise la classe DatabaseFactory qui créée une instance de la classe Database par sa méthode CreateDatabase() :

Notez tout de suite que dans notre exemple cette méthode n'a pas de paramètres : la chaîne de connexion est implicitement considérée comme étant définie dans le fichier dataconfiguration.config (on retrouve ici des concepts chers aux amateurs de sécurité...).
L'objet DataBase encapsule toutes les fonctionnalités inhérentes à l'accès aux bases de données, comme par exemple la création d'un DataSet à partir du résultat de l'exécution d'une procédure stockée. L'intérêt ici est d'encapsuler toutes les bonnes pratiques en la matière, et accessoirement de fournir une écriture simplifiée pour la définition des paramètres des procédures stockées, comme le montre l'exemple suivant et la procédure stockée GetProductsByCategory :

Ces deux lignes de code constituent tout ce qui est propre aux EntLib et à leur mise en oeuvre : le reste consiste en effet à lier le DataGrid au DataSet obtenu, code qui ne change pas nos vieilles habitudes et qui se résume aux trois lignes suivantes:

Le résultat est bien entendu conforme à nos attentes :

Au cours de cette introduction, j'ai présenté les grands principes sur lesquels est fondée la Framework Enterprise Library. J'ai ensuite parcouru les procédures d'installation, puis j'ai évoqué le contexte de mise en oeuvre de EntLib, sans oublier quelques petits trucs et un exemple concret pour bien poser les fondements et donner envie d'aller plus loin.
Un effort considérable de simplification et d'homogénéité est ainsi possible, si on prend la peine d'étudier chaque block des EntLib en profondeur, ce que je me propose de faire dans les articles suivants. La deuxième partie entrera ainsi dans le coeur du sujet en disséquant deux blocks fondamentaux: le Configuration Application Block et le Logging and Instrumentation Application Block.
Auteur : Laurent Desmons
Copyright © Mai 2005
Ressources
Le site officiel des EntLibs : Framework Enterprise Library Home
Le site GotDotNet des EntLibs : Workspace GotDotnet
Le site de Ron Jacobs (tutorials, slides, vidéos...) : http://www.ronjacobs.com
Le blog de Tom Hollander, le Project Manager des EntLib : Tom Hollander's Blog
Le site officiel de MSDE 2000 : SQL Server : MSDE 2000 Home
Téléchargez les sources
Solution EntLibIntro : EntLibIntro.zip (102 Ko)