dimanche 19 avril 2009

La fabrique de fabrique de fabrique

Ce post est une traduction de Why I Hate Frameworks, pour ceux chez qui l'anglais ne pose aucun soucis, je vous conseille de lire ce post dans sa langue native, certainement mieux rédiger que je ne l'ai fait.

J'ai décidé d'arrêter de faire le geek toute la journée sur mon pc et aujourd'hui je veux faire ma propre petite cabane en bois dans mon jardin et j'ai une idée sur les outils qu'il me faut c'est à dire : une scie et un marteau.
Grâce à cette cabane je pourrais programmer dehors pendant l'été, et je pourrai leur faire voir que même les geeks prennent l'air de temps en temps.

Je vais au magasin d'outillage le plus proche et je décide de demander à la vendeuse où est-ce que je peux trouver un marteau.

"Un marteau ?, plus personne n'en n'achète, c'est démodé."
Surpris je lui demande une explication.
"Le problème c'est qu'il existe différent type de marteau :
Le menuisier
Le marteau de mécanicien
Le marteau de maçon ou boucharde
Le manteau de couvreur ou asseau ou assette
Le marteau d'accordeur
etc...
Que se passe t'il si vous achetiez un type de marteau et puis que vous réalisiez que vous avez besoin d'un autre marteau plus tard ? Vous devez acheter un nouveau marteau pour la prochaine tâche. De nos jours, les gens veulent un marteau tout en un, un marteau couteau suisse."

"Pas bête ! Pouvez vous m'indiquer ou se trouve le marteau couteau suisse ?"

"Non nous n'en vendons plus, c'est démodé."

"Vous venez juste de dire que le marteau couteau suisse était l'outil du futur..."

"Le soucis c'est que le marteau couteau suisse peut tout faire mais il est médiocre pour tout... Planter un clou avec un marteau pour les juges, c'est pas top."

"C'est vrai, donc si vous ne vendez plus le marteau couteau suisse, quels sont les types de marteau que vous vendez ?"

"On ne vend plus de marteau du tout... D'après nos recherches, ce que les gens ont réellement besoin n'est pas un marteau couteau suisse. C'est toujours mieux d'avoir le bon type de marteau pour la tâche à accomplir. Donc ce que nous vendons est une fabrique de marteau, vous employez des travailleurs, fournissez les matières premières et ne vous occupez plus de rien, la fabrique s'occupera de vous fournir exactement le marteau adapté à vos besoins."

"Oui, mais je n'ai pas envie d'acheter une fabrique..."

"Ca tombe bien, nous n'en faisons plus c'est obsolète... Nous avons découvert que beaucoup de personnes ne voulaient pas acheter une fabrique, donc nous avons pensé à faire une fabrique de fabrique. Vous fournissez les schémas des marteaux, et notre fabrique créer une fabrique pouvant créer vos marteaux. Vous n'avez plus besoin de trouver des travailleurs, des experts, et fournir la matière première..."

"Laissez moi deviner... Vous n'en vendez plus"

"En effet, pour certaines raisons peu de personnes voulaient acquérir la fabrique de fabrique de marteau... Je les comprends, imaginez que vous devez gérer à la fois une fabrique de fabrique de scie, une fabrique de fabrique de marteau, une fabrique de fabrique de niveau à bulle... On s'est dit que cela devenait trop complexe à gérer quand nous ne voulions qu'un marteau..."

"Sans blague ?!"

"Alors cette semaine nous avons inventé une fabrique de fabrique de fabrique ! Vous avez une fabrique, vous spécifiez votre outils (un marteau) et il vous crée votre fabrique de fabrique de marteau ! De cette façon vous n'avez plus qu'une fabrique et si vous voulez juste un marteau, vous déployez un fichier de configuration et pressez un bouton, et vous avez votre marteau."

"Donc vous n'avez aucun marteau ? tout le monde fait comme cela maintenant ?"

"Non, si vous voulez de la haute qualité vous ne pouvez pas vous permettre d'avoir qu'un marteau dans votre boîte à outils, et vous ne pouvez pas vous permettre d'acheter tout les marteaux sur terre, d'où l'avantage de la fabrique de marteau et ..."

"Oui j'ai compris, j'ai compris, si c'est comme ça que ça marche, je pense qu'il ne me reste plus qu'à apprendre..."

"Bonne chance !"

"Il y a un mode d'emploi fourni avec ?"

