Archive for avril, 2008

Alt.net: première rencontre française

Julien on avr 30th 2008

La toute première rencontre Alt.net aura lieu ce soir à Paris, à l'initiation de Robert Pickering.
C'est à 20h00 au « frog and rosbif », 116 rue st. Denis, 75002.

Tout le monde est le bienvenu!

Mais qu'est ce que Alt.net?
Alt.net est une communauté de développeurs passionnés par l'amélioration de la façon dont l'on développe des logiciels. Alt.net reconnait qu'il n'y a pas de solution unique mais qu'il y a une multitude d'alternatives qui peuvent être appliquées à des situations différentes. Alt.net est un endroit pour partager ces alternatives, afin de pouvoir, ensemble, apprendre, expliquer et partager ces nouvelles idées.

Autrement dit, vi vous êtes:

  • un développeur qui utilise ce qui fonctionne tout en gardant un œil sur de meilleurs solutions
  • un développeur qui est prêt a regarder ailleurs pour adopter le meilleurs d'autres communautés: Open Source, Agile, Java, Ruby, etc.
  • un développeur qui ne se satisfait pas du status quo. Les choses peuvent toujours être améliorées, plus élégantes, plus simple, etc.
  • un développeur qui reconnait que les outils sont très utiles mais qu'ils ne peuvent pas tout faire. Ce sont les grands principes et le savoir qui comptent réellement. Les meilleurs outils sont ceux qui forcent le savoir et encourage ces principes (par exemple, Resharper)

Alors, Alt.net est fait pour vous!

Qui est derrière Alt.net?
Alt.net est un mouvement initié par David Laribee et ses confrères de Codebetter. Depuis Avril 2007, le mouvement s'est considérément agrandi avec la participation de très nombreux MVP, employés de microsoft ou de grands noms de l'informatique.

En quoi Alt.net diffère d'autres groupes d'utilisateurs?
Alors que la plupart des groupes d'utilisateurs cherchent à promouvoir des outils et des technologies, Alt.net est plus orienté sur le process de développement en lui même.

Quel est l'objectif des rencontres françaises d'Alt.net?
Il n'y a d'objectif affiché, je me contenterai donc de vous dire le mien:
rencontrer des gens qui se retrouvent dans les principes cités ci-dessus afin de pouvoir établir des canaux de communication en français. Pour le moment, Alt.net a eu un écho considérable aux Etats-Unis et dans de nombreux pays, mais la France est resté en retard.

Enfin, permettez-moi d'insister sur le fait que cette réunion est sans prétention :). Tout le monde est le bienvenue, pas besoin d'être expert en je ne sais quoi ou d'avoir un blog :). Un groupe s'est d'ailleurs créé sur Google, c'est tout neuf et donc très vide mais n'hésitez pas à passer!

Filed in Rencontres Alt.net | 4 responses so far

Comment vérifier qu’une chaine de caractère est vide de façon optimale?

Julien on avr 25th 2008

J'ai eu l'occasion de m'apercevoir qu'il y avait un certain besoin autour de trucs et astuces sur .NET. Je vais donc dorénavant essayer de poster ce qui me passera par la tête :). A noter que ces billets ont vocation à être court et couvrir des points très précis!

Comment vérifier qu'une chaine de caractère est vide de façon optimale?

Il existe plusieurs façon de faire la comparaison:
1) myString == ""
2) myString == String.Empty
3) myString.Length == 0
4) String.IsNullOrEmpty(myString)

La façon la plus performante est la solution 3, myString.Lengh == 0, à condition d'être sur que la chaine de caractère n'est pas nulle. Si la chaine de caractère peut potentiellement être nulle, String.IsNullOrEmpty(myString) est idéal. A noter d'ailleurs que String.IsNullOrEmpty(myString) utilise lui même string.Length == 0. En voici l'implémentation en guise de référence:

  1. public static bool IsNullOrEmpty(string value)
  2. {
  3. if (value != null)
  4. {
  5. return (value.Length == 0);
  6. }
  7. return true;
  8. }

