Partager via


La méthode de flux de travail : Présentation de Windows Workflow Foundation

David Chappell
Chappell & Associates

Avril 2009

Télécharger cet article

Présentation de Windows Workflow Foundation

Tout le monde qui écrit du code veut créer un excellent logiciel. Si ce logiciel est une application serveur, une partie d’une grande mise à l’échelle est bien, la gestion des charges volumineuses sans consommer trop de ressources. Une grande application devrait également être aussi facile à comprendre, à la fois pour ses créateurs et pour les personnes qui le maintiennent.

Atteindre ces deux objectifs n’est pas facile. Les approches qui aident les applications à mettre à l’échelle ont tendance à les dissocier, en divisant leur logique en blocs distincts qui peuvent être difficiles à comprendre. Pourtant, l’écriture d’une logique unifiée qui réside dans un seul exécutable peut rendre la mise à l’échelle de l’application tout sauf impossible. Ce qui est nécessaire est un moyen de maintenir la logique unifiée de l’application, ce qui le rend plus compréhensible, tout en laissant l’application mise à l’échelle.

Il s’agit d’un objectif principal de Windows Workflow Foundation (WF). En prenant en charge la logique créée à l’aide de flux de travail, WF fournit une base pour la création d’applications unifiées et évolutives. En plus de cela, WF peut également simplifier d’autres défis de développement, tels que la coordination du travail parallèle, le suivi de l’exécution d’un programme, et bien plus encore.

WF a été publié pour la première fois avec .NET Framework 3.0 en 2006, puis mis à jour dans le .NET Framework 3.5. Ces deux premières versions étaient utiles, en particulier pour les éditeurs de logiciels indépendants (ISV), mais elles ne sont pas devenues des technologies standard pour les développeurs d’entreprise. Avec la version de WF qui fait partie du .NET Framework 4, ses créateurs visent à changer cela. Un objectif majeur de cette dernière version est de rendre WF une partie standard du kit de ressources de programmation pour tous les développeurs .NET.

Comme toute technologie, l’application de WF nécessite de comprendre ce qu’elle est, pourquoi elle est utile et quand il est judicieux de l’utiliser. L’objectif de cette vue d’ensemble est de rendre ces choses claires. Vous n’allez pas apprendre à écrire des applications WF, mais vous aurez un aperçu des offres WF, pourquoi il s’agit de la façon dont il est, et comment il peut améliorer la vie d’un développeur. En d’autres termes, vous allez commencer à comprendre la façon de flux de travail.

Le défi : écriture d’une logique d’application unifiée et évolutive

Une façon simple d’écrire un programme consiste à créer une application unifiée qui s’exécute dans un seul processus sur un seul ordinateur. La figure 1 illustre cette idée.

Figure 1 : La logique d’application peut être créée dans son ensemble unifié, puis exécutée sur un thread particulier dans un processus exécuté sur un seul ordinateur.

Le pseudo-code simple dans cet exemple montre les types d’opérations que les applications effectuent généralement :

  • Conservez l’état, qui est représenté ici par une variable de chaîne simple.
  • Obtenez une entrée à partir du monde extérieur, par exemple en recevant une demande d’un client. Une application simple peut simplement lire à partir de la console, tandis qu’un exemple plus courant peut recevoir une requête HTTP à partir d’un navigateur Web ou d’un message SOAP d’une autre application.
  • Envoyez la sortie au monde extérieur. Selon la façon dont elle est générée, l’application peut effectuer cette opération via HTTP, un message SOAP, en écrivant dans la console ou d’une autre manière.
  • Fournissez d’autres chemins par le biais d’une logique à l’aide d’instructions de flux de contrôle telles que if/else et while.
  • Effectuez un travail en exécutant le code approprié à chaque point de l’application.

Dans l’approche unifiée présentée ici, la logique d’application passe toute sa vie en cours d’exécution sur un thread à l’intérieur d’un processus particulier sur un seul ordinateur. Cette approche simple présente plusieurs avantages. Pour une chose, la logique peut être implémentée de manière simple et unifiée. Cela permet aux personnes qui travaillent avec le code de le comprendre et rend également l’ordre autorisé des événements explicites. Dans la figure 1, par exemple, il est évident que la première demande du client doit précéder le deuxième : le flux de contrôle du programme l’exige. Lorsque la deuxième requête arrive, il n’est pas nécessaire de vérifier que la première demande a déjà été gérée, car il n’y a pas d’autre chemin d’accès via l’application.

Un autre avantage de cette approche est que l’utilisation de l’état de l’application est facile. Cet état est conservé dans la mémoire du processus et, étant donné que le processus s’exécute en continu jusqu’à ce que son travail soit effectué, l’état est toujours disponible : le développeur accède simplement aux variables ordinaires. Qu’est-ce qui pourrait être plus simple ?

Toutefois, ce style de programmation de base présente des limitations. Lorsque l’application doit attendre l’entrée, qu’il s’agisse d’un utilisateur dans la console, d’un client de services Web ou d’un autre élément, il suffit généralement de bloquer. Le thread et le processus qu’il utilise sont conservés jusqu’à ce que l’entrée arrive, mais cela prend beaucoup de temps. Étant donné que les threads et les processus sont des ressources relativement rares, les applications qui tiennent sur l’une ou l’autre quand elles attendent simplement l’entrée ne sont pas très mises à l’échelle.

Une approche plus évolutive consiste à arrêter l’application lorsqu’elle attend une entrée, puis à la redémarrer à l’arrivée de cette entrée. Cette approche ne gaspille pas les ressources, car l’application ne tient pas sur un thread ou un processus lorsqu’elle n’en a pas besoin. Cela permet également à l’application de s’exécuter dans différents processus sur différents ordinateurs à différents moments. Au lieu d’être verrouillé sur un seul système, comme dans la figure 1, l’application peut être exécutée sur l’un des plusieurs ordinateurs disponibles. Cela permet également la scalabilité, car le travail peut être plus facilement réparti sur différents ordinateurs. La figure 2 montre comment cela ressemble.

Figure 2 : La logique d’application peut être divisée en blocs, tout en partageant l’état commun, qui peut s’exécuter sur différents ordinateurs.