mercredi 15 avril 2009

Pourquoi faut-il éviter une carrière dans le développement ? Vraiment ?!

Quand j'étais petit, mon héros dans james bond goldeneyes, aussi étonnant que cela puisse paraître, était Boris.
Boris était un programmeur au service des méchants, le stéréotype du geek (et il meurt congelé à la fin), il me passionnait car je me disais : c'est dingue, grâce à ses connaissances, et non pas grâce à son costard ni à son coup de pied retourné, il arrive à mettre des bâtons dans les roues de James Bond, et même les méchants se reposent sur Boris! Peut-être qu'au final avons nous aussi plus de chance de devenir un Boris qu'un James Bond... bref j'aimerais bien devenir Boris, à la différence près que je ne travaillerai pas sous la contrainte du revolver du méchant. Je travaillerai car mon boulot est fun !

Flanant sur StackOverflow un jour de printemps ensoleillé je suis tombé sur ce lien :
Why a career in computer programming sucks ?.

Il ne voit visiblement pas Boris comme moi, peut être n'a-t'il pas revu James Bond GoldenEyes pendant son cours de science informatique... Insultes ! Je ne peux même pas exprimer ma rage car les commentaires sont fermés.

Pour tout étudiants hésitant à se lancer dans la voie du développement, je vais essayer de répondre à vos interrogations.

"Après 10 ans passé à coder devant mon ordinateur pourrais-je être fier de moi ? être un avocat, un manager, un médecin, un scientifique, un chef d'entreprise est tout de même plus glorieux !"
C'est la question que se pose beaucoup de lycéens, particulièrement car les métiers cités sont très valorisés en France.

La réussite professionnelle n'est pas un événement, vous êtes en réussite qu'à partir du moment où vous passez chaque minutes de votre vie à vous dire : "J'aime ce que je fais, et en plus je suis payé pour ! Et dire qu'il existe encore des personnes qui passent 60% de leur vie dans un bureau à attendre que chaque minutes passent pour rentrer chez eux !". L'orientation vers une carrière n'est pas une histoire de logique, mais une histoire de coeur.

"Les programmeurs sont des "techniciens", on en trouve en Inde, je vaux plus que ça !"
Commençons à changer le terme de "programmeur" en "développeur".
La différence entre les deux est que l'un est plus spécialisé que l'autre, cependant ça ne veut absolument pas dire qu'un développeur ne doit pas être bon voir excellent en programmation !
Pour reprendre mon lien, voici les compétences que doivent avoir les développeurs en plus :

