mercredi 10 avril 2013

Git's branches are Sticky-notes

Take this quote that circulated on twitter
"Git gets easier once you get the basic idea that branches are homeomorphic endofunctors mapping submanifolds of a Hilbert space"
Now that is probably true but it is a most complicated way of explaining something very simple. This post will try to explain it in more human friendly terms and offer a useful metaphor (IMHO) for thinking about Git which is that of sticky notes for branches and tags.

The problem
It can be scary to do a merge ("what if I mess up the history"), and when you do get it wrong it's not very simple to undo that the first couple of times. Rebasing can also be quite awkward and seem like magic. And finally how can synchronisation between multiple repositories work (If I mess something up, I won't know how to get it right again). In short I was very careful in my first steps with git because I didn't want to mess things up, in particular with public repos. The following insights have helped me work more in harmony with Git and harness some of it's power. I'm writing this in hope they might useful to someone else.

Commits
First some basics. Git has commits. Commits are pointers to a full snapshot of the contents of the tracked files. They are identified by a sha1. It's very much like if you made a checksum of the checksums of all files.

A commit also contains a pointer to the its parent (i.e. the preceding commit). A commit with two or more parents is a merge commit, it has pointers to the commits that it merges.

Sticky notes
Git has sticky notes that you can stick to a commit. They're just a way of giving a commit a meaningful name. They are actually just a file with the sha1 of the commit as its sole . Lets look at the master branch, as (almost) all branches it is just a file residing in .git/refs/heads/

$ cat .git/refs/heads/master

ed31dcf89563d51010bca1620fbdef53a05c47a6



That's all there is to it! Now there are two types of sticky notes, tags and branches. Just like Post-Its you can move them around at your leisure. So lets say we want to move the master Post-It from where it is now to the commit with sha1 d23521... 
$ git branch --force master d23521da12cca757fac7c5f6b4729308b329c8ff

now the content of the master Post-It has changed
$ cat .git/refs/heads/master

d23521da12cca757fac7c5f6b4729308b329c8ff


Simple eh? You can even mess with the Post-Its of the team repository, but that will probably make your team mates just about as angry as if you moved around the Post-Its of your scrum board!

As I said there are two types of Post-Its: tags and branches. Tag Post-Its live in .git/refs/tags/ and there's not much more to them than that. Branch Post-Its live in .git/refs/heads/. What's special about branch sticky notes is that if you do a checkout on them they will follow your commits, so as to always point to the last commit - an example.
$ git checkout master
$ cat .git/refs/heads/master
d23521da12cca757fac7c5f6b4729308b329c8ff
$ ... modify some files
$ git commit

$ cat .git/refs/heads/master

6013c8f4133c175ff4bfeaf6af8bf3419f6bb6ba



In essence tags and branches are just pointers to a single commit.

Undoing a merge or rebase
Then it follows that if you mess up a merge you can easily redo it by checking out the commit you were on before the merge and then move the branch Post-it back. For instance lets say we're on the master
$ git merge somefeature

Let's undo!
$ git checkout HEADˆ                # HEAD means current commit, and the ^ means "the one before", we're no longer on the branch master.
$ git branch -f master HEAD      # moves the postit
$ git checkout master                 # we need to move back to the branch master

In practice you would rather do git reset --hard HEAD^, wich does all the above in one command. Btw there's an amazing doc about git reset.

Also if you messed up a rebase, even after it completed you can easily undo it by checking out the commit you were on before the rebase and moving along the branch Post-it, then checkout the branch Post-it at its new location.

Synchronisation with remotes

We're ready for some clarity about how pull and push to and from remote repositories work. When you do
$ git push origin master

That's a short for
$ git push origin master:refs/heads/master

That is, push any local commits on my master to the master branch on the remote repo origin. Or as we now see it : push my commit named master to the repo origin, and move the remote post-it (to the right of the colon) master to that commit. Under the hood Git will make sure that the commit-graph (all reachable parents from master) on both sides are identical and upload any missing commits.

Conclusion

In Git branches are just a way to name a commit.

I hope this post has taken away some of the strangeness and scariness of Git and that it has helped to see some of the commit-centric nature of git. I use this way of thinking all the time, in particular for merging, rebasing, reverting and in working with remotes. It has certainly made things easier and relieved me from the stress of doing something wrong.

