Archives de catégorie : Développement

Comment fonctionne le versionning de base de données ?

J’ai récemment décrit comment mettre en place de l’intégration continue afin d’intégrer automatiquement les modifications de schéma de bases de données sur des bases de données de test par exemple.

On m’a à cette occasion très justement indiqué que j’aurais pu décrire comment fonctionne le versionning de base de données.

Je vais donc décrire via ce post comment gérer dans un SCM une base de données, et je vais l’illustrer via l’utilisation de RedGate SQL Source Control. Les principes fondamentaux restent identiques pour les autres outils de la catégorie.

Cet outil peut être utilisé avec différents SCM : SVN, Git, Mercurial et bien évidemment avec TFS.

Une fois installé, vous disposez d’un nouvel onglet dans SQL Server Management Studio, celui-ci vous permet d’effectuer les principales tâches de gestion de version d’une base de données :

  • Définition du lien avec le SCM de votre choix
  • Opérations Get Latest et Commit

Première étape à réaliser donc, établir le lien entre une base de données et votre SCM :

image

A noter que ce lien étant stocké sur la machine où il est réalisé, il doit être réalisé sur chaque poste de développement.

Une fois le lien effectué, RedGate SQL Source Control va scruter en continu les modifications effectuées sur votre base de données. Il sera ainsi capable de vous indiquer les modifications effectuées lorsque vous souhaiterez faire un commit.

Le développeur peut donc effectuer les modifications qu’il souhaite sur sa base et va ensuite être capable de faire un commit dans le source control de ses modifications.

A noter qu’afin d’être capable de stocker les informations de schémas d’une base de données dans n’importe quel SCM il faut être capable de créer un ou plusieurs fichiers représentant ce schéma.

La plupart des outils de versionning de bases de données fonctionne de la même manière.

Un des objectifs de la mise en place de versionning étant la capacité de recréer from scratch une BDD propre, les outils crééent un script de création de chaque “objet” (Table, Vue, Procédure stockée, Trigger, etc.) et stockent ces fichiers dans le repository.

Ainsi le premier commit effectué depuis RedGate génère la structure suivante dans le source control :

image

Un petit tour dans le dossier de définition des tables et nous retrouvons notre table de test stockée sous forme de fichier .sql :

image

Ce fichier SQL contenant le script de création de la table avec l’ajout du champ et de la clé primaire :

image

A chaque modification de schéma, l’outil de versionning de BDD va ainsi générer le même script de création mis à jour en fonction des modifications de schéma effectuées. Ainsi un ajout de champ “nom_test” génère une nouvelle version du fichier Test.sql :

image

 

Vous retrouverez également ces scripts directement dans SQL Source Control lorsque vous effectuerez un GetLatest :

image

Bien évidemment, lorsque l’on effectue ce GetLatest, RedGate SQL Source Control ne vas pas bêtement remplacer la table en exécutant directement le script de création présent dans le source control mais il va générer un script de modification adéquat  afin de préserver les données présentes :

image

Cette génération de requête à partir du diff de deux requêtes de création est d’ailleurs la seule partie complexe de ce type de logiciels.

Oubliez DropBox, de vrais outils gratuits de gestion de sources existent !

C’est avec une grande surprise que j’ai découvert il y a quelques jours l’annonce du support de DropBox pour les déploiements dans Windows Azure.

Proposer le support de TFS, de git ou de mercurial d’accord, mais DropBox ?!?

Dropbox : sauvegardez, synchronisez et partagez facilement, en toute sécurité.

DropBox étant un “simple” espace de stockage sur le cloud, j’avais du mal à croire que certains développeurs l’utilisent en tant que repository de source, et pourtant cela semble bien être le cas.

DropBox propose en effet un outil de synchro qui permet de directement mapper un dossier local vers l’espace de stockage DropBox.

Certains développeurs l’utilisent donc comme certains pouvaient utiliser un dossier partagé pour gérer leurs sources.

J’avoue être complètement surpris que l’on puisse encore utiliser ce type de système même pour des tout petits développements.

La plupart des outils de gestion de sources sont gratuits, nécessitent peu d’apprentissage, et ont un coût d’utilisation (=surcharge de travail) très très très faible.

Même Microsoft fournit ce type d’outil gratuitement :

Vous pouvez en effet côté serveur mettre en place un TFS Express pour des équipes de 5 personnes max, ou encore sans aucune installation utiliser TFS Service.

