Architecture Silverlight LOB – Concepts et technologies (Partie 1)

Dans cette première partie de la série sur l’architecture LOB je vais me concentrer sur certains projets open source dans Microsoft « Patterns & Practices technologies » et d’autres qui sont disponibles et peuvent nous aider à atteindre 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 modulaire WPF et des application Silverlight. Il a également intégré dans les composants qui vous permettent de profiter de certains des modèles connus comme MVVM, événement agrégateur et l’injection de dépendance. Il existe d’autres, mais je vais me concentrer sur ces trois.

PRISM

PRISM s’applique aux développement Client. Je pense que la meilleure caractéristique de PRISM est d’offrir la possibilité de spécifier vos modules applicatifs (XAPs dans Silverlight) comme un catalogue et de les charger à la demande. Nous allons explorer cette question en détail dans d’autres parties de cette série lorsque nous créons un catalogue de module pour être utilisé dans l’application.

L’injection de dépendance (un usage spécifique de la notion d’inversion de contrôle) est une technique de choix pour le renforcement des applications faiblement couplés, car il fournit les moyens de gérer les dépendances entre les objets. Il vous aide à construire un code testable, car vous pouvez facilement passer des implémentations concrètes que votre objet en dépend. PRISM est construit en utilisant ce principe de conception et il utilise le conteneur Unity, qui met en Å“uvre la technique de DI (Dependency injection). PRISM permet également d’utiliser d’autres récipients DI, mais je vais me concentrer sur Unity.

Ce modèle peut être appliqué tant dans le développement client et serveur.

Le pattern MVVM est entrain de devenir l’alpha et l’omega dans le developpement d’application WPF et silverlight. Il vous aide à séparer vos couches : la conception de votre couche de présentation et si elle est bien pensé, vous pouvez créer un grand ensemble de code réutilisable et même les réutiliser pour d’autres applications.

Avec MVVM vous pensez essentiellement à votre view comme un ensemble de classes et de propriétés et non comme un ensemble de contrôles d’interface utilisateur (UI).Cela vous permet de passer facilement à votre interface utilisateur tout en conservant la même logique, et en même temps permet la testabilité. De plus, il vous permet de réutiliser un ensemble de la logique UI dans beaucoup de vues avec moins d’effort. Ce modèle est appliqué au développement client.

Le pattern Event Aggregator vous permet de construire votre application avec une Driven Architecture de l’événement où les composants communiquent entre eux de manière découplée. La seule chose que vous devez savoir est l’événement que vous publiez ou vous vous inscrivez et comment réagir face à cet événement. Habituellement les modules ne dépendent pas les uns des autres.

Ensuite, nous allons mettre l’accent sur le développement côté serveur.

la communication Client-server dans Silverlight recommande d’utiliser des services web. Puisque nous sommes dans la création d’applications LOB il est logique d’utiliser les services qui sont bon pour traiter des données. Les services WCF sont recommandé, mais sont-elles idéales? Quel est le coût du maintien d’une couche de service complete qui nous permet d’exposer les opérations CRUD (création, modification, suppression) sur nos données et nous fournit également la capacité de faire d’autes requêtes (comme obtenir des produits par productType) ? Combien de fois avons-nous fait cela? Et combien de fois avons-nous fait cela pour différentes applications? quand est il de la validation des données sur le serveur et le côté client ? quand est il de génération de proxy ? quand est il de la quantité de données envoyées sur le wire 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 laid comme l’enfer et le maintien du côté client des agent de service complète peut être gênant, parce que vous avez habituellement besoin de garder la synchronisation avec votre contrat de service. Dans Silverlight, il est un peu plus compliqué de partager un ensemble de contrats de service et les données de WPF, en raison d’incompatibilités de type. Aussi nous aimons habituellement les données côté client pour mettre en Å“uvre nos contrats INotifyPropertyChanged et ObservableCollections.

WCF RIA Services vise à résoudre tous ces problèmes et bien d’autres. Les caractéristiques les plus importantes, nous explorerons : la composition des requête, la validation des données, le suivi des modifications, unit of work, entre autres.