Cet exemple d’application contient la même logique que précédemment, mais elle est maintenant divisée en blocs distincts. Lorsque la première requête du client est reçue, le bloc approprié est chargé et exécuté. Une fois cette requête gérée et une réponse renvoyée, ce bloc peut être déchargé. Il n’est pas nécessaire de rester en mémoire. Lorsque la deuxième requête du client arrive, le bloc qui le gère est chargé et exécuté. Comme le montre la figure 2, ce bloc peut s’exécuter sur un autre thread dans un autre processus s’exécutant sur un autre ordinateur à partir du premier bloc. Une fois qu’il a géré la requête, ce deuxième bloc peut également être déchargé, ce qui libère la mémoire qu’il utilise.

Un exemple courant d’une technologie qui fonctionne de cette façon est ASP.NET. Un développeur implémente une application ASP.NET sous la forme d’un ensemble de pages, chacune contenant une partie de la logique de l’application. Lorsqu’une requête arrive, la page correcte est chargée, exécutée, puis déchargée à nouveau.

Une application créée dans ce style peut utiliser des ressources de machine plus efficacement qu’une application créée à l’aide de l’approche plus simple présentée précédemment, et elle va donc s’améliorer. Pourtant, nous avons payé pour cette scalabilité améliorée avec la complexité. Pour une chose, les différents blocs de code doivent en quelque sorte partager l’état, comme le montre la figure 2. Étant donné que chaque bloc est chargé à la demande, exécuté, puis arrêté, cet état doit être stocké en externe, par exemple dans une base de données ou dans un autre magasin de persistance. Au lieu d’accéder simplement à des variables ordinaires, comme le scénario illustré dans la figure 1, un développeur doit désormais effectuer des opérations spéciales pour acquérir et enregistrer l’état de l’application. Dans ASP.NET applications, par exemple, les développeurs peuvent écrire l’état directement dans une base de données, accéder à l’objet Session ou utiliser une autre approche.

Un autre coût de cette scalabilité améliorée est que le code ne fournit plus une vue unifiée de la logique globale du programme. Dans la version indiquée dans la figure 1, l’ordre dans lequel le programme s’attend à ce que l’entrée soit évidente, il n’y a qu’un seul chemin possible dans le code. Toutefois, avec la version de la figure 2, ce flux de contrôle n’est pas évident. En fait, le bloc de code qui gère la deuxième requête du client peut avoir besoin de commencer par vérifier que la première demande a déjà été effectuée. Pour une application qui implémente n’importe quel type de processus métier important, la compréhension et l’implémentation correcte du flux de contrôle sur différents segments peut être difficile.

La situation est la suivante : l’écriture d’applications unifiées facilite la vie du développeur et le code simple à comprendre, mais le résultat n’est pas bien mis à l’échelle. L’écriture d’applications segmentes qui partagent un état externe, comme ASP.NET applications, permet une scalabilité, mais rend la gestion de l’état plus difficile et perd le flux de contrôle unifié. Ce que nous aimerions est un moyen de faire les deux : écrire une logique métier évolutive avec une gestion d’état simple, mais toujours avoir une vue unifiée du flux de contrôle de l’application.

C’est exactement ce que fournit le flux de travail. La section suivante montre comment procéder.

La solution : la méthode de flux de travail

Comprendre comment une application WF résout ces problèmes (et d’autres) nécessite de parcourir les principes de base du fonctionnement de WF. Nous allons voir pourquoi cette technologie peut améliorer la vie des développeurs dans un nombre étonnamment important de cas.

Création d’une logique d’application unifiée

Une application basée sur un flux de travail créée à l’aide de WF effectue les mêmes types d’opérations qu’une application ordinaire : elle conserve l’état, obtient l’entrée et envoie la sortie au monde extérieur, fournit un flux de contrôle et exécute du code qui effectue le travail de l’application. Toutefois, dans un flux de travail WF, toutes ces opérations sont effectuées par les activités. La figure 3 montre comment cela se présente, avec l’approche de code unifiée présentée en même temps que pour la comparaison.

Figure 3 : Dans un flux de travail WF, tous les travaux d’un programme sont effectués par les activités.

Comme le montre la figure 3, chaque flux de travail a une activité la plus externe qui contient tous les autres. Ici, cette activité la plus externe est appelée Sequence, et comme un programme ordinaire, elle peut avoir des variables qui conservent son état. Étant donné que Sequence est une activité composite, elle peut également contenir d’autres activités.

Dans cet exemple simple, le flux de travail commence par une activité ReceiveMessage qui obtient une entrée du monde extérieur. Cette opération est suivie d’une activité If, qui (sans surprise) implémente une branche. S’il s’agit également d’une activité composite, contenant d’autres activités (étiquetées X et Y ici) qui exécutent le travail effectué sur chaque branche. L’activité If est suivie d’une activité SendMessage qui envoie une sortie au monde au-delà de ce flux de travail. Une autre activité ReceiveMessage s’affiche ensuite, qui obtient plus d’entrée, puis est suivie d’une activité While. Alors que contient une autre activité, Z, qui effectue le travail de cette boucle while. L’ensemble du flux de travail se termine par une activité SendMessage finale, en envoyant le résultat final du programme.

Toutes ces activités correspondent fonctionnellement à différentes parties d’un programme classique, comme le suggèrent les couleurs correspondantes dans la figure 2. Mais plutôt que d’utiliser des éléments de langage intégrés, comme le fait un programme traditionnel, chaque activité d’un flux de travail WF est en fait une classe. L’exécution du flux de travail est effectuée par le runtime WF, un composant qui sait exécuter des activités. La figure 4 illustre cette idée.

Figure 4 : Le runtime WF exécute des activités dans l’ordre déterminé par le flux de travail.

Lorsqu’il commence à exécuter un flux de travail, le runtime WF exécute d’abord l’activité la plus externe, qui dans cet exemple est une séquence. Il exécute ensuite la première activité à l’intérieur de celle-ci, qui est ici ReceiveMessage, suivie de l’activité suivante, et ainsi de suite. Exactement quelles activités sont exécutées dans une situation particulière dépendent du chemin d’accès effectué via le flux de travail. Par exemple, l’obtention d’un type d’entrée dans la première activité ReceiveMessage peut entraîner l’exécution de l’activité If X, tandis qu’un autre type d’entrée peut entraîner l’exécution de l’activité Y. C’est comme n’importe quel autre programme.