Filed in .NET, Trucs et Astuces | No responses yet

3 acronymes pour améliorer la qualité de votre code

Julien on avr 25th 2008

Pour ce premier billet d'une longue série (je l'espère du moins) sur les bonnes pratiques de développement, les méthodes agiles, et les valeurs défendues par Alt.Net, je vous propose de vous faire (re)découvrir 3 acronymes qu'il convient d'appliquer quotidiennement.

DRY - Don't Repeat Yourself:
L'acronyme DRY se traduit en français par "Ne vous répétez pas". Autrement dit, cet acronyme rappelle qu'il ne faut pas avoir des lignes de code identiques dupliquées à plusieurs endroits. En effet, les blocs de codes dupliqués devrait être déplacés dans une fonction ou dans une classe afin de pouvoir être réutilisables partout ailleurs. DRY permet donc une plus grande abstraction et diminue la complexité. La maintenabilité de l'application est aussi améliorée dans le sens ou les modifications du code n'auront plus à être reporté à différents endroits.

KISS - Keep It Simple, Stupid:
En développement, il est simple de faire compliqué et compliqué de faire simple! KISS, qui se traduit par "Gardez le code simple, stupide" rappelle ce grand principe. Malheureusement, il n'y a pas de recette miracle pour appliquer KISS. Il faut par exemple garder un code explicite, un niveau d'abstraction correct, ne pas optimiser prématurément, utiliser des patterns reconnus plutôt que de réinventer la roue, utiliser la composition plutôt que l'héritage pour réduire la taille des classes et promouvoir la réutilisation (DRY!), ou encore adopter la "programmation basé sur les interfaces" et l'inversion de contrôle. Evidemment, cette liste est non exhaustive et chaque point mériterait son propre billet!

YAGNI - You're Ain't Gonna Need It!:
YAGNI, ou, en français, "Vous n'allez pas en avoir besoin!" est une pratique très chére aux méthodes agiles. Le but avoué de YAGNI est d'éviter de développer quoique ce soit qui ne soit pas nécessaire maintenant. Quelques exemples:

  • il ne sert à rien de développer des fonctionnalités qui n'ont pas été demandées par les utilisateurs, sous peine de faire quelque chose de complètement inutile et de perdre son temps.
  • Attention de ne pas inventer quelque chose d'extrèmement puissant/modulaire/extensible/(ajouter votre mot ici) par rapport au besoin (KISS!). Attendez que le besoin se manifeste réellement pour commencer à développer quelque chose de plus complexe. Si vous le faites trop tôt, il est tout à fait possible que les priorités changent en cours de route et que tout soit rendu bancal par de nouveaux développements.
  • N'optimisez pas prématurément, sous peine de passer des heures à gagner 100ms sur une partie du système qui sera en fin de compte modifiée 2 semaines plus tard.

En résumé: DRY! KISS! YAGNI!

Filed in Alt.net Foundations | One response so far

Impact du mot cléf readonly sur les performances

Julien on avr 22nd 2008

Un collègue de travail m'a dit que le mot clef readonly permettait d'optimiser les accès mémoire et par conséquent l'accès se faisait plus rapidement qu'un membre classique (sans le mot clef readonly). Je dois avouer que cette affirmation m'a un peu surpris. J'aurai d'abord parié sur des performances identiques avec ou sans ce mot clef (Ce serait juste une vérification du compileur, qui ne modifie en rien l'exécution); puis, si cette première théorie s'avérait fausse, sur un accès mémoire plus lent (La CLR pourrait faire des vérifications lorsqu'elle essaye d'accéder au membre). Voyons donc si je me trompe!

Malheureusement pour moi, je n'ai trouvé aucune source pour confirmer ou non mes théories... J'ai donc décidé de réaliser mon propre micro-benchmark.

J'ai mesuré le temps nécessaire pour exécuter 3 principaux scénarios, avec un membre en lecture seule (readonly) puis avec un champs en lecture écriture (donc sans readonly):
- Scénario 1: Création d'un objet
- Scénario 2: Accès à un membre d'un objet
- Scénario 3: Création d'un objet et accès à un membre