RIA Services

Suite : prochain poste

PS : cet article est une adaptation en français d’une suite d’articles par Manuel Felício

Kamel DJELLAL
Chef de projet
EDIS CONSULTING – GROUPE UBISIDE

http://www.ubiside.fr/

Architecture Silverlight LOB – Concepts et technologies (Partie 2)

J’ai utilisé RIA Services pendant les 4 derniers mois et une chose que j’ai trouver utile c’est la manière de communiquer avec le serveur et avec le modèle (du côté client) et par une API très bien définie qui rend facile la création d’un code très générique qui peut être utilisé pour créer des viewmodels réutilisable. C’est particulièrement utile quand vous avez des plusieurs personnes travaillant dans le même projet et vous voulez assurer que chacun codera de la même façon.

Cela ne signifie pas que vous ne devriez pas utiliser WCF aussi. 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 que vous créez un Service WCF ou un HttpHandler pour traiter les cas particuliers.

Pour notre couche de données les meilleures options sont de nos jours : 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’acces aux données directement dans nos services. RIA Services produit le code client basé sur la réflexion et d’autres métadonnées qui sont appliqués dans nos entités de côté serveur. Si vous utilisez Entity Framework avec des Services RIA il a déjà un fournisseur de métadonnées spécifique qui peut comprendre des relations entre des entités et les produire correctement dans le client. Si vous voulez 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 explique comment utiliser NHIBERNATE.

Aussi, je voudrais parler de MEF (Managed Extensibility Framework): la Structure d’Extensibilité Gérée est conçu pour nous aider à composer nos applications d’une façon détachée beaucoup plus facile que l’utilisation d’un conteneur IoC pour l’injection de dépendance. Vous annotez simplement vos classes avec Import/Export des attributs et MEF résoudra des dépendances entre des objets pour vous. Bien sûr il y a plus nous pouvons faire. Vous pouvez fournir des métadonnées en exportant un objet et importer seulement des objets qui suivent ce critère. MEF peut être utilisé pour télécharger le XAP’S quand une Importation doit être satisfaite et l’objet exporté est dans un autre XAP, qui aide des applications modulaires construisants. Il est dit que la nouvelle version de Prisme utilisera MEF pour ses caractéristiques fonctions de modularité, qui le rend encore plus intéressant.

Voici le lien vers la communauté MEF :

http://mef.codeplex.com/

Suite : prochain post

PS : cet article est une adaptation en français d’une suite d’articles par Manuel Felício

Kamel DJELLAL
Chef de projet
EDIS CONSULTING – GROUPE UBISIDE

http://www.ubiside.fr/

Architecture Silverlight LOB – Concepts et technologies (Partie 3)

L’image suivante décrit comment une application peut être mise en couche dans de multiple modules. Ces modules peuvent communiquer les un avec les autre par des messages bien définis et des contrats définis dans le module de la couche d’Infrastructure.

En outre, ils récupèrent et manipulent des objets de données par les Services WCF qui sont convenus pour le DDD (appelé WCF RIA Services). Ces objets de données sont souvent appelés des entités et peuvent représenter votre « Domain Model » et sont perssister dans le data store en utilisant « Data Access Objects ».

WCF RIA Services fournit des voies pour vous pour manipuler vos entités dans le client de la même façon comme vous feriez dans le serveur , des données de changement et des changements de soumission, mettre à jour des données ou soumettre des modification.

Une telle application compte souvent sur l’infrastructure de côté de serveur pour l’authentification et l’autorisation, l’enregistrement et la gestion des erreurs. Du côté client ils comptent sur des structures que l’aide réduit, harmonise et réutilise le code dans le développement de module tant à la logique de présentation qu’aux vues de présentation. Quelques couches peuvent avoir les composants qui dépendent de composants d’autres couches.
Dans de tels cas, nous réduisons ces dépendances avec des conteneurs IoC ou des structures semblables comme MEF.