Il est important de comprendre que le runtime WF ne connaît rien du tout sur les éléments internes des activités qu’il exécute. Il ne peut pas indiquer si à partir d’un ReceiveMessage. La seule chose qu’il sait faire est d’exécuter une activité, puis d’exécuter la suivante. Le runtime peut toutefois voir les limites entre les activités, ce qui, comme nous le verrons, est une chose utile.

Une conséquence importante est que WF ne définit pas de langage particulier pour décrire les flux de travail, tout dépend des activités qu’un développeur choisit d’utiliser. Pour faciliter la vie, WF inclut une bibliothèque d’activités de base (BAL) qui fournit un ensemble d’activités largement utile. (Tous les exemples d’activités utilisés ici sont tirés du BAL, en fait.) Mais les développeurs sont libres de créer toutes les autres activités qu’ils aiment. Ils peuvent même choisir d’ignorer complètement le BAL.

Il y a une question évidente ici : Pourquoi aller à toutes ces difficultés ? La création d’un programme à l’aide d’activités est différente de ce que les développeurs sont utilisés, alors pourquoi quelqu’un doit-il déranger ? Pourquoi n’écrivez-vous pas simplement du code ordinaire ?

La réponse, bien sûr, est que cette approche peut nous aider à créer un meilleur code. Notez, par exemple, que le flux de travail donne au développeur un flux de contrôle unifié. Tout comme dans le cas simple présenté dans la figure 1, la logique principale du programme est définie dans un flux cohérent. Cela facilite la compréhension et, étant donné que la logique n’est pas divisée en blocs, il n’est pas nécessaire d’effectuer des vérifications supplémentaires. Le flux de travail lui-même exprime le flux de contrôle autorisé.

Cela représente la moitié de notre objectif : création d’une logique d’application unifiée. Toutefois, les applications WF peuvent également accomplir la deuxième moitié, créant des applications évolutives avec une gestion d’état simple. La section suivante explique comment le flux de travail rend cela possible.

Fourniture d’une scalabilité

Pour être évolutive, une application serveur ne peut pas être verrouillée dans un seul processus sur un seul ordinateur. Pourtant, cassant explicitement la logique d’application en blocs, comme dans ASP.NET pages, décompose ce qui doit être un flux de contrôle unifié. Il force également le programmeur à travailler explicitement avec l’état. Ce que nous aimerions vraiment, c’est que notre logique soit automatiquement divisée en blocs qui peuvent s’exécuter dans différents processus sur différents ordinateurs. Nous aimerions également que l’état de notre application soit géré pour nous, donc tout ce que nous devons faire est des variables d’accès.

C’est exactement ce que fournissent les flux de travail. La figure 5 montre les principes fondamentaux de la façon dont WF accomplit ces choses.

Figure 5 : le runtime WF décharge un flux de travail pendant qu’il attend l’entrée, puis le charge une fois l’entrée arrivée.

Comme n’importe quelle application, un flux de travail WF bloque l’attente d’entrée. Dans la figure 5, par exemple, le flux de travail est bloqué au niveau de la deuxième activité ReceiveMessage en attente de la deuxième requête du client (étape 1). Le runtime WF remarque cela, et ainsi il stocke l’état du workflow et une indication de l’endroit où le flux de travail doit reprendre dans un magasin de persistance (étape 2). Lorsque l’entrée arrive pour ce flux de travail (étape 3), le runtime WF trouve son état persistant, puis recharge le flux de travail, en sélectionnant l’exécution là où il s’est arrêté (étape 4). Tout cela se produit automatiquement : le développeur WF n’a rien à faire. Étant donné que le runtime WF peut voir dans le flux de travail, il peut gérer tous ces détails lui-même.

L’un des avantages évidents de cette approche est que le flux de travail ne se bloque pas dans la mémoire bloquant un thread et utilise un processus pendant qu’il attend l’entrée. Un autre avantage est qu’un flux de travail persistant peut potentiellement être rechargé sur un ordinateur autre que celui sur lequel il s’exécutait à l’origine. En raison de cela, différentes parties du flux de travail peuvent finir par s’exécuter sur différents systèmes, comme l’illustre la figure 6.

Figure 6 : un flux de travail peut s’exécuter sur différents threads, dans différents processus et sur différents ordinateurs pendant sa durée de vie.

Dans cet exemple, supposons que le flux de travail gère la première requête du client dans un processus sur l’ordinateur A. Lorsque le second ReceiveMessage provoque le blocage du flux de travail en attente d’entrée, le runtime WF décharge l’état du flux de travail dans un magasin de persistance, comme décrit simplement. Lorsque la deuxième requête du client arrive, il est possible que ce flux de travail soit rechargé dans un processus sur l’ordinateur B. Au lieu d’être verrouillé sur un thread spécifique dans un processus spécifique sur un ordinateur spécifique, un flux de travail WF peut être déplacé si nécessaire. Et le développeur obtient cette agilité gratuitement , elle est fournie automatiquement par WF.

Il est important de souligner que le runtime WF ne s’occupe pas de la durée pendant laquelle le flux de travail doit attendre l’entrée. Il peut arriver quelques secondes après la persistance du flux de travail, quelques minutes plus tard, voire quelques mois plus tard. Tant que le magasin de persistance conserve toujours l’état du flux de travail, ce flux de travail peut être redémarré. Cela rend WF une technologie attrayante pour la création d’applications qui implémentent des processus de longue durée. Réfléchissez à une application qui soutient un processus d’embauche, par exemple, qui englobe tout, de la planification des entrevues initiales à l’intégration d’un nouvel employé dans l’organisation. Ce processus peut durer des semaines ou des mois, et ainsi gérer l’état de l’application à l’aide de WF est judicieux. Toutefois, même si la fonction WF peut être très utile avec ce type de processus de longue durée, il est important de comprendre que ce n’est pas son seul objectif. Toute application nécessitant une logique unifiée et évolutive peut être un bon candidat pour WF.

En fait, jetez un autre coup d’œil à la figure 6. Ne ressemble-t-il pas beaucoup à la figure 2, qui a montré comment une application segmente (par exemple, une application créée uniquement avec ASP.NET) a atteint l’extensibilité ? Et en fait, la figure 6 n’a-t-elle pas également une forte similarité avec la figure 1, qui a montré une application unifiée créée avec un flux de contrôle linéaire ? WF effectue ces deux opérations : le flux de contrôle de l’application est exprimé de manière compréhensible, unifiée et peut être mis à l’échelle, car elle n’est pas verrouillée sur un seul processus sur un seul ordinateur. C’est la beauté du flux de travail.