j'ai exécuté ce code 1 000 000 000 de fois pour chaque scénario, et j'ai lancé chaque scénario 10 fois de suite sur 4 PC différents afin d'avoir une moyenne représentative. Pour chaque test, j'ai exclus le résultat le plus rapide et le plus lent.
Le code de mes tests (en C# et .NET 2.0) est disponible ici (Le code est dupliqué pour chaque test. Je sais que c'est horrible, toutes mes excuses :)), et les résultats sont .

Chaque test ressemble à cela (avec quelques modifications évidemment):

  1. _streamWriter.WriteLine();
  2. _streamWriter.WriteLine("Obj creation & access in loop");
  3. for (int j = 0; j < _numberOfTestExecutions; j++)
  4. {
  5. Poco poco = new Poco();
  6.  
  7. Stopwatch watch = new Stopwatch();
  8. watch.Start();
  9. for (int i = 0; i < _numberOfIterationPerTest; i++)
  10. {
  11. ReadOnlyField objReadOnlyField = new ReadOnlyField(poco);
  12. Poco myCopyOfPoco = objReadOnlyField.Poco;
  13. }
  14. watch.Stop();
  15. _streamWriter.Write(watch.ElapsedMilliseconds + ";");
  16.  
  17. watch.Reset();
  18. watch.Start();
  19. for (int i = 0; i < _numberOfIterationPerTest; i++)
  20. {
  21. ReadWriteField objReadWriteField = new ReadWriteField(poco);
  22. Poco myCopyOfPoco = objReadOnlyField.Poco;
  23. }
  24. watch.Stop();
  25. _streamWriter.WriteLine(watch.ElapsedMilliseconds);
  26. }

Voici les chiffres bruts:

Scénario 1: Création d'un objet
- lecture seule: 25172ms
- lecture écriture: 24983ms
La création d'un objet avec un membre en lecture seule est en moyenne 0.76% plus lent.

Scénario 2: Accès à un membre d'un objet
- lecture seule: 6437ms
- lecture écriture: 6449ms
L'accès à un membre en lecture seule est 0.19% plus rapide

Scénario 3: Création d'un objet et accès à un membre
- lecture seule: 19929ms
- lecture écriture: 19761ms
La création avec un membre en lecture seule puis l'accès au membre est en moyenne 0.85% plus lent

Cependant, Il est possible de voir des différences plus significatives en regardant les résultats pour chaque PC. Par exemple, sur le premier PC sur lequel j'ai fait le test (un core 2 duo, 2,8Ghz, DDR2 800Mhz), J'ai les résultats suivants:

- Scénario 1: Création d'un objet
La création d'un objet avec un membre en lecture seule est en moyenne 5.72% plus rapide qu'avec un membre en lecture écriture.
- Scenario 2: Accès à un membre d'un objet
L'accès à un membre en lecture seule est 0.94% plus rapide.
- Scenario 3: Création d'un objet et accès à un membre
La création avec un membre en lecture seule puis l'accès au membre est en moyenne 2.28% plus rapide.

Et sur un portable (centrino 1,7ghz, DDR):
- Scenario 1: Création d'un objet
La création d'un objet avec un membre en lecture seule est en moyenne 5.72% plus lent qu'avec un membre en lecture écriture.
- Scenario 2: Acces à un membre d'un objet
L'accès à un membre en lecture seule est 0.21% plus rapide.
- Scenario 3: Création d'un objet et accès à un membre
La création avec un membre en lecture seule puis l'accès au membre est en moyenne 3.01% plus lent.

Mes (propres) conclusions:
Il semblerait qu'il y ait une différence de performances non négligeable lorsque l'on utilise le mot clef readonly. Le problème est que cet impact est très dépendant du matériel sur lequel le logiciel tourne. Sur un PC avec du matériel décent, accéder à un membre en lecture seule est entre 1% et 2.5% plus rapide qu'accéder à un champs en lecture écriture. Quand à la création d'un objet, elle peut être jusqu'à 6% plus rapide. Sur du matériel plus ancien, les résultats sont inversés.
Cependant, les tests ont été exécutés avec une classe très simple, gardez donc en mémoire que dans le réalité, les différences constatées pour la création d'objets seraient probablement beaucoup moins importantes avec des classes qui ont plus de membres.

A ce stade, j'exclurai donc d'utiliser le mot clef readonly à des fins d'optimisation, sauf peut être dans des cas de figures très précis, et seulement après avoir vérifié qu'il y a effectivement un gain de performance sur les machines qui feront tourner le logiciel. A moins que votre application soit:
- installé que sur un nombre limité de machines, dans un environnement contrôlé et homogène
- pseudo temps réel ou extrêmement sensible aux performances
je ne pense pas que vous devriez considérer l'impact du mot clef readonly sur les performances. Il y a probablement des centaines d'optimisations qui seront plus efficaces!

Enfin, si vous avez constaté des résultats différents, n'hésitez pas à me le faire savoir et j'éditerai ce billet en conséquence :).
Je suis particulièrement intéressé par des benchmark avec des processeurs Xeon (malheureusement, je n'en ai pas sous la main).

Filed in .NET | No responses yet

Gardez vos objets dans un état consistent

Julien on avr 12th 2008

Une part d'un bon design orienté objet est de s'assurer que ses objets sont toujours dans un état correct.

Par exemple, dans le monde de la finance, nous avons des instruments financiers appelés "Dérivés". D'après Wikipedia:

Un produit dérivé est un instrument financier dont la valeur fluctue en fonction de l'évolution du taux ou du prix d'un produit appelé sous-jacent.

Par conséquent, dans le monde réel, un produit dérivé ne peut exister sans la présence du produit sous-jacent. Un future sur le CAC 40 n'aurait pas pu être créé sans que le CAC 40 existe auparavant. Si nous voulons représenter un produit dérivé dans une application, nous devons donc nous assurer que nous suivons la même règle.

Assumons que nous avons la classe suivante:

  1. class Derivative
  2. {
  3. private string _name;
  4. private Instrument _underlyingInstrument ;
  5.  
  6. public string Name
  7. {
  8. get { return _name; }
  9. }
  10.  
  11. public Instrument UnderlyingInstrument
  12. {
  13. get { return _underlyingInstrument; }
  14. }
  15.  
  16. public Derivative(string name, Instrument underlyingInstrument)
  17. {
  18. _name = name;
  19. _underlyingInstrument = underlyingInstrument;
  20. }
  21. }

Un nouveau développeur arrivant sur un projet associera notre classe Derivative au concept financier associé. A priori, il n'aura pas besoin de regarder le code de la classe et il s'attendra à ce que la propriété UnderlyingInstrument retourne un objet non-null. Cependant, l'implémentation courante de le garanti pas. En réalité, cette classe peut actuellement être utilisé pour véhiculer le nom d'un dérivé sans l'associer à son produit sous-jacent. Si nous voulions faire cela, nous devrions alors créer une nouvelle classe dans ce but uniquement. En attendant, si nous voulons que notre code reste dans un état maintenable, nous devons nous assurer que chaque objet de type Derivative sera construit correctement. Sans cela, chaque personne pourra faire un usage différent et potentiellement incompatible de la classe.

Dans le cas présent, s'assurer que notre objet est dans un état correcte peut se faire très facilement. Nous devons juste appliquer une pincée de "Design By Contract". Notre constructeur deviendra alors:

  1. public Derivative(string name, Instrument underlyingInstrument)
  2. {
  3. if(name == null || name.Length == 0)
  4. {
  5. throw new Exception("The name of the derivative can't be null or empty");
  6. }
  7. else if(underlyingInstrument == null)
  8. {
  9. throw new Exception("A derivative must have an underlying instrument");
  10. }
  11.  
  12. _name = name;
  13. _underlyingInstrument = underlyingInstrument ;
  14. }

Maintenant, nous sommes certain qu'un collègue développeur ne va pas utiliser la classe de façon étrange :)

Évidemment, il est possible d'améliorer cet exemple de façon significative avec différents frameworks et techniques (ce qui inclus l'appel à Debug.Assert ou le développement de sa propre classe d'assertion). Par exemple, J'écrirai idéalement le code de la façon suivante:

  1. public Derivative(string name, Instrument underlyingInstrument )
  2. {
  3. Guard.Against(name == null, "The name of the derivative can't be null");
  4. Guard.Against(name.Length == 0, "The name of the derivative can't be empty");
  5. Guard.Against(underlyingInstrument == null, "The underlying instrument of the derivative can't be null");
  6.  
  7. _name = name;
  8. _underlyingInstrument = underlyingInstrument;
  9. }

Mais c'est un sujet pour un autre billet!

Filed in Alt.net Foundations | No responses yet

Les nombres magiques

Julien on avr 10th 2008

Le code suivant est familier? rien de vous choque?

  1. persistAtIteration = 25000/iterationDurationInMilliseconds;

Si oui, vous êtes en flagrant délit d'utilisation d'un "nombre magique" :), c'est à dire un nombre sorti de nulle part sans aucune explication. Dans le cas ci-dessus, le but de la ligne de code est apparemment de savoir à quelle itération le programme doit réaliser une opération de persistance. Le code est simple et les 2 variables ont des noms plutôt expressifs. Mais la ligne contient aussi le nombre "25000" qui:
- Ne véhicule aucun sens.
- Ne peut pas être réutilisé à travers la classe
- Ne peux pas être modifié simplement (il est "masqué" au milieu du code et à moins de connaitre la valeur exacte, on ne peut pas la chercher simplement)

