Archives mensuelles : mars 2013

image

Librairie FeatureFlags : Choix de conception

Je vous ai parlé il y a peu de l’utilisation des Feature Flags qui est une technique qui facilite la mise en place d’intégration continue, je vous avais alors indiqué que les différentes implémentations disponibles en .net ne me satisfaisait pas.

imageJ’ai donc débuté le développement d’une librairie appelée tout simplement FeatureFlags.

Avant de mettre le code à disposition sur codeplex, je vais donc partager vous les différents choix de design que j’ai effectué.

J’ai opté pour un principe simple afin de faciliter la maintenance des features : je souhaite que l’utilisation du principe soit le plus fortement typé possible afin que l’on puisse agir directement sur les différents emplacements dans le code où une feature est utilisée.

Ainsi toute suppression de feature (car plus utile, par exemple dans le cas d’une activation définitive), doit lever différentes erreurs de compilation afin de forcer le développeur à supprimer tout le code inhérent.

Niveau UI

Mon besoin étant uniquement orienté autour d’applications WPF, je me suis attardé uniquement sur ce type d’intégration.

L’objectif est de pouvoir afficher ou non n’importe quel contrôle WPF en fonction de l’état d’activation d’une fonctionnalité.

Pour une intégration simple et souple, j’ai opté pour l’implémentation d’une custom MarkupExtension.

Cette solution de lier très simplement une propriété Visibility à une Feature et permet également de rester fortement typé. Si la classe de définiton de la feature est supprimée, nous nous retrouverons avec une erreur de compilation XAML facilement détectable.

image

A noter la possibilité d’afficher des contrôles en fonction de la non activation d’une feature via la définition de la propriété IsEnabled (définie à True par défaut) :

image

D’un point de vue du rafraichissement, j’ai opté pour une récupération de l’état d’activation de la feature en “One Time” uniquement au moment de la récupération de la MarkupExtension. Cela signifie que si l’état d’activation change alors que la fenêtre parent est déjà chargé, l’UI ne sera pas impactée.

Niveau Code

D’un point de vue code, le flip se fait de manière très simple :

image

Je viendrais dans un prochain post sur la gestion de la persistence de l’état des features en base de données.

N’hésitez pas à me faire part de vos remarques sur ce design par rapport aux autres libraires du marché.

image

Gestion des évolutions grâce aux Feature Flags

Gérer correctement les évolutions dans un projet logiciel n’est pas simple car il faut arriver à gérer le cycle des releases qui en général est beaucoup plus rapide que le rythme de mise à disposition de certaines fonctionnalités qui prennent du temps à être développé.

Il est donc souvent nécessaire de mettre en place certains mécanismes permettant d’arriver à livrer très régulièrement une application “malgré” des développements en cours non finalisés.

Première principe et le plus populaire :

La mise en place de branching

Quelle que soit la stratégie de branching choisie (branche corrective + branche évolutive, branches par version, ou branches par fonctionnalité – je vous recommande d’ailleurs ce guide sur les différentes stratégies de branching que l’on peut mettre en place –), la mise en place de branches ajoute une surcharge de travail qui est gérable mais qui peut être conséquente.

Il y a bien évidemment la surcharge de travail pour les développeurs au niveau des merges entre les différentes branches, mais également une surcharge de travail d’un point de vue des tests.

Il est en effet nécessaire d’effectuer des tests sur la branche sur laquelle le développement a été effectué, mais également sur toutes les autres branches sur lesquelles les modifications vont être fusionnées.

Il s’agit donc d’une technique qui peut avoir un impact sur la vélocité des releases, sur le rythme de mise à disposition de nouvelles fonctionnalités.

Les feature flags

Autre principe plus léger à mettre en place : les feature flags.

imageLe principe est simple : afin d’être capable de gérer les évolutions, il suffit de développer les fonctionnalités et de les livrer même non finalisés dans les différentes releases mais de les désactiver afin de les rendre inacessibles aux utilisateurs.

Il suffira ensuite de les activer ou non directement au runtime par configuration, sans aucune modification de code et donc sans aucun déploiement lorsqu’on le souhaitera.

 

 

Plusieurs avantages à ce principe :

  • On ne ralentit pas la cadence des releases puisqu’on livre les fonctionnalités non terminées (qui resteront masquées)
  • On peut activer ou non certains certains fonctionnalités en fonction des différents clients (selon leur profil par exemple) afin de les faire participer à des phases de tests (alpha, beta, etc.)
  • On n’est capable de revenir en arrière en cas de problème car en général les feature flags doivent pouvoir être accompagnées de logique de rollback

Ce concept a été mis en place et mis en avant par les équipes de Flickr. Je vous invite d’ailleurs à consulter le post de fin 2009 présentant le principe et son application au site web flickr.

Le principe a été ensuite décrit par Martin Fowler via le pattern Feature Toggle.

Il existe différentes implémentations des feature flags dans l’ecosystème .net : FeatureSwitcher, FeatureToggle, NFeature

La plupart des librairies reposent sur le même principe : on active ou désactive les features de l’application en passant par le fichier de configuration de l’application.

D’un point de vue de la représentation des features au niveau du code, la plupart se basent sur des classes implémentant une interface ou une classe de base, ou alors via une Enum qui permet de lister celles-ci.

N’aimant pas particulièrement les fichiers de configuration (ils sont trop compliqués à maintenir, à faire évoluer), je vais bientôt revenir vers vous avec une nouvelle libraire permettant de gérer cela directement en base de données.

Stay tuned !

image

Team Foundation Server Build qui tombe aléatoirement

Problème :

Votre serveur de build (installé sur le serveur TFS 2012 ou sur une machine dédiée) tombe aléatoirement et se remet à marcher comme par magie tout seul quelques heures après.

Symptômes :

Lorsque le serveur de builds ne fonctionne plus, les builds s’”accumulent dans la queue, et les builds en cours n’avancent pas, et aucun log n’est disponible sur celles-ci.

Si on se connecte sur la console d’administration on se rend compte que le controller et l’agent sont dans un état assez étrange :

image

Lorsque l’on clique sur le lien Détails du service de build on se retrouve avec le message d’erreur suivant :

image

HTTP code 500: System.ServiceModel.ServiceActionException

 

Solution :

Pour comprendre pourquoi vous rencontrez le problème il faut se se rendre dans l’Event Log du serveur TFS et non sur celui du serveur de build.

Dans notre cas, nous avions le message suivant :

image

Un service WCF ne peut pas se monter car il y a moins de 5% de RAM disponible sur le serveur TFS, et cela impacte le serveur de build.

Un petit tour vers le Task Manager pour trouver le fautif :

image

SQL Server prenant beaucoup de RAM, il a suffit de limiter le volume de RAM MAX pris par celui-ci afin de résoudre le problème :

image

Problem solved !