Et ce n’est pas tout. l’utilisation de WF présente également d’autres avantages. Il peut faciliter la coordination du travail parallèle, par exemple, faciliter le suivi de la progression d’une application, et bien plus encore. La section suivante examine ces aspects de la technologie.

Autres avantages de la méthode de flux de travail

Un flux de travail WF se compose d’activités exécutées par le runtime WF. Bien que la compréhension du monde WF prenne quelques efforts, l’écriture de la logique d’application dans ce style facilite un certain nombre de défis de programmation courants, comme décrit ci-dessous.

Coordination du travail parallèle

La bal WF inclut des activités qui correspondent à des instructions de langage de programmation familières. En raison de cela, vous pouvez écrire des flux de travail qui se comportent beaucoup comme des programmes ordinaires. Pourtant, la présence du runtime WF permet également de créer des activités qui fournissent plus qu’un langage de programmation classique. Un exemple important est l’utilisation d’un flux de travail pour faciliter la coordination du travail parallèle.

Ne vous confondez pas : le focus ici n’est pas sur l’écriture de code parallèle qui s’exécute simultanément sur un processeur multicœur. Au lieu de cela, pensez à une application qui, par exemple, doit appeler deux services Web, puis attendre les deux résultats avant de continuer. L’exécution des appels en parallèle est clairement plus rapide que de les exécuter séquentiellement, mais l’écriture de code traditionnel qui le fait n’est pas simple. Et bien que le .NET Framework offre différentes approches pour effectuer ces appels de façon asynchrone, aucune d’entre elles n’est particulièrement simple. Il s’agit d’une autre situation dans laquelle le flux de travail peut briller : WF facilite cette opération. La figure 7 montre comment procéder.

Figure 7 : Activités contenues dans une activité parallèle exécutées en parallèle.

Cette figure montre un flux de travail simple qui ressemble beaucoup à l’exemple précédent. La grande différence est qu’il appelle maintenant deux services Web, puis attend une réponse des deux avant de continuer. Pour exécuter ces appels en parallèle, le créateur du flux de travail a encapsulé les deux paires d’activités SendMessage et ReceiveMessage à l’intérieur d’une activité Parallèle. Parallel est une partie standard de la bibliothèque d’activités de base WF et fait exactement ce que son nom suggère : exécute les activités qu’il contient en parallèle. Au lieu de faire face à la complexité de la gestion de ce problème, le runtime WF et l’activité Parallel effectuent le travail lourd. Tout ce que le développeur doit faire est d’organiser les activités selon les besoins pour résoudre son problème.

Fourniture d’un suivi automatique

Étant donné que le runtime WF peut voir les limites entre les activités d’un flux de travail, il sait quand chacune de ces activités démarre et se termine. Étant donné cela, le suivi automatique de l’exécution du flux de travail est simple. La figure 8 illustre cette idée.

Figure 8 : Le runtime WF peut suivre automatiquement l’exécution d’un flux de travail.

Comme l’illustre cet exemple, le runtime WF peut écrire un enregistrement de l’exécution d’un flux de travail dans un magasin de suivi. Une option consiste à journaliser les activités, avec un enregistrement écrit chaque fois qu’une activité commence et met fin à l’exécution. À l’heure indiquée dans la figure, par exemple, le flux de travail est sur le point de commencer à exécuter l’activité If, et donc le runtime WF écrit un événement indiquant ceci. Il est également possible de suivre des variables spécifiques, c’est-à-dire l’état du flux de travail, d’enregistrer leurs valeurs à différents points dans l’exécution du flux de travail.

Comme pour d’autres aspects de la WF, cette journalisation automatique ne nécessite essentiellement aucun travail de la part du développeur. Il peut simplement indiquer que le suivi doit se produire, en spécifiant le niveau qui lui intéresse, et WF s’occupe du reste.

Création d’activités personnalisées réutilisables

Les activités du BAL de WF fournissent une variété de fonctions utiles. Comme indiqué précédemment, par exemple, cet ensemble intégré inclut des activités pour le flux de contrôle, l’envoi et la réception de messages, le travail en parallèle, etc. Toutefois, la création d’une application réelle nécessite généralement la création d’activités qui effectuent des tâches spécifiques à cette application.

Pour rendre cela possible, WF permet de créer des activités personnalisées. Par exemple, les activités étiquetées X, Y et Z dans les flux de travail indiqués précédemment sont des activités personnalisées, car la figure 9 rend explicite.

Figure 9 : Les activités personnalisées permettent à un flux de travail d’effectuer des tâches spécifiques à l’application.

Les activités personnalisées peuvent être simples, exécutant une seule tâche, ou elles peuvent être des activités composites contenant une logique arbitrairement complexe. Et qu’elles soient simples ou complexes, les activités personnalisées peuvent être utilisées de différentes façons. Par exemple, une application métier créée à l’aide de WF peut implémenter une logique spécifique à l’application comme une ou plusieurs activités personnalisées. Par ailleurs, un fournisseur de logiciels utilisant WF peut fournir un ensemble d’activités personnalisées pour faciliter la vie de ses clients. Par exemple, Windows SharePoint Services permet aux développeurs de créer des applications basées sur WF qui interagissent avec des personnes via les listes standard de SharePoint. Pour faciliter cette opération, SharePoint inclut des activités personnalisées pour écrire des informations dans une liste.

Les activités personnalisées peuvent être écrites directement dans du code, en utilisant C# ou Visual Basic ou un autre langage. Ils peuvent également être créés en combinant des activités existantes, ce qui permet d’obtenir des options intéressantes. Par exemple, une organisation peut créer des activités personnalisées de niveau inférieur pour ses développeurs les plus qualifiés, puis les empaqueter dans des fonctions métier de niveau supérieur pour que les personnes moins techniques utilisent. Ces activités de niveau supérieur peuvent implémenter toute logique métier requise, toutes encapsulées dans une boîte réutilisable.

Une autre façon de réfléchir à cela consiste à afficher un ensemble spécifique d’activités exécutées par le runtime WF en tant que langage. Si une organisation crée un groupe d’activités personnalisées qui peuvent être réutilisées pour résoudre des problèmes spécifiques dans plusieurs applications, ce qu’elles font réellement est de créer un type de langage spécifique au domaine (DSL). Une fois cette opération effectuée, il peut être possible pour des personnes moins techniques de créer des applications WF à l’aide de ces blocs pré-empaquetés de fonctionnalités personnalisées. Au lieu d’écrire du code pour implémenter les fonctions de l’application, de nouveaux logiciels utiles peuvent être créés uniquement en assemblant des activités existantes. Ce style de DSL, défini de la manière du flux de travail, peut améliorer considérablement la productivité des développeurs dans certaines situations.