Modifions légèrement le code par le suivant:

  1. persistAtIteration = persistEachMilliseconds/iterationDurationInMilliseconds;

Désormais, la signification de la ligne est devenu évidente. persistEachMilliseconds indique que l'on veut faire l'opération de persistance toutes les X millisecondes. On le divise par la durée de l'itération pour savoir a quelle itération l'opération doit être réalisée. Le code est devenu bien plus clair!

A noter également que l'utilisation des nombres 0, 1 et -1 est toléré sans qu'il y ait besoin de passer par une variable intermédiaire. C'est notamment vrai pour les boucles for par exemple. Cela peut aussi être le cas d'autres nombres comme dans l'expression suivante qui test si i est un nombre pair: if(i % 2 == 0). C'est donc au programmeur de faire la part des choses.

La littérature sur les nombres magique est très vaste et le sujet a été couvert des centaines de fois. Il n'y clairement a rien de nouveau! Pourtant, chaque projet contient sont lot de nombres magiques, d'où l'écriture de ce billet!

Remarque:
Lorsque vous exprimez des durées, je vous conseille de systématiquement ajouter l'unité au nom de la variable. Soit xxxInSeconds, xxxInMinutes, xxxInDays, etc. Sans cela, il sera nécessaire de vérifier où la variable est utilisé pour savoir quelle est l'unité requise.