Côté client, Team Explorer 2012 et un coup de PowerTools (bon ok sur ce coup là l’install est pas vraiment très légère…) permet de gérer n’importe quel fichier directement depuis l’explorateur de fichiers et de bénéficier de bien de fonctions qu’un simple rollback de fichiers :

  • la gestion des changesets : pour quelle raison (=commentaire sur le changeset) a été modifié un fichier (ou un ensemble de fichiers) par qui et quand,  et quel a été le diff exact
  • permet de savoir quels sont les fichiers en cours de modification et par qui, et support des merge en cas de modification multiple
  • Gestion “nommée” de versions de source via des labels
  • etc.

Je ne vais pas vous le faire le coup du Allo ?!? Non mais allo, quoi… Mais vraiment utiliser DropBox comme gestionnaire de source me parait vraiment être d’un autre âge même pour toutes les petites structures et pour les petits projets.

Intégration Continue de BDD avec SQLCompare de RedGate

Nous utilisons SQL Source Control de RedGate pour le gérer le versionning de nos bases de données ainsi que SQLCompare afin de générer les scripts de mise à jour d’une version à une autre. Cette solution est en effet peu coûteuse et à mon sens plus simple à utiliser que les outils proposés par Microsoft.

L’objectif de la mise en place d’intégration continue est d’arriver à déployer de manière automatique toutes les modifications sur une base de données destinée aux tests.

Pour notre scénario exemple, j’ai donc une base de données DBTest liée au source control, et une base de données DBTest_CI non liée au source control et qui sera automatiquement mise à jour par le serveur de builds (celle-ci peut évidemment être sur un autre serveur) :

image

Pour arriver à impacter la base DBTest_CI à chaque checkin d’une modification sur la base versionnée, il est donc nécessaire de créer un processus de build en intégration continue :

image

Une fois le processus de build défini, il est nécessaire de rajouter une tâche au processus de build : cette tâche permettra d’appeler SQL Compare selon le principe suivant :

image

SQL Compare ne va pas effectuer un compare entre le source control et la base de données d’intégration mais entre le dossier de scripts présent sur le source control et cette même base.

Pour cela nous allons utiliser le fait que le processus de build par défaut un getlatest pour directement récupérer la dernière version des scripts SQL.

Pour avoir de souplesse dans les modifications du processus de builds je préfère souvent externaliser les commandes à réaliser via un fichier .bat ou un fichier powershell. L’intêret est que le développement en est beaucoup plus simple (plus besoin de fait un checkin/checkout de la définition de la build à chaque modification), l’inconvénient est que cette définition n’est donc pas versionnée.

Vous pouvez donc utiliser cette technique dans vos phases de définition/personnalisation de de builds et ensuite pousser vos modifications sur le source control une fois que vous avez terminé pour garder les avantages des deux solutions.

Pour lancer la commande vous pouvez utiliser l’activité InvokeProcess et spécifier en argument de la commande à lancer les informations souhaitées :

image

De plus comme vous pouvez le voir, afin d’avoir un retour dans le log de la build, j’ai placé une activité WriteBuildMessage au niveau de la gestion de l’output ce qui permettra d’avoir une tracabilité au niveau des actions effectuées.

Concernant mon .bat donc, la commande est assez simple :

SNAGHTML61b1df96

J’indique à SQL Compare d’utiliser le dossier de scripts SQL qui a été getlatesté par le processus de build, j’indique ensuite les informations de connexion au second serveur. A noter que j’utilise l’authentification SQL afin de me simplifier la vie. Le paramètre /sync indique enfin à SQL Compare de directement exécuter le résultat du compare pour synchroniser les deux sources de données.

Le résultat est que lorsque l’on checkin un ajout d’un nouveau champ dans une table de la base DBTest :

image

Une nouvelle build se déclenche automatiquement :

image

Build qui a pour effet d’automatiquement intégrer les modifications sur la base d’intégration continue :

imageimage

Critique : Continous Integration in .net

Comme indiqué dans le titre de l’ouvrage, ce livre traite de la mise en place du principe d’intégration continue au sein de projets .net.

Pour rester général, les auteurs évoquent cette mise en place via 3 environnements : CruiseControl.net, Team Foundation Server et Team City.

Le message distillé au long des plus de 300 pages est clair, la mise en place d’intégration continue ne nécessite pas un investissement financier important (peut être gratuit via les 3 produits cités sous différentes conditions), il nécessite un investissement en montée en compétence, et en temps d’implémentation qui va très vite être rentabilisé.