-Faire les specifications
-Gérer les configurations (build automatique, serveur d'intégration, code coverage etc...)
-Revue de code
-Tests
-Tests unitaires
-Documentation
-Résoudre les problèmes difficiles des clients

Hélas, les cours ne nous apprennent qu'à devenir programmeur (qui est difficile en soit), on ne nous apprend qu'à coder ! Le développement c'est plus que ça.
Première chose à savoir dans le développement : Vous êtes responsable de votre réussite, aucune certification, aucun nom d'école, aucun titre, ne fera votre réussite, vous devez apprendre par vous même comment devenir développeur et apprendre beaucoup de choses essentielles que l'on ne vous apprend pas à l'école.
Et vous devez aimer ça.
Lisez, Lisez, Lisez, et devenez un expert en quelque chose avant de pouvoir vous dire généraliste. Ne lisez pas n'importe quoi, cherchez sur internet les meilleurs livres.
Dans le développement il y a beaucoup de chemin à emprunter où vous pouvez vous démarquer des autres, ça peut être dans une plateforme comme le java ou le .net (avec les framework associés, EJB,WCF,WPF,EJB,Hibernate,les design patterns), ça peut être dans la programmation de bas niveau (débugger windows à coups de Windbg, connaitre les tuyauterie de windows ou linux sur le développement du noyau).
Vous pouvez aussi vous démarquer sur un domaine particulier comme la BI ou les jeux videos.
Seulement après, vous pourrez pensez à vous généraliser (ce qui devient de moins en moins difficile au fur et à mesure que l'on apprend).
Cependant vous apprendrez toute votre vie, et si le développement est fait pour vous ce n'est pas une contrainte mais un avantage ! Je dirais même qu'une entreprise qui n'utilise pas les nouvelles technologies et qui ne nous demande pas d'être à jour est ennuyeuse.
Peu de métiers nous permettent d'apprendre tout les jours, et contrairement à ce que dit cette essai, les connaissances temporaire représente à peine 10 à 20% de ce que vous apprenez.

Vos connaissances de développement seront souvent couplé à d'autre domaine d'expertise. Si vous faites un moteur physique, vous devez apprendre la physique, et la maîtriser parfaitement, si vous faites un logiciel de traitement d'image, si vous faites des logiciels comptables, partout il faudra que vous appreniez le métier de la personne à qui vous voulez rendre la vie meilleur. Et c'est notre boulot ! Rendre la vie meilleur aux personnes qui utiliseront notre logiciel, comment peut on réussir à le faire si l'on n'apprend pas le métier de vos clients ?

Autre compétence fondamentale du développeur : savoir communiquer, j'apprends à communiquer à travers ce blog, et mon rôle de formateur.
"Pourquoi devoir communiquer ? un programmeur est un geek devant un pc sans relation avec le monde extérieur !"... Peut être le programmeur ,et encore j'ai un doute, mais le développeur doit savoir communiquer car il est en contacte avec beaucoup d'acteurs.
En tant que développeur, nous devons nous montrer diplomate (ou pas) avec le client pour savoir ce qu'il veut et pour apprendre son jargon, son métier.

Nous devons aussi parler à notre une équipe, il faut savoir ne pas vexer ses camarades et apprécier tout le monde. C'est un atout essentiel si vous voulez que votre vie de tout les jours soit radieuse (et peut être pas forcément qu'en développement).
Rien de pire qu'une équipe qui ne s'entend pas car dans ces cas là le seul remède est d'aller voir ailleurs.

L'auteur de l'essai, stipule qu'il n'existe aucune différence entre un programmeur de 60 ans d'expérience et un autre de 5 ans d'expérience. Oui c'est le cas pour le programmeur mort... un programmeur Elvis ou Einstein avec 5 ans d'expérience sera même jusqu'a 10x plus productif que le mort et cela quelque soit l'age.

"The working conditions suck" je vous direz que cette affirmation n'est pas totalement fausse, c'est le cas quand on travaille chez EA Games par exemple.
Une chose à faire si vous tombez sur un entreprise pourri : fuir.
Quand vous êtes bon, et vous le deviendrez si vous aimez votre métier, vous trouverez TOUJOURS un autre boulot.
Allez voir mon autre post pour savoir pourquoi en général les éditeurs logiciels ont de meilleurs conditions de travail que les autres entreprise (banques, SSII,...).

Si vous n'aimez pas votre travail, vous ne serez pas compétent, et par conséquent si vous avez pu arriver dans cette entreprise, d'autre personnes qui n'aiment pas leur métier sont aussi présentes et travailleront avec vous. Le seul moyen de travailler dans une bonne boîte et d'être libre c'est de devenir bon, car une bonne entreprise ne prend que des personnes qui sont compétentes et aiment ce qu'elles font. (Ou du moins elles essayent)

Les mauvais ont alors tendance à se regrouper au sein d'une même entreprise, comme le font les bons (cf Peopleware).

Apparemment c'est ce qui s'est passé pour l'auteur de cet essai.

La plus belle des virtues du développement c'est le pouvoir de construire ses idées en lignes de code. Vous ne vous imaginez pas le nombre de chose que l'on peut accomplir, toutes les idées nous passant par la tête faisable par un ordinateur, nous pouvons le réaliser.
Au fur et à mesure que l'on développe on commence à se rendre compte que nous ne sommes plus limité à cause d'un language ou d'un framework, nous devenons limité par notre capacité à cerner clairement ce que l'on veut faire, et à SIMPLIFIER les choses.
Le bon développeur est la personne qui recherche à faire toujours plus simple, et c'est pour cela que nous devons continuer à apprendre ! Nous ne sommes limité que par notre abilité à simplifier un problème, et c'est seulement en acceptant les faiblesses de notre cerveau que l'on apprendra tout les jours de nouvelles choses, "je suis trop bête pour réfléchir voyons ce qu'à fait quelqu'un de plus intelligent que moi". C'est pour cela que nous n'avons pas peur d'apprendre la physique quand nous créons un moteur physique, c'est pour cela que nous n'avons pas peur d'apprendre la comptabilité quand nous développons un logiciel de gestion. L'apprentissage n'est rien de plus qu'un ensemble modèles à assimiler qui guide notre pensée vers des solutions plus simple (beaucoup de personnes très talentueuses et intelligentes ont probablement résolues votre problème d'une façon beaucoup plus élégante que vous ne l'auriez fait).

Apprendre toute sa vie n'est pas une contrainte mais une opportunité.

dimanche 12 avril 2009

Casser la dépendance temporelle ! Un pas vers le multi-threading

Je me lève un matin de printemps, les oiseaux chantent et le ciel et bleu, comme tout bon geek, je ferme alors les volets, la lumière étant trop éblouissante et le boucan des oiseaux m'empêchant de réfléchir à des choses plus fondamentales ("Qu'est ce que je vais bien pouvoir coder aujourd'hui ?")... j'allume mon PC et visual studio 2008 team system : team suite (EN x86)... Me voilà d'attaque !

Je pense faire quelque chose de révolutionnaire... disons une fenêtre en WPF avec un titre ! Elle suffira à me faire comprendre...
Bref, je vais utiliser le pattern MvvM, je ne jure que par ça, mais n'ayez crainte ceux qui ne connaissent pas, je vais garder mon exemple à la portée de tous.

Voici mon ViewModel (la donnée qui sera affichée dans ma fenêtre) :

public interface WindowViewModel

{

  string Title

  {

    get;

  }

}



Rien de sorcier, j'ai utilisé une interface pour découpler ma vue de ma couche métier qui va être accéder par l'intermédiaire d'une implémentation de cette interface. (Mediator)

On va tester ça !
Pour cela je crée un faux ViewModel :

public class FakeViewModel : WindowViewModel

{

  public string Title

  {

    get

    {

      return "Hello";

    }

  }

}



Et je le bind à ma fenêtre.

Window1 window = new Window1();

window.ViewModel = new FakeViewModel();

window.Show();



Pour ne pas dérouter ceux qui ne sont pas habitué au C# je ne détaille pas la création de la propriété ViewModel de ma Window1, et le binding du XAML.

Pas de soucis jusqu'à ici j'ai bien Hello en titre de ma fenêtre. Je vais passer aux choses sérieuse ! Faire une vrai implémentation de ViewModel qui dialoguera avec mon Model.

Voici mon Model :

public class BusinessObject

{

  private string _ShortDesc;

  public event EventHandler ShortDescriptionChanged;

 
  public BusinessObject()

  {

    _ShortDesc = "Description par défaut";

  }

  public String ShortDescription

  {

    get

    {

      Thread.Sleep(2000);

      return _ShortDesc;

    }

    set

    {

      if(_ShortDesc != value)

      {

        _ShortDesc = value;

        if(ShortDescriptionChanged != null)

          ShortDescriptionChanged(this, EventArgs.Empty);

      }

    }

  }

}




Il a une seule propriété et un événement qui se déclenche quand cette propriété se met à jour,
cependant l'accès au Get prend deux secondes.
Et mon voici ViewModel :

public class BusinessViewModel : WindowViewModel, INotifyPropertyChanged

{

  private BusinessObject _Bo;

  private string _Title;

 
  public BusinessViewModel(BusinessObject bo)

  {

    _Bo = bo;

    _Bo.ShortDescriptionChanged += new EventHandler(_Bo_ShortDescriptionChanged);

    _Title = _Bo.ShortDescription;

  }

 
  void _Bo_ShortDescriptionChanged(object sender, EventArgs e)

  {

    Title = ((BusinessObject)sender).ShortDescription;

  }

 
  public string Title

  {

    get

    {

      return _Title;

    }

    private set

    {

      if(value != _Title)

      {

        _Title = value;

        if(PropertyChanged != null)

          PropertyChanged(this, new PropertyChangedEventArgs("Title"));

      }

    }

  }

 
  public event PropertyChangedEventHandler PropertyChanged;

}



Il s'abonne à l'événement du changement de description de l'objet du model, et met à jour son titre en conséquence.

Je modifie l'instanciation de ma Window1 :

Window1 window = new Window1();

//window.ViewModel = new FakeViewModel();

BusinessObject bo = new BusinessObject();

window.ViewModel = new BusinessViewModel(bo);

window.Show();

bo.ShortDescription = "Hello";



Tout est beau dans le meilleur des mondes, mon code fonctionne, la fenêtre s'affiche après deux secondes et deux secondes après son titre change en "Hello".
Sauf que ma fenêtre a pris deux secondes à se lancer et mon interface a freezé deux secondes de plus juste après.

Vous seriez peut être prêt à régler le problème à coup de thread/lock/BackgroundWorker et compagnie ! Je vous arrête là... je ne veux pas que mon code devienne compliqué à comprendre et subtile à débugger. Si vous avez déjà essayé de faire des tests unitaires sur une classe qui gére plusieurs threads, je compatis, ce n'est pas drôle et ça ne donne pas envie de vivre.

Notre problème vient du couplage temporelle entre mon objet métier et mon ViewModel, c'est à dire que nous supposons que les 2 objets sont dans le même thread.

Il suffit de découpler les deux objets de façon explicite dans notre design.
Nous allons accéder à notre BusinessObject via un délégué, et notre ViewModel possédera un Dispatcher courant, nous nous en serviront pour traiter les appels du thread du BusinessObject à notre ViewModel.

Voici un Dispatcher :

public interface IDispatcher

{

  void BeginInvoke(Delegate method, params Object[] args);

}



Et voila l'implémentation du dispatcher pour WPF, puis l'implémentation du dispatcher qui sera non couplé à WPF et synchrone (il sera utilisé dans les tests unitaires).

public class SynchronizedDispatcher : IDispatcher

{

  public void BeginInvoke(Delegate method, params object[] args)

  {

    method.DynamicInvoke(args);

  }

}

 
public class WpfDispatcher : IDispatcher

{

  private Dispatcher _WpfDispatcher;

  public WpfDispatcher(): this(null)

  {

  }

  public WpfDispatcher(Dispatcher wpfDispatcher)

  {

    _WpfDispatcher = wpfDispatcher ?? Dispatcher.CurrentDispatcher;

  }

  public void BeginInvoke(Delegate method, params object[] args)

  {

    _WpfDispatcher.BeginInvoke(method, args);

  }

}

 


Maintenant voyons comment découpler temporellement nos deux classes.

public class DispatchedBusinessViewModel : WindowViewModel, INotifyPropertyChanged

{

  private String _Title;

  private readonly IDispatcher _CurrentDispatcher;

  private Action<Action<BusinessObject>> _Bo;

 
  public DispatchedBusinessViewModel(Action<Action<BusinessObject>> businessObject, IDispatcher currentDispatcher)

  {

    _CurrentDispatcher = currentDispatcher ?? new WpfDispatcher();

    _Bo = businessObject;

    _Bo((bo) =>

    {

      string shortDesc = bo.ShortDescription;

      _CurrentDispatcher.BeginInvoke(new Action(() =>

      {

        Title = shortDesc;

      }));

      bo.ShortDescriptionChanged += new EventHandler(bo_ShortDescriptionChanged);

    });

  }

 
  void bo_ShortDescriptionChanged(object sender, EventArgs e)

  {

    BusinessObject bo = (BusinessObject)sender;

    string newTitle = bo.ShortDescription;

    _CurrentDispatcher.BeginInvoke(new Action(() =>

    {

      Title = newTitle;

    }), null);

 
  }

 
  public DispatchedBusinessViewModel(Action<Action<BusinessObject>> businessObject)

    : this(businessObject, null)

  {

  }

 
  //Identique

  public string Title

  {

    get

    {

      return _Title;

    }

    private set

    {

      if(value != _Title)

      {

        _Title = value;

        if(PropertyChanged != null)

          PropertyChanged(this, new PropertyChangedEventArgs("Title"));

      }

    }

  }

  public event PropertyChangedEventHandler PropertyChanged;

}



L'astuce réside dans le fait que l'on accède à notre BusinessObject qu'à partir d'un  Action<Action<BusinessObject>>. Si on souhaite utiliser notre BusinessObject nous devons fournir une methode à executer qui prendra le BusinessObject en paramètre. Tout le code à l'intérieur de cette méthode n'est pas garantie d'être dans le même thread que le ViewModel. On se sert du dispatcher courant de notre ViewModel pour appeler une méthode dans le même thread que notre ViewModel (ici on met à jour le titre de notre ViewModel).

En clair on utilise Action<Action<BusinessObject>> pour faire un appel du thread du ViewModel au thread du Model, et on utilise le IDispatcher pour faire un appel du thread du Model au thread ViewModel.

Il est important de ne pas ajouter une méthode à sémantique synchrone à notre interface IDispatcher, car il y aurait des risque de deadlock.

L'intérêt de cette technique est que notre ViewModel n'est pas chargé de gérer dans quel thread s'execute notre objet métier (dans notre premier exemple, il s'en chargé dans son propre thread).
De cette manière nous pouvons facilement utiliser un Dispatcher synchrone pendant les tests unitaires, et un dispatcher Wpf dans notre application.