Filed in Qualité du code | No responses yet

AutoResetEvent vs ManualResetEvent: Attention!

Julien on avr 7th 2008

J'ai effectué quelques tests de montée en charge il y a quelques jours sur le composant sur lequel je travaille. Malheureusement, je me suis rapidement rendu compte que les performances étaient simplement misérables... Le soft était à peine capable de traiter 60 messages par secondes, ce qui était: 1) mauvais et 2) surprenant! (En résumé, c'est une petite brique logiciel qui fait une sorte de transformation/redirection/cache de messages en temps réel)

J'ai donc passé quelques minutes dans DotTrace afin d'avoir un aperçu de l'exécution. J'ai rapidement trouvé que dans le thread qui observait la queue et envoyait les messages, j'avais utilisé une instance de ManualResetEvent à la place de AutoResetEvent.

Si vous ne les avez jamais utilisé, ces 2 classes permettent d'envoyer des signaux entre 2 threads. De cette façon, le thread qui observe la queue ne consomme pas de ressources bêtement tant que le thread qui remplit la queue n'envoie pas un signal pour prévenir qu'il y a quelque chose à récupérer. Par exemple, le thread 1 attendra que la queue soit remplie de la façon suivante:

  1.  
  2. private AutoResetEvent mySignal = new AutoResetEvent(false);
  3.  
  4. private void MonitorQueue()
  5. {
  6. while(!monitorQueue)
  7. {
  8. mySignal.WaitOne();
  9. GetItemsInTheQueueAndDoStuff();
  10. }
  11. }