Rendre les processus visibles

La création d’applications avec un langage de programmation traditionnel signifie écrire du code. La création d’applications avec WF n’est généralement pas très faible. Au lieu de cela, au moins le flux de contrôle principal d’un flux de travail peut être assemblé graphiquement. Pour autoriser cela, WF inclut un concepteur de flux de travail qui s’exécute dans Visual Studio. La figure 10 illustre un exemple.

Figure 10 : Le concepteur de flux de travail, exécuté à l’intérieur de Visual Studio, permet à un développeur de créer un flux de travail en faisant glisser et en supprimant des activités.

Comme l’illustre cet exemple, les activités disponibles pour un développeur WF apparaissent sur la gauche. Pour créer un flux de travail, elle peut assembler ces activités sur l’aire de conception pour créer la logique requise par l’application. Si nécessaire, le concepteur de flux de travail WF peut également être réhébergé dans d’autres environnements, ce qui permet à d’autres utilisateurs d’utiliser cet outil à l’intérieur de leurs propres offres.

Pour certains développeurs, cette approche graphique facilite la création d’applications plus rapidement et plus facilement. Elle rend également la logique principale de l’application plus visible. En fournissant une image simple de ce qui se passe, le concepteur de flux de travail WF peut aider les développeurs à comprendre plus rapidement la structure d’une application. Cela peut être particulièrement utile pour les personnes qui doivent gérer les applications déployées, car l’apprentissage d’une nouvelle application suffisamment pour le modifier peut être un processus fastidieux.

Mais qu’en est-il des activités personnalisées ? N’y a-t-il pas encore besoin d’écrire du code ? La réponse est oui, et donc WF permet également d’utiliser Visual Studio pour créer des activités personnalisées en C#, Visual Basic et d’autres langages. Pour comprendre comment cela fonctionne, il est important de comprendre comment le concepteur WF représente les différentes parties d’un flux de travail. La figure 11 montre comment cela est généralement fait.

Figure 11 : L’état et le flux de contrôle d’un workflow sont généralement décrits en XAML, tandis que les activités personnalisées peuvent être écrites dans du code.

La composition d’un flux de travail WF ( les activités qu’elle contient et la façon dont ces activités sont liées) est généralement représentée à l’aide du langage XAML (Application Markup Language) eXtensible. Comme le montre la figure 11, XAML fournit un moyen XML de décrire l’état du flux de travail en tant que variables et d’exprimer les relations entre les activités du flux de travail. Ici, par exemple, le code XAML de la séquence d’activité de flux de travail la plus externe contient une activité ReceiveMessage suivie d’une activité If, comme prévu.

Cette activité Si l’activité contient les activités personnalisées X et Y. Au lieu d’être créées en XAML, toutefois, ces activités sont écrites en tant que classes C#. Bien qu’il soit possible de créer certaines activités personnalisées uniquement en XAML, une logique plus spécialisée est généralement écrite directement dans le code. En fait, bien qu’il ne s’agisse pas de l’approche habituelle, un développeur est également libre d’écrire des flux de travail entièrement dans du code , l’utilisation de XAML n’est pas strictement requise.

Utilisation de Windows Workflow Foundation : certains scénarios

Comprendre la mécanique de WF est une partie essentielle de la saisie du flux de travail. Il n’est pas suffisant, cependant : vous devez également comprendre comment les flux de travail peuvent être utilisés dans les applications. En conséquence, cette section examine comment , et pourquoi, WF peut être utilisé dans certaines situations typiques.

Création d’un service de flux de travail

La création d’une logique métier en tant que service est souvent logique. Supposons, par exemple, que le même ensemble de fonctionnalités doit être accessible à partir d’un navigateur via ASP.NET, à partir d’un client Silverlight et d’une application de bureau autonome. L’implémentation de cette logique en tant qu’ensemble d’opérations pouvant être appelées à partir d’un de ces clients, c’est-à-dire en tant que service, est susceptible d’être la meilleure approche. L’exposition de la logique en tant que service facilite également l’accès à d’autres logiques, ce qui peut parfois faciliter l’intégration des applications. (Il s’agit de l’idée fondamentale de la notion de SOA, architecture orientée service.)

Pour les développeurs .NET aujourd’hui, la technologie phare pour la création de services est Windows Communication Foundation (WCF). Entre autres choses, WCF permet aux développeurs d’implémenter une logique métier accessible à l’aide de REST, SOAP et d’autres styles de communication. Et pour certains services, WCF peut être tout ce qui est nécessaire. Si vous implémentez un service où chaque opération se trouve seule, par exemple, toute opération peut être appelée à tout moment, sans ordre requis, la création de ces services en tant que services WCF bruts est juste correct. Le créateur d’un service dont les opérations exposent uniquement les données peuvent être en mesure de s’éloigner de l’utilisation de WCF, par exemple.

Toutefois, pour des situations plus complexes, où les opérations d’un service implémentent un ensemble de fonctionnalités associé, WCF seul peut ne pas suffire. Réfléchissez aux applications qui permettent aux clients de réserver des réservations de vol ou de faire des achats en ligne ou d’effectuer d’autres processus métier. Dans les cas comme ceux-ci, vous pouvez choisir d’utiliser WF pour implémenter la logique du service. Cette combinaison a même un nom : la logique implémentée à l’aide de WF et exposée via WCF est appelée service de flux de travail. La figure 12 illustre l’idée.

Figure 12 : un service de flux de travail utilise WCF pour exposer la logique basée sur WF.

Comme le montre la figure, WCF permet d’exposer un ou plusieurs points de terminaison que les clients peuvent appeler via SOAP, REST ou autre chose. Lorsque le client appelle l’opération initiale dans cet exemple de service, la requête est gérée par la première activité ReceiveMessage du flux de travail. Une activité If apparaît ensuite, et laquelle de ses activités personnalisées contenues est exécutée dépend du contenu de la requête du client. Une fois l’opération If terminée, une réponse est retournée via SendMessage. La deuxième requête du client, appelant une autre opération, est gérée de la même manière : elle est acceptée par un ReceiveMessage, traitée par la logique du flux de travail, puis a répondu à l’aide d’un SendMessage.