Gestion des sources, compilation, feedback, mise en place de tests, analyse statique via FxCop, StyleCop et NDepend, gestion des changements de schéma de BDD, génération de projets de setup, et génération de documentation, tous les sujets techniques sont évoqués et décris de manière pratique.

Le parti pris d’évoquer les 3 environnements à certainement pesé sur le fait que l’ouvrage ne décrit pas en profondeur les fondamentaux, ne donne pas la part belle à “la théorie”, au pourquoi du comment, ni aux concepts associés (les feature flags par exemple).

Continuous Integration in NET est un bon ouvrage pour les débutants en intégration continue qui souhaite se mettre de manière pratique via un des 3 environments cités ci-dessus. Ceux d’entre vous qui maitrisent déjà les notions de base et qui cherchent un ouvrage de référence préférerons passer le chemin et se diriger vers un ouvrage plus théorique.

FeatureFlags : Initial Checkin sur CodePlex

Comme indiqué dans le titre, je viens de faire un premier checkin de mon état d’avancement de la librairie de gestion de FeatureFlags sur CodePlex.

image

Vous pouvez accéder au portail du projet à cette adresse : http://featureflags.codeplex.com

Pour rappel du scope actuel :

  • Création de Feature
  • Gestion de Flip au niveau code ou au niveau UI (WPF uniquement)
  • Persistence de l’état des features dans une base SQL Server

Je vais très prochainement faire une vraie application de démo pour montrer l’utilisation de librairie ainsi que la documentation pour montrer comment étendre le stockage de l’état des features.

Toutes les remarques, idées, critiques sont les bienvenues ! N’hésitez pas à m’en faire part via l’issue tracker du projet directement sur CodePlex.

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é.

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 !

Forcer les developpeurs a mettre des commentaires de changesets pertinents

Ecrire des commentaires de checkins pertinents fait parti  des tâches simples que l’on a du mal à faire comprendre et accepter des équipes.

Les tâches non liées à l’écriture de code mais qui sont là pour faciliter la maintenance des applications (via dans le cas présent une meilleure traçabilité des modifications effectuées) sont il est vrai souvent considérées par les développeurs comme des tâches moins importantes, moins prioritaires, des tâches de seconde classe.

Par fainéantise, ou par désintérêt on se retrouve le plus souvent avec ce type de commentaire :

image

Des commentaires (lorsqu’ils sont présent ce qui n’est pas le cas pour le changeset 7817) qui n’ont aucune valeur.

Le problème est important puisque cela conduit à ce genre de choses :

image

Un historique de fichier inutilisable  où on ne sait pas ce qui s’est passé sauf à passer beaucoup de temps à faire des compare entre chaque changeset.

Lors d’une discussion avec un responsable ALM, celui-ci m’indiquait qu’il n’arrivait pas à arriver à ce type de résultat :

image Un résultat certes imparfait mais quand même de qualité, avec des information utiles qui pourront être consultées dans le futur.

Pour parvenir à cela, et bien évidemment après avoir expliqué à l’équipe en quoi il est important de placer des commentaires pertinents, j’ai été obligé de passer en mode “dictateur”, et TFS propose une solution simple pour y arriver : les alertes.

Afin “d’encourager” les membres d’une équipe il suffit de se créer une alerte sur tous les checkins lié à un Team Project :

image

Une fois le mail d’alerte reçu, sachez qu’il est possible de directement répondre à ce mail afin de communiquer avec le développeur. – Je vous invite à consulter cet ancien post qui décrit le process -.

Ainsi vous pouvez réagir très rapidement à ces mauvais commentaires en demandant au développeur fautif de modifier à posteriori son commentaire afin qu’il soit pertinent.

Après avoir reçu plusieurs mails de rappel à l’ordre demandant de corriger le problème, les plus récalcitrants rentrent ainsi dans le bon chemin sur une période de temps assez courte (environ 1 mois dans mon cas).

La détection de doublons de code – Tips #3 Bis

Je vous présentais hier la fonctionnalité de détection des doublons de code proposée par Visual Studio 11, je vous propose aujourd’hui un rapide retour d’expérience sur l’utilisation de cette fonctionnalité sur un vrai projet avec un bon volume de code (620 000 lignes).

image