Et le thread 2 injectera des données avec:

  1.  
  2. public void EnqueueItem(Item myItem)
  3. {
  4. InsertInQueue(myItem);
  5. mySignal.Set();
  6. }
  7.  

Comme je l'ai dis, mon problème venait du fait que j'avais utilisé par erreur une instance de ManualResetEvent à la place de AutoResetEvent. Ces 2 classes sont quasiment identiques, excepté que lorsque vous utilisez ManualResetEvent, vous devez reseter le signal manuellement avec mySignal.Reset(). Dans mon cas, à la place de bloquer sur mySignal.WaitOne(), le code bouclait en permanence et consommait une quantité de CPU très importante.

J'ai corrigé le problème et relancé mon test de performance: je suis maintenant à 5000 messages par secondes et à moins de 40% de CPU. Bien mieux!

Filed in .NET | No responses yet

lock(this): A ne pas faire!

Julien on avr 5th 2008

J'ai vu ce genre de choses dans plusieurs bouts de code récemment:

  1. lock(this)
  2. {
  3. // Do stuff...
  4. }

Même si cela fonctionne, c'est une très mauvaise idée! Vous ne devriez jamais (ou du moins je n'ai aucune bonne raison en tête) faire un lock sur un type public, ce qui inclue évidemment le "this". Il y a une raison très simple à cela: vous n'avez aucun moyen de maitriser ce que le code appelant va essayer de faire.

Prenons un exemple simple. Dans le code suivant, nous avons une class qui utilise un lock sur "this" (On l'appellera ClassThatLocksItself). Nous avons aussi une seconde class (CallerClass) qui va appeler la première. CallerClass va alors utiliser un lock sur l'instance de ClassThatLocksItself lors de cet appel.

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. ClassThatLocksItself myObj = new ClassThatLocksItself();
  6.  
  7. CallerClass caller = new CallerClass(myObj);
  8. caller.LockTheObjectInAThread();
  9. Thread.Sleep(500);
  10.  
  11. myObj.LockMe();
  12. }
  13. }
  14.  
  15. class CallerClass
  16. {
  17. private ClassThatLocksItself _myObj;
  18. public CallerClass(ClassThatLocksItself myObj)
  19. {
  20. _myObj = myObj;
  21. }
  22.  
  23. public void LockTheObjectInAThread()
  24. {
  25. ThreadPool.QueueUserWorkItem(LockTheObject);
  26. }
  27.  
  28. public void LockTheObject(object state)
  29. {
  30. Console.WriteLine("Acquiring lock on the object");
  31. lock (_myObj)
  32. {
  33. Thread.Sleep(100000); // Do a long computation
  34. }
  35. Console.WriteLine("Releasing lock on the object");
  36. }
  37. }
  38.  
  39. public class ClassThatLocksItself
  40. {
  41. public void LockMe()
  42. {
  43. Console.WriteLine("ClassThatLocksItself -- Trying to acquire lock on this");
  44. lock (this)
  45. {
  46. Console.WriteLine("ClassThatLocksItself -- lock on this acquired");
  47. }
  48. Console.WriteLine("ClassThatLocksItself -- lock on this released");
  49. }

Si vous essayez d'exécuter ce code, vous remarquerez que Console.WriteLine("ClassThatLocksItself -- lock on this acquired"); est seulement executé lorsque la fonction LockTheObject() retourne (dans notre cas, après 100 secondes!). En utilisant lock(this), vous êtes devenu dépendant de facteurs externes inconnus (dans notre exemple, CallerClass a décidé d'utiliser l'instance de CLassThatLocksItself pour la synchronisation, ce que ClassThatLocksItself n'avait pas moyen de savoir). La situation est même pire pour les développeurs qui veulent réutiliser votre ClassThatLocksItself: a moi de parcourir la source de la classe, ils n'ont aucun moyen de savoir qu'il peut y avoir de grave problèmes de synchronisation.