Exemple voici notre ViewModel en test unitaire :

[TestMethod]

public void ShouldMapTitleToShortDescription()

{

  BusinessObject bo = new BusinessObject();

  Action<Action<BusinessObject>> action = (act) =>

  {

    act(bo);

  };

  bo.ShortDescription = "Desc1";

  DispatchedBusinessViewModel vm = new DispatchedBusinessViewModel(action, new SynchronizedDispatcher());

  Assert.AreEqual("Desc1", vm.Title);

  bo.ShortDescription = "Desc2";

  Assert.AreEqual("Desc2", vm.Title);

}



Pour WPF, premièrement je déclare mon action (la méthode qui déclenchera la méthode passé en paramètre dans le thread du bo), et je l'initialise dans le thread du BusinessObject :

Action<Action<BusinessObject>> action = null;

 
Thread boThread = new Thread(() =>

{

  BusinessObject bo = new BusinessObject();

  Dispatcher boDispatcher = Dispatcher.CurrentDispatcher;

  action = (act) =>

  {

    boDispatcher.BeginInvoke(act, bo);

  };

  Dispatcher.Run();

});

boThread.Start();



Puis j'instancie mon ViewModel avec l'action en paramêtre du constructeur, par défaut le ViewModel utilisera le dispatcher courant de WPF, donc je n'ai pas à le spécifier.