Pourquoi la création d’une logique métier orientée service est-elle une bonne idée ? La réponse est évidente : elle permet de créer une application unifiée et évolutive. Plutôt que de demander à chaque opération de contenir des vérifications , est-il légal de m’appeler maintenant ? – cette connaissance est incorporée dans la logique de flux de travail elle-même. Cela facilite l’écriture de l’application et, tout aussi important, plus facile à comprendre pour les personnes qui doivent éventuellement la maintenir. Et plutôt que d’écrire votre propre code pour gérer la gestion de l’évolutivité et de l’état, le runtime WF effectue ces opérations pour vous.

Un service de flux de travail obtient également tous les avantages décrits précédemment, tout comme n’importe quelle autre application WF. Il s’agit notamment des éléments suivants :

  • L’implémentation de services qui effectuent un travail parallèle est simple : supprimez simplement les activités dans une activité parallèle.
  • Le suivi est fourni par le runtime.
  • Selon le domaine du problème, il peut être possible de créer des activités personnalisées réutilisables à utiliser dans d’autres services.
  • Le flux de travail peut être créé graphiquement, avec la logique de processus directement visible dans le concepteur de flux de travail WF.

L’utilisation de WF et WCF comme ceci — création de services de flux de travail — n’était pas si facile dans les versions antérieures de WF. Avec .NET Framework 4, cette combinaison de technologies se réunit de manière plus naturelle. L’objectif est de créer une logique métier dans ce style aussi simple que possible.

Exécution d’un service de flux de travail avec « Dublin »

Un problème important avec les flux de travail n’a pas encore été abordé : où s’exécutent-ils ? Le runtime WF est une classe, comme les activités. Toutes ces choses doivent s’exécuter dans un processus hôte, mais quel est ce processus ?

La réponse est que les flux de travail WF peuvent s’exécuter dans pratiquement n’importe quel processus. Vous êtes libre de créer votre propre hôte, même en remplaçant certains des services de base de WF (comme la persistance) si vous le souhaitez. Beaucoup d’organisations ont fait cela, en particulier les fournisseurs de logiciels. Pourtant, la création d’un processus hôte véritablement fonctionnel pour WF, avec des fonctionnalités de gestion, n’est pas la chose la plus simple dans le monde. Et pour les organisations qui veulent dépenser leur argent pour créer une logique métier plutôt que l’infrastructure, éviter cet effort est logique.

Une option plus simple consiste à héberger un flux de travail WF dans un processus de travail fourni par Internet Information Server (IIS). Bien que cela fonctionne, il fournit uniquement une solution nue. Pour faciliter la vie des développeurs WF, Microsoft fournit un code technologique nommé « Dublin ». Implémenté en tant qu’extensions pour IIS et le service d’activation de processus Windows (WAS), l’objectif principal de « Dublin » est de rendre IIS et WAS plus attrayant en tant qu’hôte pour les services de flux de travail. La figure 13 montre comment un service de flux de travail ressemble lorsqu’il s’exécute dans un environnement « Dublin ».

Figure 13 : « Dublin » fournit la gestion et bien plus encore pour les services de flux de travail.

Bien que la WF elle-même inclut des mécanismes permettant de conserver l’état, le suivi et bien plus encore d’un flux de travail, il fournit uniquement les bases. « Dublin » s’appuie sur la prise en charge intrinsèque de WF pour offrir un environnement plus utile et gérable. Par exemple, avec un magasin de persistance SQL Server et un magasin de suivi, « Dublin » fournit un outil de gestion pour l’utilisation de ces magasins. Cet outil, implémenté en tant qu’extensions au Gestionnaire des services Internet, permet à ses utilisateurs d’examiner et de gérer (par exemple, arrêter) les flux de travail persistants, de contrôler la quantité de suivi effectuée, d’examiner les journaux de suivi et bien plus encore.

Outre ses ajouts aux fonctionnalités existantes de WF, « Dublin » ajoute également d’autres services. Par exemple, « Dublin » peut surveiller l’exécution d’instances de flux de travail, en redémarrant automatiquement tout échec. L’objectif principal de Microsoft avec « Dublin » est clair : fournir un ensemble utile d’outils et d’infrastructure pour la gestion et la supervision des services de flux de travail hébergés dans IIS/WAS.

Utilisation d’un service de flux de travail dans une application ASP.NET

Il est probablement juste de dire qu’une majorité d’applications .NET utilisent ASP.NET. Rendre le flux de travail standard, alors, signifie rendre WF une option attrayante pour les développeurs ASP.NET.

Dans les versions antérieures de WF, les performances du flux de travail n’ont pas été suffisantes pour un nombre significatif d’applications ASP.NET. Pour la version .NET Framework 4, toutefois, les concepteurs de WF réécritaient les parties importantes de la technologie, ce qui améliore considérablement les performances. Cette version, ainsi que l’avènement de « Dublin », rend les applications basées sur WF, en particulier les services de flux de travail, une option plus viable pour les développeurs ASP.NET. La figure 14 montre une image simple de la façon dont cela ressemble.

Figure 14 : Une logique métier d’application ASP.NET peut être implémentée en tant que service de flux de travail

Dans ce scénario, ASP.NET pages implémentent uniquement l’interface utilisateur de l’application. Sa logique est entièrement implémentée dans un service de flux de travail. Pour le service de flux de travail, l’application ASP.NET n’est qu’un autre client, tandis qu’à l’application ASP.NET, le service de flux de travail ressemble à n’importe quel autre service. Il n’est pas nécessaire de savoir que ce service est implémenté à l’aide de WF et WCF.