Le développement dans une architecture N-Tiers peut être ennuyeux quand vous voulez réutiliser le code qui doit être spécifié tant du côté serveur que du côté client quand il s’agit de la validation ou de la logique métier.

Notez que la couche de mapping entre les « Data Entities » et le « Domain entities ». cette couche est optionnelle et peut être utile quand vous ne voulez pas exposer vos « data entities » comme « domain model ». Cela aide à réaliser l’ignorance de persistance et vous permet aussi de créer des classes simples et légères pour transporter des données. Pour la simplicité, je ne vais pas utiliser cette couche aux postes prochains, donc mes entités de données seront mes entités de domaine.

Suite : prochain poste

PS : cet article est une adaptation en français d’une suite d’articles par Manuel Felício

Kamel DJELLAL
Chef de projet
EDIS CONSULTING – GROUPE UBISIDE

http://www.ubiside.fr/

Architecture Silverlight LOB – Concepts et technologies (Partie 4)

Dans ce post je vais commencer avec un simple « Business Domain Model » et je vais crée une couche de domain autour du modele.

Dans cet exemple notre application sera une application Web pour une société qui vend des produits et cela peut être utilisé par ses clients pour faire des commandes et ses salariés pour les traiter. Ces commandes ont les détails qui consistent en produits et des quantités. Chaque produit peut avoir une catégorie de produit. Quand un client soumet une commande, un salarié de la société peut traiter cet commande et préparer les articles pour l’expédition.

La société a quelques départements et chaque salarié appartient à un département. Cela signifie que les salariés du Service des ventes devront traiter les commandes; les salariés du département de Ressources Humain pourront recruter de nouveaux salariés; et les salariés du Département Financier pourront observer quelques diagrammes et des rapports avec la statistique comment les ventes se développent en fonction du temps, des rapports de ventes, etc.

l’authentication et l’authorization seront ajoutés plutard.

Pour faire simple, j’ai créent le modèle de données suivant :

modele

Ce modèle sera tant notre modèle de données que le modèle de domaine. C’est très simple et comme j’ai dit au poste précédent, créant un modèle de domaine séparé est facultatif parce que vous pouvez toujours faire bien avec vos entités de données. Puisque nous utilisons la « Entity FRamework » nous profiterons de LinqToEntitiesDomainService, un Service de Domaine spécifique qui traite avec les objets de l’EF.

Puisque nous commençons par notre couche de Domaine, nous définirons un Service de Domaine qui peut être utilisé de notre application Silverlight (ou d’autres clients aussi) et créer les opérations CRUD (creation, mise à jour, suppression). Je suis sûr que vous avez remarqué combien de code est produit quand vous utilisez le modèle de Service de Domaine de visual Studio. Créez juste une classe de base pour vos services de domaine et ajoutez les méthodes suivantes :

#region Basic CRUD
protected IQueryable<T> GetQuery<T>()
    where T : class
{
    return this.GetRepository<T>().GetQuery();
}
protected void Insert<T>(T entity)
    where T : class
{
    this.GetRepository<T>().Add(entity);
}
protected void Update<T>(T entity)
    where T : class
{
    this.GetRepository<T>().AttachAsModified(entity, this.ChangeSet.GetOriginal(entity));
}
protected void Delete<T>(T entity)
    where T : class
{
    this.GetRepository<T>().Delete(entity);
}
#endregion
 
protected IRepository<T> GetRepository<T>()
    where T : class
{
    return this.Container.Resolve<IRepository<T>>();
}

La propriété conteneurs est un cas IUNITYCONTAINER, que jegarde dans le Service de Domaine de base. J’ai d’habitude d’une classe singleton commune où le conteneur IoC est disponible mais je crée aussi un conteneur enfant pour chaque Service de Domaine. Cela me permet d’enregistrer des cas spécifiques dans le conteneur enfant et l’utiliser seulement dans les limites de mon Service de Domaine. C’est utile pour résoudre des repositories parce que mes repositories dépendent de l’ObjectContext qui est injecté via l’injection de dépendance. Voici comment on procède :