Window1 window = new Window1();

window.ViewModel = new DispatchedBusinessViewModel(action);

action((bo) =>

{

  bo.ShortDescription = "new desc";

});




Mission accomplie ! ;)

mercredi 8 avril 2009

ISV Forever !

De ma petite expérience, de mes recherches sur le net et de mes bouquins de dev, l'endroit où l'air est le plus frais et l'herbe est la plus verte se situe chez les ISV (éditeur de logiciel indépendant).

Dans notre carrière de développeur nous sommes confronté à 4 choix différents :

-Travailler chez un ISV,
-Travailler dans une SSII,
-Travailler dans une entreprise dont le coeur de métier n'est pas l'informatique,
-Etre freelance

Je vais ici juste comparer un ISV avec une SSII.
Je me suis posé la question des raisons pour lesquelles l'herbe serait plus verte chez les ISV, et je crois avoir trouvé la réponse !

Tout d'abord un rappel sur comment fonctionne une web farm dans l'entreprise X !

-La requète de l'utilisateur transite sur le réseau et arrive à un routeur configuré par X pour répartir la charge sur toute la farm de X.
-La requête est traité par un des serveurs et la réponse est renvoyé au client.

Maintenant si un de vos serveurs dans la farm tombe, il n'y a aucun soucis, d'autres serveurs sont là, et vous avez vos 99.999% de disponibilité (5.2 min par an)! Au pire des cas vous perdez la requête HTTP de l'utilisateur, mais si c'est important vous pouvez router la requête qui a échouée vers un autre serveur disponible !