Encore une fois, cependant, la grande question est, Pourquoi feriez-vous cela ? Pourquoi n’écrivez-vous pas simplement la logique de l’application ASP.NET de la manière habituelle ? Qu’est-ce que l’utilisation de WF (et WCF) vous achète ? À ce stade, la plupart des réponses à ces questions sont probablement évidentes, mais elles valent toujours la peine de répéter :

  • Au lieu de répartir la logique de l’application sur de nombreuses pages de ASP.NET différentes, cette logique peut être implémentée au sein d’un flux de travail unifié unique. En particulier pour les grands sites, cela peut rendre l’application beaucoup plus facile à créer et à gérer.
  • Au lieu d’utiliser explicitement l’état dans l’application ASP.NET, peut-être à l’aide de l’objet Session ou autre chose, le développeur peut s’appuyer sur le runtime WF pour effectuer cette opération. L’application ASP.NET n’a besoin que d’effectuer le suivi d’un identificateur d’instance pour chaque instance de workflow (probablement une par utilisateur), par exemple en la stockant dans un cookie. Lorsque l’application fournit cet identificateur à « Dublin », l’instance de workflow est automatiquement rechargée. Il commence ensuite à s’exécuter là où il s’est arrêté, avec tout son état restauré.
  • Les autres avantages de WF s’appliquent également, notamment le parallélisme plus facile, le suivi intégré, le potentiel des activités réutilisables et la possibilité de visualiser la logique de l’application.

Étant donné qu’un service de flux de travail n’est pas lié à un processus spécifique sur un ordinateur spécifique, il peut être équilibré sur plusieurs instances « Dublin ». La figure 15 montre un exemple de la façon dont cela peut ressembler.

Figure 15 : une application ASP.NET répliquée peut utiliser plusieurs instances « Dublin » pour exécuter un service de flux de travail.

Dans ce scénario simple, les pages d’une application ASP.NET sont répliquées sur trois ordinateurs serveur IIS. Bien que ces pages gèrent l’interaction avec les utilisateurs, la logique métier de l’application est implémentée en tant que service de workflow s’exécutant avec « Dublin ». Deux instances de l’environnement « Dublin » sont en cours d’exécution, chacune sur son propre ordinateur. Lorsque la première requête d’un utilisateur est entrée, un équilibreur de charge l’achemine vers l’instance supérieure d’IIS. La page ASP.NET qui gère cette requête appelle une opération dans le service de workflow qui implémente ce segment de logique métier. Cela provoque l’exécution d’un flux de travail WF dans l’instance « Dublin » sur l’ordinateur le plus haut de la figure. Une fois les activités pertinentes de ce flux de travail terminées, l’appel revient à la page ASP.NET et le flux de travail est conservé.

La deuxième requête de l’utilisateur est acheminée vers une autre instance d’IIS. La page ASP.NET sur cet ordinateur appelle à son tour une opération dans le flux de travail (persistant) sur un ordinateur différent de celui qui a traité sa première requête. Ce n’est pas un problème : « Dublin » charge simplement l’instance de workflow à partir du magasin de persistance qu’elle partage avec son collègue serveur. Ce service de flux de travail rechargé gère ensuite la demande de l’utilisateur, en choisissant là où il s’est arrêté.

Comprendre WF (et WCF), puis apprendre à créer une logique dans ce nouveau style prend du travail. Pour les applications de ASP.NET simples, l’escalade de cette courbe d’apprentissage peut ne pas mériter l’effort nécessaire. Toute personne qui crée des applications web plus volumineuses à l’aide de .NET doit toutefois envisager au moins la possibilité de créer sa logique en tant que service de flux de travail.

Utilisation de flux de travail dans les applications clientes

Jusqu’à présent, le focus a été entièrement mis sur l’utilisation de WF pour créer des applications serveur. Pourtant, bien que cette technologie soit la plus souvent utilisée aujourd’hui, WF peut également être utile pour les applications clientes. Ses aspects de scalabilité n’ajoutent généralement pas beaucoup dans ce cas, car le code qui s’exécute sur des ordinateurs clients n’a généralement pas besoin de gérer un grand nombre d’utilisateurs simultanés, mais WF peut toujours être utilisé.

Par exemple, pensez à une application cliente qui présente à son utilisateur une interface graphique créée à l’aide de Windows Forms ou de Windows Presentation Foundation. L’application aura probablement des gestionnaires d’événements pour traiter les clics de souris de l’utilisateur, en répartissant peut-être sa logique métier sur ces gestionnaires d’événements. Cela ressemble beaucoup à une application ASP.NET répartissant sa logique sur un groupe de pages distinctes, et peut créer les mêmes défis. Le flux de l’application peut être difficile à discerner, par exemple, et le développeur peut avoir besoin d’insérer des vérifications pour s’assurer que les choses sont effectuées dans l’ordre correct. Tout comme avec une application ASP.NET, l’implémentation de cette logique en tant que flux de travail WF unifié peut vous aider à résoudre ces problèmes.

D’autres aspects de WF peuvent également être utiles sur le client. Supposons que l’application doit appeler plusieurs services web principaux en parallèle, par exemple, ou peut tirer parti du suivi. Tout comme sur le serveur, WF peut aider à relever ces défis. Bien que la majorité des applications WF s’exécutent aujourd’hui sur des serveurs, il est important de reconnaître que ce n’est pas le seul choix.

Regardez plus près : La technologie de Windows Workflow Foundation

L’objectif de cette vue d’ensemble n’est pas de vous rendre développeur WF. Pourtant, savoir un peu plus sur la technologie de WF peut aider à décider quand il est judicieux de choisir le mode de flux de travail. En conséquence, cette section examine de plus près certaines des parties les plus importantes de WF.

Types de flux de travail

Dans le .NET Framework 4, les développeurs WF choisissent généralement entre deux styles de flux de travail différents en choisissant différentes activités à l’extérieur. Ces activités sont les suivantes :

  • Séquence : exécute des activités dans une séquence, l’une après l’autre. La séquence peut contenir des activités If, Tandis que les activités et d’autres types de flux de contrôle. Toutefois, il n’est pas possible de revenir en arrière : l’exécution doit toujours avancer.
  • Organigramme : exécute les activités l’une après l’autre, comme une séquence, mais permet également le contrôle de revenir à une étape antérieure. Cette approche plus flexible, nouvelle dans la version WF de .NET Framework 4, est plus proche de la façon dont les processus réels fonctionnent et de la façon dont la plupart d’entre nous pensent.

Bien que Sequence et Flowchart puissent agir comme les activités les plus externes d’un flux de travail, elles peuvent également être utilisées dans un flux de travail. Cela permet à ces activités composites d’être imbriquées de manière arbitraire.