Maintenant, essayez de deviner ce qui va se passer si l'on modifie l'implémentation de LockTheObject() par la suivante:

  1. public void LockTheObject(object state)
  2. {
  3. Console.WriteLine("Acquiring lock on the object");
  4. lock (_myObj)
  5. {
  6. _myObj.LockMe(); // will not lock!
  7. }
  8. Console.WriteLine("Releasing lock on the object");
  9. }

Un certain nombre d'entre vous devrait parier sur le deadlock je suppose. Mais non! En fait, la CLR est assez intélligente pour détecter que vous avez déjà acquis le lock sur le même objet lorsque LockMe execute lock(this). N'oubliez pas, nous sommes dans le même thread! Cela rend lock(this) très subtile: vous n'aurez des problèmes que dans des cas très spécifiques!.

Filed in .NET | No responses yet

Encore un blogger de plus sur la planète!

Julien on avr 4th 2008

Bonjour, et bienvenue sur ce blog!

Comme un certain nombre de personnes, j'ai énormément appris en lisant des articles de plusieurs auteurs très connus (Pensez Jeremy Miller, JP Boodhoo, Martin Fowler et bien d'autres encore!). Depuis que j'ai découvert leurs blogs respectifs, leur savoir m'a été d'une très grande utilité. Alors même que je ne les ai jamais rencontrés, ils m'ont permis d'améliorer mes compétences en tant que développeur. En quelques mots, je leur dois énormément!

Démarrer ce blog est pour moi une façon d'essayer de rembourser ma dette envers la communauté (à mon humble niveau!). En fait, il me semble qu'il nous reste énormément de chemin à faire afin d'améliorer la façon dont nous développons des logiciels. Alors même qu'il y a d'excellents livres et d'excellentes ressources sur Internet, la plupart des personnes avec qui j'ai eu l'occasion de travailler m'ont toujours paru assez étrangères à des sujets comme la bonne programmation orientée objet, les design patterns, le testing ou encore les méthodes agiles. Même si je n'ai pas le degré d'expertise des bloggeurs cités plus haut (ni la maitrise de ces différents sujets!), avec un peu de chance, je serai capable de véhiculer certaines idées ou aussi ce que l'on appelle les "best practices". Principalement sur .NET. Qui sait, peut être que je serai même capable de faire une petite différence autour de moi :)!

Permettez-moi aussi de vous donner un aperçu rapide de mon parcours:
Je suis actuellement développeur .NET dans la finance de marché. J'ai passé la dernière année à Londres dans un fond d'investissement puis j'ai décidé de rentrer à Paris en Février ou j'ai rejoint une société de conseil. Avant tout cela, j'étudiais l'informatique dans une école d'ingénieur, ce qui m'a permis d'effectuer plusieurs stages significatifs. J'ai aussi eu l'occasion de créer une société à cette époque mais c'est une vieille histoire :). En résumé: je suis encore très jeune et j'ai encore beaucoup à apprendre!

Enfin, notez que ce blog sera aussi édité dans la langue de Shakespeare. Le contenu sera du même ordre mais avec quelques différences significatives tout de même. En effet, de nombreux sujets ont déjà été discutés mille fois en anglais alors qu’ils n’ont eu que très peu d'échos sur la blogosphère française. Si le temps me le permet, j'essaierai donc d'aborder un certain nombre de choses qui, à mon avis, méritent d'être discuter en français aussi!

A bientôt!

Filed in Divers | No responses yet