Remplacez Utilisateur par Client, web farm par Equipes (au pluriel), entreprise X par SSII, requête par cahier des charges et nous y sommes. Je récapepette depuis le début !

"Tout d'abord un rappel sur comment fonctionne les équipes dans une SSII !
-Le cahier des charge du client transite par la poste, par mail, par téléphone, sur un torchon, jusqu'à une personne du "upper management" qui se charge de répartir le travail à toutes les équipes de la SSII.
-Le cahier des charge est traité par une des équipes et le logiciel est livré au client.

Maintenant si une équipe parmis d'autre échoue, il n'y a aucun problème, d'autres équipes sont là, et vous arrivez quand même à vous occuper de tout vos clients. Au pire des cas le projet échoue, mais si c'est important vous pouvez confier ce projet à une autre équipe."

Dans une SSII le turnover des employés n'impacte qu'une seul équipe, et surtout qu'un seul projet, tout comme vos serveurs web dans la farm, les équipes sont "stateless" dans le sens où quand un projet est terminé on peut facilement remplacer l'équipe ou un membre sans mettre en péril la SSII.
C'est grâce à ça que le travail est aussi parallélisable, les équipes sont indépendantes entre elles, les projets le sont aussi, le risque est minimisé !

Qu'en est t'il du turnover ressenti par un ISV ? Il est beaucoup plus cher et plus risqué !
L'analogie de la web farm ne tient pas pour un ISV, car il ne reçoit pas de projet venant de l'extérieur.
Une équipe chez un ISV n'est pas stateless ! Les connaissances requises pour les développeurs ISV, sont non seulement techniques mais aussi métiers.
Et comme chez les SSII lorsqu'un projet est en cours l'équipe ne peut plus être considérée comme stateless.
La différence est qu'un projet dans une ISV est moins "volatile" que dans une SSII, on y passe sans doute plus de temps on l'améliore, on s'y passionne, ce projet est peut être même le seul qui maintient l'ISV vivant. Et en réalité l'ISV réutilise les même compétences métiers à travers plusieurs projets à la fois. (Ce genre d'entreprise se spécialise souvent sur un domaine d'expertise précis)