public abstract class DomainRepositoryService<TContext> : LinqToEntitiesDomainService<TContext>, IDbContextManager
    where TContext : ObjectContext, IDbContext, new()
{
    protected IUnityContainer Container { get; private set; }
    /// <summary>
    /// Create a child container to use THIS as the IDbContextManager implementation when resolving repositories
    /// Ensures that other threads / domain services can use the main container to resolve repositories
    /// and use its own instance as the IDbContextManager for the repositories they need
    /// </summary>
    /// <param name="context">The DomainServiceContext instance</param>
    public override void Initialize(DomainServiceContext context)
    {
        base.Initialize(context);
 
        this.Container = IoC.Current.Container.CreateChildContainer();
        this.Container.RegisterInstance<IDbContextManager>(this);
    }
 
    #region IDbContextManager Members
    public IDbContext GetDbContext()
    {
        return this.ObjectContext;
    }
    #endregion
    //...
}

Cela a dit, le Service de Domaine spécifique pour notre application Silverlight y ressemblera :

[EnableClientAccess()]
public class MyAppService : DomainRepositoryService<MyAppEntities>
{
    #region Customer
    public IQueryable<Customer> GetCustomers()
    {
        return base.GetQuery<Customer>();
    }
    public void InsertCustomer(Customer entity)
    {
        base.Insert(entity);
    }
    public void UpdateCustomer(Customer entity)
    {
        base.Update(entity);
    }
    public void DeleteCustomer(Customer entity)
    {
        base.Delete(entity);
    }
    #endregion
    //repeat for the other entities...
}

Remarquez comment ma Couche de Domaine ne se soucie pas vraiment de comment les entités sont stockées ou gérées avec EF (entity framework). Il le délègue la responsabilité à un objet qui met en oeuvre l’interface IREPOSITORY.

Cette interface peut être générique et ressemble souvent :

public interface IRepository<TEntity>
    where TEntity : class
{
    TEntity GetEntity(int id);
    IQueryable<TEntity> GetQuery();
    void Add(TEntity entity);
    void Update(TEntity entity);
    void Delete(TEntity entity);
    /// <summary>
    /// Abstraction on RIA's AttachAsModified extension method
    /// </summary>
    /// <param name="current"></param>
    /// <param name="original"></param>
    void AttachAsModified(TEntity current, TEntity original = null);
}

Pour la simplicité j’ai inclus la méthode AttachAsModified dans l’IREPOSITORY. Cette méthode est importante parce que RIA exige que l’entité actuelle étant mise à jour soit attachée dans l’ObjectContext. Une autre option devrait créer une interface séparée qui provient d’IREPOSITORY et ajouter la méthode là. C’est que l’interface IREPOSITORY est un concept générique qui peut être utilisé avec beaucoup de technologies d’accès de données.

Notez que du moment vous créez votre Service de Domaine et exposez vos entités, imediatement une autre personne/équipe peut commencer à construire l’application utilisant les entités exposées, tandis qu’une autre équipe continue à travailler sur la couche serveur ajoutant des métadonnées et-ou la logique de validation qui sera aussi disponible pour l’application client.

Suite : prochain poste

PS : cet article est une adaptation en français d’une suite d’articles par Manuel Felício

Kamel DJELLAL
Chef de projet
EDIS CONSULTING – GROUPE UBISIDE

http://www.ubiside.fr/

News & retour vers le blog

Bonjour chers lecteurs,

Après une absence de plusieurs mois, du à ma faible disponibilité pour me consacrer au blog, je reviens en force pour vous mettre l’eau à la bouche et vous prévenir de l’arrivée de plusieurs sujets :

– Ma participation aux journées SQL Server 2012 et vous présenter mon avis dessus et les enseignements qu’on peut tirer de la présentation de « DENALI »

– Quelques articles sur Sharepoint 2007

Ces articles arrivent bientôt.
Ils sont déjà prêts sur brouillon et reste à affiner pour vous les présenter correctement.

Techniquement vôtre,

Kamel DJELLAL
Chef de projet
EDIS CONSULTING – GROUPE UBISIDE

http://www.ubiside.fr/