In short I use this mental model should help when:
  • you merge two branches - you're just merging two commits using their name instead of their sha1
  • you're pushing or pulling to/from a remote repository -  there is absolutely no need for the names of the sticky notes on your repo and the remote repo to be the same. 
  • you're rebasing you're creating entirely new commits, then the the Post-It is moved to the tip of the new commits.
  • you do a bad merge, you can just move the Post-It down to where it was before and try again.
I just discovered Think like a git which provides very easy to read documentation

samedi 2 mars 2013

Anonymous Developers @JoyOfCoding - feedback


Here's a compilation of the extensive feedback we got from the just under 60 people that attended Developers Anonymous at the absolutely excellent 1st edition of the JoyOfCoding conference. Btw the organisers rock!

This is a compilation, we've selected statements with no particular rationale other than to put in bold statements that represent an idea shared by at least 3 people.

What have you done differently than usual?
  • Run the tests systematically
  • I had tests!
  • Making classes out of primitives
  • Took smaller steps in refactoring, a more structured approach (bigger steps, more mistakes)
  • Focusing on details instead of the bigger picture, to start with.
  • Lean more on the compiler / IDE
What suprised you the most?
  • Amount of thinking involved in OO design
  • The plugin auto running unit tests on save
  • Code became readable quite quickly
  • Not analysing just extracting logic in small steps
  • How small the resulting code was
  • The power of refactoring tool in Eclipse, what more tooling am I not using!?
  • Ease of refactoring when you have 100% coverage and following a few rules
  • Ease, fun
  • How many different solutions are available for the same problem
Name one question that this workshop has raised
  • When is it OK to have getters and setters?
  • Is this actually faster than extracting the different cases?
  • Why the heck this code works as is!?
  • Will this work with our code?
  • What more do I need to know to apply this more rigorously?
  • I wonder what my design is going to look like using classes with only 2 instance variables
  • Amount of work to get 100% coverage
Does it match your expectations? 
  • Yes, I want to know more 
  • Yes it is nice to see a design evolve using these small steps
  • Expected it to be less difficult 
  • It was fun
Would this be useful at work? How? Why not?
  • We will talk much about it to our colleagues
  • Yes it is a better way of refactoring
  • If I didn't know the business domain, yes.
  • Yes, it helps me figure out how to attack complicated functions in our legacy code
  • Yes, our largest "zzz" class suffers a lot from Feature Envy
Miscallaneous
  • It would have been good to have a session about how to write tests for this kind of code
  • It was a very nice learning experience

As presenters we're particularly fond of that last phrase! A great thanks to all the participants, we had a great time!

If you didn't attend and you would like to know a bit more about this session there's a github repository with the exercise in several languages, along with documentation that'll give you some idea about the content. With Rémy Sanlaville we'll also prepare a screencast with the live demos.

You can rate this talk/workshop at http://spkr8.com/t/20171


mardi 16 octobre 2012

Pattern Visitor, ne baissons pas les bras


Suite au post très intéressant de Xavier Nopre sur le Single Responsibility Principle et son approche beans+services, Nicolas Capponi a animé une séance du dojo du club agile pour explorer différents solutions qui s'offrent à nous pour ce problème.

Personnellement j'ai choisi d'utiliser le temps pour m'affuter en Visitor, car comme dis Xavier ce n'est pas le pattern le plus facile. D'autres personnes ont essayé d'autres solutions. 

Voici deux variantes du Visitor pattern. L'un qui expose les objets métier (et donc utilise des getters) l'autre qui fait passer des primitives pour résoudre ce problème (pas forcément mieux, juste différent). 

Extrait de la solution avec objets métier:


Les autres solutions explorés, dont j'aimerais bien voir le résultat, était délégation à une autre classe ou introduction d'une petite interface pour gérer le cas d'utilisation en question (par exemple Mailer pour contenir computeMailContent()). Ces deux solutions me semblent être des bonnes solutions temporaires en attendant de les extraire pour de bon. Par contre une fois extraite il me semble qu'on va tomber sur soit le visitor soit la solution que mentionne Xavier: beans+services. Non?

Conclusion
Les visitor qu'on trouve ici, est-ce vraiment trop complexe? Personnellement je pense que nous gagnerions à simplement pratiquer ce pattern pour savoir le mettre en oeuvre avec aise quand cela est préférable. Certes il faut le faire plusieurs fois pour avoir l'impression de maitriser, mais nous sommes nombreux  à être informaticiens plus de 10 ans, alors qu'il suffit avec ~10h de pratique étalé sur quelques mois pour le maitriser en profondeur. Qu'en pensez-vous?