Nous sommes entrain de perdre cette indépendance entre les équipes et entre les projets !

Je reviens sur une affirmation non détaillée que j'ai faite au dessus :
"Et comme chez les SSII lorsqu'un projet est en cours l'équipe ne peut plus être considéré comme stateless",
Il est facile d'affirmer cela, car toute tentative d'ajout de personnes sur un projet déjà en cours peut retarder ce projet plus que de l'avancer, cette effet est d'autant plus élevé que la date du début du projet est lointaine (à cause de la learning curve des nouveaux et de leur intégration à l'équipe qui fait perdre du temps aux autres membres). "The mythical Man-Month" explique ces phénomènes certainement mieux que moi ! :)
Ce phénomène se fait ressentir lors du départ d'un membre d'une équipe pendant un projet, plus le membre fait partie du projet depuis longtemps plus son départ se ressent car la connaissance et l'expertise qu'il a accumulé sont perdues.

Si vous ne pouvez pas supprimer un composant comme vous le feriez sur un serveur d'une web farm, ça signifie que ce composant n'est plus "stateless" le coût de son remplacement sera plus cher que le coût absolu de ce composant.

La différence c'est que pour une SSII ce coût est réduit quasiment à néant à la fin du projet.

Si le coût du turnover dans une SSII est inférieur à celui d'un ISV, ça signifie que l'ISV fera plus d'effort pour garder ses employés le plus longtemps possible, car les connaissances accumulées deviennent inestimables.
C'est peut être pour cela qu'il doit être bon de travailler chez Google et Microsoft !

samedi 4 avril 2009

Gare aux homonymes !

Imaginez que vous êtes le programmeur du système d'information d'Amazon.
Evidement vous pensez faire une classe Livre qui a un auteur et un titre, mais puisque c'est un article destiné à la vente peut être seriez vous tenter d'ajouter un prix.

C'est l'échec ! Ceci signifie que si vous changez le prix d'un livre vous devez changer le prix de TOUT livre et aussi si je n'ai plus de livre, je n'aurais plus accès aux prix des livres ni au nom de l'auteur ni au titre du livre, car je n'en n'aurais plus en stock. Je vous embrouille ? c'est normal dans la phrase précédente je viens d'utiliser 2 homonymes vous les avez trouvé ? "Livre" et "Livre".

Dans un cas je parle d'une oeuvre littéraire, dans l'autre je parle d'une copie physique de cette oeuvre.

Surtout ne faites pas une classe nommée LivreDescription, qui renseignera sur le prix d'un livre, le titre et le nom de l'auteur.

Bien que l'intention soit louable, vous manquez l'occasion d'enrichir le vocabulaire exprimé par le design (UbiquitousLanguage).
Votre classe est enfet une OeuvreLitteraire (non pas un LivreDescription), vous serez capable de mieux communiquer avec les experts métiers, et votre compréhension du domaine évolue !

Votre classe Livre pourra aussi s'appeller CopiePhysique, elle représentera un livre physique, qui pourra être traçer individuellement (date d'impression, de sortie du stock etc...)

Vous venez de dissocier nos deux homonymes! (ou plutôt vous venez de vous rendre compte du mauvaise usage du mot Livre dans la language française)
Il est fou de constater que sur un exemple aussi bête et un domaine aussi simple on puisse déjà faire des erreurs de design.

Le bon développeur doit devenir aussi un expert métier si il veut faire un bon design (dans notre cas on aurait peut être du se renseigner sur le vocabulaire du bibliothécaire !).

Source : TypeInstanceHomonym