L’analyse du code a pris 3h30. Le temps d’analyse pour un aussi gros volume de code est certes important mais ne me choque pas plus que cela. Je suis plutôt surpris par le fait que la machine ne soit pas “à genoux” durant l’analyse mais ne soit occupé qu’à  20% au niveau du CPU sachant qu’il ne semble pas y avoir d’autres goulots d’étranglements (mémoire, disque).

Les résultats sont classés en 4 catégories : exact match, strong match, medium match, weak match.

L’analyseur indique que 25% du code semble être du doublon (et peut donc être quasi-supprimé suite à du refactoring) soit dans mon cas plus de 150 000 lignes de code. Je sais que le code est très loin d’être optimisé et qu’il y a beaucoup de redondance de code mais ce résultat est pour le moins plutôt étrange…

J’ai vite été conforté dans mon impression en analysant la qualité des résultats. J’ai commencé l’étude par l’analyse des weak match.

Je n’ai pas réussi à trouver un résultat à peu près pertinent dans les weak match.

Un des exemples typiques concerne ce type de code :

image

Le moteur d’analyse prend en compte uniquement le texte et non pas le vocabulaire en lui-même et trouve donc des clones qui ne sont pas du tout pertinents.

Autre exemple avec l’initialisation “en masse” d’objets, l’affichage de ce type de résultat n’est pas forcément pertinent :

image

image

 

Les bonnes nouvelles se retrouvent plutôt au niveau des correspondances exact ou très voisines :

image

J’ai été ainsi surpris de découvrir qu’un même bloc de code a été repris 58 fois ( ! ) au sein de l’applicatif.

Une séance de refactoring va donc pouvoir être planifié afin d’éliminer cette redondance ainsi que les suivantes.

En résumé, cette nouvelle fonctionnalité est plus proche de l’analyseur de texte que de l’analyseur de code car le vocabulaire n’est pas pris en compte de manière pertinente. Et il ne faut pas se fier au grand nombre de résultats potentiels affiché mais faire un filtre et une analyse de ceux-ci afin de décider des actions à mener pour améliorer la qualité du code.

La détection de Copier Coller–Tips #3

Afin de lutter contre les copier coller intempestif et plus généralement d’aider à trouver des blocs de code identiques ou très proches, Visual Studio 11 propose une fonctionnalité de détection de clone de code.

Si l’on prend un exemple simple :

image

Un clic sur le menu Analyze, Analyze Solution for Code Clones permet de lancer une analyse sur le code source de l’intégralité de la solution et d’afficher un nouveau panneau :

image

Il est ensuite possible de naviguer dans les blocs de code détectés afin de refactorer et donc d’améliorer la qualité du code.

A noter que l’outil ne permet pas d’uniquement trouver les blocs de code strictement identique mais permet de faire des analyses légèrement plus poussées. Le nommage des variables n’est par exemple pas pris en compte, si la structure du code est voisine avec des noms de variables différents, la fonctionnalité sera capable de trouver des résultats pertinents.

Point qui peut être intéressant, l’analyse se fait bien sur le code source et non sur l’IL, il n’est donc pas nécessaire que le code compile pour lancer la détection (oui, je sais; c’est tordu mais c’est toujours bon à savoir Sourire).

Inconvénient, l’analyse se faisant sur la structure du code source, l’outil n’est pas capable de détecter du code identique  fonctionnellement mais pas syntaxiquement.

Par exemple le code suivant ne renvoie aucun résultat :

image

A noter que la fonctionnalité ne se concentre que sur des blocs d’une 10 de lignes de code uniquement, les blocs plus petits ne sont pas détectés.

De plus; il est possible de lancer une analyser afin de rechercher des clones d’un bloc de code en particulier. Il suffit pour cela de le sélectionner et de sélectionner le bon élément dans le menu contextuel pour y parvenir.

Et sur du vrai code ? J’ai lancé l’analyse sur l’application sur laquelle je travaille (plusieurs centaines de milliers de lignes de code) et j’attends le résultat depuis 2 heures !

Grosse déception, le moteur d’analyse ne semble à priori pas multithreadé. Sur mon quad-coeur, le process de VS 11 tourne en moyenne à 20%, la consommation mémoire reste à peu près stable, et les accès disque sont faibles. Le CPU semble donc être le goulot d”étranglement…

image

Après 2 heures d’analyse, cela progresse lentement… mais surement… Je mettrais à jour ce post si cela se termine un jour ! Sourire