mardi 24 janvier 2012

Tester entrées et sorties en Clojure

En faisant ce kata en Clojure j'étais sous pression de temps alors je n'ai pas fait une partie en TDD - l'interaction avec la console. Ca ne me dérange pas plus que ça mais je voulais voir comment on pourrait le faire en TDD. Il se trouve que c'est extrêmement simple!

Dans cet exercise on doit construire une caisse de primeur qui accepte en entrée (console) des fruits et qui pour chaque entrée affiche le total sur la sortie (console). Pour cela je vais construire une fonction buy  qui va s'appuyer sur la fonction read-line qui lit une ligne du console et println qui affiche une ligne sur la console

Premier besoin : je ne veux pas de boucle fini dans ma fonction - quand j'entre une ligne vide la fonction sort. La syntaxe ici vient de Midje - un framework de test qui a la particularité (pour un langage fonctionnel) d'être orienté outside-in.

Ici j'aime vraiment la facilité avec laquelle on arrive à faire un bouchon de read-line - on déclare simplement que ceci est un fait (fact) si read-line renvoie les valeurs énumérés

Deuxième besoin : On doit afficher le total de l'achat après chaque ligne d'entrée.

Ici c'est facile, court et ça reste lisible mais il y a du bruit :

  • on est obligé de déclarer la valeur de retour attendue de println (qui renvoie toujours nil), j'ai mis anything pour signifier que ce n'est pas important
  • chaque contrainte sur println (d'abord total 100 puis total 175) se déclare sur une ligne. Nous n'avons pas l'expressitivité de du bouchon avec =streams=>.  Dans mes rêves ça aurait été  

Et sinon le code ça rend quoi?

Ce à quoi je m'attendais pas en commençant cette exercise c'est que bien qu'on gère de la mutabilité (le prix total du panier s'incrémente) aucune fonction n'est mutable et aucun variable mutable n'est nécessaire. L'état du panier est contenu dans la recursion

Pour moi c'est fascinant de découvrir ce moyen de gérer l'état visible d'une application sans mutabilité.

dimanche 27 novembre 2011

mardi 18 octobre 2011

Pas si simple de faire simple

La version express de ce billet est que nous ne faisons pas assez la différence entre “construire avec des briques simples” et “faire des objets simples à utiliser”. Ce n’est pas du tout la même chose!
  • La différence :
    • La simplicité d’utilisation est
      • Contextuel
      • Composé
      • Plutôt fermé à l’évolution
    • Les briques simples sont
      • Généralistes
      • Unitaires
      • Ouverts à l’évolution
  • C’est possible d’avoir les deux.
Voici la version longue, avec des explications et, promis, des exemples.

Dans ce keynote Stuart Halloway explique que le mot simple veut dire quelque chose de très fondamentale. Il soutient que la définition du mot simple est non composé ou non assemblé (non compound en anglais).

Puis il continue à nous expliquer pourquoi il est primordiale de construire seulement à partir de choses simples. Notamment il dit
  • Essayez de faire quelque chose de simple à partir de choses non simples … C’est impossible
Autrement dit, pour avoir une librairie ou application simple, on doit l’assembler de choses simples. Puis il finit son keynote par dire.
  • Si un peu plus du code était écrit dans le respect de la simplicité le monde serait un peu meilleur.
Bon finalement c’était juste le Single Responsibility Principle dans une nouvelle sauce. Soit, seulement quelques jours plus tard, il m’est venu à l’ésprit qu’il y a un paradoxe. Car si j’écris tout mon code de cette manière alors il serait chiant à utiliser, même pour moi. Notamment lorsqu’on utilise fréquemment une fonction/objet avec les mêmes paramètres ce serait chouette de ne pas le répéter partout dans le code. Un code simple n’est pas toujours simple à utiliser.   En regardant de près il n’y a pas de paradoxe, mais la réflexion m’a fait comprendre quelque chose que je vais partager ici.

Pour rendre la vie facile pour ceux qui utilisent notre code (souvent nous mêmes) nous avons tendance à faire du code simple à utiliser. Je suis convaincu que si on échoue à faire quelque chose de simple c’est souvent parce qu’on veut faire quelque chose de simple à utiliser! Et pourtant ce compromis n'est pas nécessaire.

Si on revient à la définition de simple on constate que simple est une qualité intrinsèque et non contextuelle. Il est possible de juger de la simplicité de manière objective.

