Partie 1 - Concepts et technologies▲
Dans cette première partie de la série je vais me concentrer sur certains projets open source dans « Patterns & Practices » de Microsoft et d'autres technologies qui sont disponibles et peuvent nous aider à accomplir notre objectif.
Nous avons d'abord Prism (« Composite Application Guidance for WPF et Silverlight »). Prism est composé d'une orientation et d'un ensemble de bibliothèques qui sont conçus pour vous aider à créer plus facilement des applications WPF et Silverlight modulaires. Il possède également des composants intégrés qui vous permettent de tirer profit de certains « patterns » connus tels que MVVM, l'agrégateur d'événements et l'injection de dépendances. Il en existe d'autres, mais je vais me concentrer sur ces trois, car je les trouve plus utiles.
Prism s'applique au développement client. Je pense que la meilleure caractéristique qu'offre Prism est la possibilité de spécifier vos modules applicatifs (XAP dans Silverlight) en tant que catalogue et de les charger à la demande. Nous allons explorer ceci en détail dans d'autres parties de cette série lorsque nous créerons un catalogue de modules à utiliser dans l'application.
L'injection de dépendances (un usage spécifique de la notion d'inversion de contrôle) est une technique de choix pour construire des applications à couplage lâche, car il fournit des moyens de gérer les dépendances entre les objets. Il vous aide à construire du code testable, car vous pouvez facilement changer les implémentations concrètes desquelles vos objets dépendent. Prism est conçu en utilisant ce principe de conception et il utilise le conteneur Unity, qui implémente la technique d'injection de dépendances. Prism vous permet également d'utiliser d'autres conteneurs d'injection de dépendances, mais je vais me concentrer sur Unity, car je n'ai pas suffisamment d'expérience avec les autres.
Ce « pattern » peut être appliqué tant dans le développement client que serveur.
Je n'ai pas trouvé d'illustration bonne et simple à propos de l'injection de dépendances, je vais donc faire le lien vers cet article où j'ai utilisé cette technique dans un service WCF (OrderService) qui a utilisé un IOrderRepository implémenté par la classe OrderRepository dont les dépendances étaient injectées dans son constructeur.
Le « pattern » MVVM est en train de devenir l'alpha et l'oméga lorsqu'il s'agit de développement d'applications WPF et Silverlight. Il vous aide à séparer les aspects lors de la conception de votre couche de présentation et si elle est bien pensée, vous pouvez créer un bel ensemble de code réutilisable pour votre application et même le réutiliser pour d'autres applications.
Avec MVVM vous considérez essentiellement votre vue comme un ensemble de classes et de propriétés et non comme un ensemble de contrôles d'interface utilisateur. Cela vous permet de facilement changer votre interface utilisateur tout en conservant la même logique à laquelle elle est liée, et en même temps permet la testabilité. De plus, cela vous permet de réutiliser une partie de la logique d'interface utilisateur dans beaucoup de vues avec moins d'effort. Ce « pattern » est appliqué au développement client.
Le « pattern » Event Aggregator vous permet de construire votre application avec une architecture orientée événements où les composants communiquent entre eux de manière découplée. Il fournit une manière de publier et de s'abonner à des événements sans savoir qui s'abonne ou qui publie. La seule chose que vous devez savoir est l'événement que vous publiez ou auquel vous vous abonnez et comment réagir à cet événement. D'habitude, les modules ne dépendent pas les uns des autres et utiliser des événements comme contrats afin de communiquer entre eux est une bonne approche.
Nous allons maintenant nous concentrer sur le développement côté serveur.
Pour la communication client-serveur dans Silverlight, il est recommandé et imposé d'utiliser les services Web. Puisque nous construisons des applications métier il est logique d'utiliser des services qui sont bons pour traiter des données. Les services WCF sont certes bons, mais sont-ils idéaux ? Quel est le coût du maintien d'une couche de service complète qui nous permet d'exposer les opérations CRUD sur nos données et nous fournit également la capacité d'effectuer d'autres requêtes (telles qu'obtenir les produits par productType) ou d'autres opérations métier ? Combien de fois avons-nous fait cela ? Et combien de fois avons-nous fait cela pour différentes applications ? Qu'en est-il de la validation des données côté serveur et client ? Qu'en est-il de la génération de proxy ? Qu'en est-il de la quantité de données envoyées sur le réseau juste pour changer une valeur DateTime sur la base de données ?
Nous savons tous que le code généré par Visual Studio est terriblement laid et que le maintien des agents de service complets côté client peut être problématique, parce que vous avez d'habitude besoin de le garder synchronisé avec votre contrat de service. Dans Silverlight, il est un peu plus compliqué de partager un assembly avec des contrats de services et de données qu'en WPF, en raison d'incompatibilités de type. Aussi, d'habitude nous aimons que nos contrats de données côté client implémentent INotifyPropertyChanged et utilisent des ObservableCollections de manière à tirer profit de la liaison de données, mais du côté serveur on ne se soucie pas vraiment de ça.
WCF RIA Services vise à résoudre tous ces problèmes et bien d'autres. Je vais laisser tomber la partie « toutes les choses que peuvent faire les RIA Services » et vous diriger au bon endroit si vous ne le savez toujours pas. Les fonctionnalités les plus importantes que nous explorerons sont la composition des requêtes, la validation des données, le suivi des modifications, l'unité de travail, entre autres.
J'ai utilisé RIA Services pendant les sept derniers mois et une chose que j'ai trouvée très utile est que la manière dont vous communiquez soit avec le serveur soit avec le modèle (du côté client) est par le biais d'une API très bien définie, ce qui rend facile la création de code très générique qui peut être utilisé pour créer des viewmodels réutilisables. C'est particulièrement utile lorsque vous avez plusieurs personnes travaillant sur le même projet et vous voulez assurer que chacun codera de la même façon (je compte bien explorer ceci par la suite).
Au moment de rédiger cet article, WCF RIA Services est disponible en version RC2 et a une licence « go-live », donc tout devrait fonctionner.
Cela ne veut pas dire que vous ne devriez pas également utiliser WCF. Il y a des cas où WCF RIA Services n'est pas adapté. Par exemple, le cas de téléchargement de fichier. Dans cette situation il est préférable de créer un service WCF ou un HttpHandler pour traiter ce cas particulier.
Pour notre couche de données les meilleures options sont de nos jours toujours NHibernate (utilisant Linq to NHibernate) ou Entity Framework. Néanmoins, nous devrions encapsuler notre accès aux données par des objets repository et ne pas utiliser notre technologie d'accès aux données directement dans nos services. J'ai un article très simple qui parle exactement de ça. RIA Services génère du code sur le client basé sur la réflexion et d'autres métadonnées qui sont appliquées dans nos entités côté serveur. Si vous utilisez Entity Framework avec RIA Services, il possède déjà un fournisseur de métadonnées spécifique qui peut comprendre les relations entre entités et les générer correctement dans le client. Si vous souhaitez utiliser NHibernate vous devrez spécifier des métadonnées supplémentaires dans vos entités. Pour la simplicité j'utiliserai Entity Framework. Il y a d'autres ressources sur le Web qui expliquent comment utiliser NHibernate.
Dernier point, mais non des moindres, je voudrais parler de MEF. MEF, qui signifie Managed Extensibility Framework, a été livré avec .NET 4 (et SL 4) et est conçu pour nous aider à composer nos applications d'une façon découplée beaucoup plus facile que l'utilisation d'un conteneur IoC pour l'injection de dépendances. Vous annotez simplement vos classes avec les attributs Import/Export et MEF résoudra les dépendances entre objets pour vous. Bien sûr, il y a plus que nous pouvons faire. Vous pouvez fournir des métadonnées en exportant un objet et importer uniquement des objets qui suivent certains critères. MEF peut être utilisé pour télécharger le XAP quand un « Import » doit être satisfait et que l'objet exporté est dans un autre XAP, ce qui aide la construction d'applications modulaires. Il paraît que la nouvelle version de Prism utilisera MEF pour ses fonctionnalités de modularité, ce qui le rend encore plus intéressant.
Conclusion▲
Dans la prochaine partie, je vais démarrer avec un scénario d'entreprise simple et suivre une approche de haut en bas en concevant une architecture construite sur ces technologies. Je n'ai pas été très disponible ces derniers temps, mais j'essaie de me rattraper. À bientôt, donc.