Dans ses deux premières versions, WF incluait également une autre option pour l’activité la plus externe d’un flux de travail appelée State Machine. Comme son nom l’indique, cette activité permet à un développeur de créer explicitement un ordinateur d’état, puis d’avoir des activités de déclenchement d’événements externes dans cet ordinateur d’état. WF dans le .NET Framework 4 est un changement important, cependant, qui nécessite une réécriture de la plupart des activités dans les versions précédentes et la création d’un nouveau concepteur. En raison des efforts déployés, les créateurs de WF ne fournissent pas l’activité State Machine à partir de la version initiale du .NET Framework 4. (Même les ressources de Microsoft ne sont pas sans limite.) Toutefois, la nouvelle activité de diagramme de flux doit traiter une grande partie des situations précédemment requises à l’aide de l’ordinateur d’état.

Bibliothèque d’activités de base

Un flux de travail peut contenir n’importe quel ensemble d’activités qu’un développeur choisit d’utiliser. Il est tout à fait légal, par exemple, pour qu’un flux de travail contienne uniquement des activités personnalisées. Toujours, ce n’est pas très probable. La plupart du temps, un flux de travail WF utilise au moins certains éléments fournis dans la bibliothèque d’activités de base. Parmi les activités BAL les plus utiles fournies par WF dans le .NET Framework 4 sont les suivantes :

  • Assigner : affecte une valeur à une variable dans le flux de travail.
  • Compenser : permet d’effectuer une compensation, telle que la gestion d’un problème qui se produit dans une transaction de longue durée.
  • DoWhile : exécute une activité, puis vérifie une condition. L’activité est exécutée sur et au-dessus tant que la condition est vraie.
  • Organigramme : regroupe un ensemble d’activités exécutées séquentiellement, mais permet également au contrôle de revenir à une étape antérieure.
  • ForEach : exécute une activité pour chaque objet d’une collection.
  • Si : crée une branche d’exécution.
  • Parallèle : exécute plusieurs activités en même temps.
  • Persist : demande explicitement au runtime WF de conserver le flux de travail.
  • Choisir : autorise l’attente d’un ensemble d’événements, puis l’exécution uniquement de l’activité associée au premier événement.
  • ReceiveMessage : reçoit un message via WCF.
  • SendMessage : envoie un message via WCF.
  • Séquence : regroupe un ensemble d’activités exécutées séquentiellement. En plus d’agir comme l’activité la plus externe d’un flux de travail, Sequence est également utile dans les flux de travail. Par exemple, une activité While ne peut contenir qu’une autre activité. Si cette activité est Sequence, un développeur peut exécuter un nombre arbitraire d’activités dans la boucle while.
  • Commutateur : fournit une branche multidirectionnel d’exécution.
  • Levée : déclenche une exception.
  • TryCatch : permet de créer un bloc try/catch pour gérer les exceptions.
  • While : exécute une seule activité tant qu’une condition est true.

Il ne s’agit pas d’une liste complète : WF dans le .NET Framework 4 inclut plus. En outre, Microsoft prévoit de rendre les nouvelles activités WF disponibles sur CodePlex, son site d’hébergement pour les projets open source. Peu après la publication de .NET Framework 4, par exemple, recherchez des activités qui permettent aux flux de travail d’émettre des requêtes et des mises à jour de base de données, d’exécuter des commandes PowerShell, etc.

Comme le suggère cette liste, le BAL fait largement écho aux fonctionnalités d’un langage de programmation à usage général traditionnel. Cela ne devrait pas être surprenant, car WF est destiné à être une technologie à usage général. Comme cette vue d’ensemble a été décrite, toutefois, l’approche qu’elle prend , les activités exécutées par le runtime WF, peuvent parfois améliorer la vie pour les développeurs d’applications.

Flux de travail dans .NET Framework 4

La version 4 du .NET Framework apporte des modifications significatives à Windows Workflow Foundation. Les activités du BAL ont été réécrites, par exemple, et certaines nouvelles ont été ajoutées. Cela apporte des avantages réels : de nombreux flux de travail s’exécutent désormais beaucoup plus rapidement, par exemple, mais cela signifie également que les flux de travail créés à l’aide de versions antérieures de WF ne peuvent pas être exécutés par la version .NET 4 du runtime WF. Ces anciens flux de travail peuvent toujours s’exécuter en même temps que les flux de travail .NET Framework 4 inchangés, mais ils n’ont pas besoin d’être jetés. En outre, les activités créées à l’aide de versions antérieures de WF, y compris des flux de travail entiers, peuvent potentiellement s’exécuter à l’intérieur d’une nouvelle activité d’interopérabilité fourni par WF dans le .NET Framework 4. Cela permet d’utiliser la logique à partir de flux de travail plus anciens dans les nouveaux flux de travail.

Outre de meilleures performances, cette nouvelle version de WF apporte également d’autres changements intéressants. Par exemple, les versions antérieures de WF incluaient une activité de code qui pouvait contenir du code arbitraire. Cela permet à un développeur d’ajouter presque toutes les fonctionnalités souhaitées à un flux de travail, mais il s’agissait d’une solution légèrement inélégante. Dans le .NET Framework 4, les créateurs de WF ont considérablement simplifié l’écriture d’activités personnalisées, et l’activité code a donc été supprimée. De nouvelles fonctionnalités sont désormais créées en tant qu’activité personnalisée.

Les modifications apportées à la version .NET Framework 4 sont les plus importantes depuis l’apparence initiale de WF en 2006. Tous ont toutefois le même objectif : faciliter la création d’applications efficaces à l’aide de flux de travail.

Conclusion

Windows Workflow Foundation offre des avantages réels pour de nombreuses applications. Dans ses premières versions, WF a rencontré un accord principalement avec les fournisseurs de logiciels. Ces incarnations originales de la technologie étaient utiles, mais elles n’étaient pas vraiment appropriées pour l’utilisation standard de l’entreprise. Avec .NET Framework 4, les créateurs de WF cherchent à changer cela.

En rendant WF et WCF bien ensemble, améliorant les performances de WF, fournissant un meilleur concepteur de flux de travail et offrant un processus hôte complet avec « Dublin », Microsoft rend le flux de travail plus attrayant pour un plus large éventail de scénarios. Ses jours en tant que joueur spécialisé dans le drame de développement d’applications Windows dessinent à proximité. WF est sur son chemin pour centrer la scène.

À propos de l’auteur

David Chappell est principal de Chappell & Associates à San Francisco en Californie. Grâce à ses discours, à l’écriture et à la consultation, il aide les gens du monde entier à comprendre, utiliser et prendre de meilleures décisions sur la nouvelle technologie.