Avec Simple à utiliser c’est l’inverse. Par définition c’est simple pour l’utilisation prévue. Si on change un peu le contexte il y a toutes les chances que ce ne soit plus très simple à utiliser. Simple à utiliser est contextuel.

Souvent nous trouvons des choses simples à utiliser parce que ça ressemble à quelque chose de connu, par exemple un patron de conception que nous avons déjà utilisé. Simple à utiliser est subjectif.

Ce serait bien dommage de faire des compromis entre une qualité "absolue" et une qualité contextuelle et subjective !

Prenons par exemple cet objet qui fait partie d’une application de crawl basique.

BatchCrawler est simple à utiliser car nous n’avons pas à fournir beaucoup d’arguments pour l’instancier. Par contre il n’est pas Simple car il fait un tas de choses en plus de crawler une liste d’urls :

  • Il spécifie où est configuré le timeout de chargement d’une page.
  • Il contraint ce timeout à ne changer dans toute la JVM voire même on doit redéployer pour la changer.
  • Il contraint à utiliser un RetryingHttpCrawler – qui retente en cas de timeout et qui passe par le protocole HTTP.

Limitant ainsi fortement le potentiel de réutilisation de l’objet.

Pour que l’objet puisse être qualifié de Simple, le constructeur devrait ressembler à ça

Mais alors il deviendrait chiant à utiliser. Si cet objet est instancié de plusieurs endroits de l’application il y aurait de la duplication. Nous allons donc réintroduire ce constructeur sous forme de FactoryMethod avec un nom explicatif (documentation) parce qu’il s’agit d'une façon de configurer ce graph d’objets.

Comme avec tout exemple simplifié c’est n’est jamais trop grave. C’est encore suffisamment petit pour être corrigé après-coup. Seulement dans une application réelle ça peut être un cauchemar car régulièrement on se retrouve avec l’initialisation d’une grappe d’objets - ici BatchCrawler initialise un RetryingHttpCrawler etc. Presque à chaque fois l’initialisation des objets plus bas dans le graphe ont des conséquences indésirables, c’est souvent ça qui nous rend les tests après si difficiles ... Le remplacement d’un objet dans ce graphe n’est pas toujours aisé et le code nécessaire teintera le code d’initialisation avec complèxité.

En construisant uniquement avec des objets et fonctions Simples on arrive à l’enrober avec une simplicité d’utilisation… pour le besoin actuellement connu. Quand le besoin change (lire toujours) on est le roi du pétrole. On a le beurre et l’argent du beurre.

Note : je ne dis pas qu’il faut essayer d’imaginer le besoin futur, seulement qu’il faut décomposer son code actuel en des briques les plus simples possible. Par dessus on peut ensuite construire la simplicité d’utilisation avec par exemple des valeurs par défaut.

Conclusion
Je ne vais pas conseiller de toujours faire ainsi, car à vrai dire rien n’est toujours vrai. Simplement le message que j’essaie de passer est

  • Il y a une différence importante :
    • La simplicité d’utilisation est
      • Contextuel
      • Composé
      • Plutôt fermé à l’évolution
    • Les briques simples sont
      • Généralistes
      • Unitaires
      • Ouverts à l’évolution
  • C’est possible d’avoir les deux.

dimanche 3 juillet 2011

Symfony actions ARE easily testable

All Symfony experts I've met have told me that I'd better not bother with unit testing the actions because it's difficult enough that it just isn't worth it. Even an official Sensio Labs trainer that wisited our company said the same thing (I find that quite surprising). Only when you're doing TDD it's rather annoying not to be able to test the first lines of a new feature as it breaks your flow.

I should never have believed them. Luckily a colleague of mine didn't. In fact it turns out it's strikingly easy so I'd like to share it with you.


Here's an example of a how to unit test a standard action “executeHelloWorld” and an ajax action “executeGoodEvening”. It takes two simple lines in the setUp to prepare instantiation of the action.



The rest of the non-magic is in the fact that Symfony actions do not directly return the values we are interrested in. Ordinary (non-ajax) actions do not return anything they just prepare the execution of the template by storing values in a var-holder, we access it by action->getVar('name'). Ajax actions generally directly compiles the partials with parameters passed in an array and adds all that to action->response->content.

Credits go to Marc Nazarian and Sebastien Fromont without whom I still wouldn't TDD my actions.

For reference the action code

and the partial used