mardi 28 janvier 2020

Quand faut-il refactorer pour éviter le legacy?

Quand est-ce que nous devons refactorer le code? Pour ne pas contracter trop de legacy il faut refactorer, on le sait, mais quand? 

Est-ce qu'il faut faire des stories de refactoring? Est-ce que ce sont des stories "utilisateur"? Ou faut-il le faire plutôt au fil de l'eau? Pour moi la réponse est "majoritairement au fil de l'eau", pendant les stories. Dans cette video on voit pourquoi cette approche est la plus intéressant à mon sens et s'il faut le faire avant, pendant ou après la story. 

On verra aussi en quoi ceci peut être contre nature au début car c'est pas dans nos habitudes. 

Toi aussi tu aimes le code propre et le legacy t'embête, voire le fais chier :), viens à mon webinar sur la dette technique, ce vendredi 31/1 et tu pourras poser les questions qui te brulent en direct!
  T peux aussi jeter un oeuil sur la formation interactive en ligne Clean code, sortir de la dette technique, il y a des chances que ça te plaira autant que les personnes qui l'ont déjà suivi ;o)

lundi 6 janvier 2020

Stop feeding the big classes - Class division

I typically ask people to show me the one or the a few classes that hinder them from writing unit tests. Almost consistently (!) this is a class of 1000 lines or even a few thousand lines of code and this is where most of the development work takes place. Of course this is very difficult to test and even though sometimes these classes are tested with unit tests, they are very very hard to maintain. 

I wouldn't even try

I do admit that it is very hard to write unit tests for these classes. I would find it very difficult to write good unit tests for them too. In fact I wouldn't even try to test this with unit tests. Now what I would do is I would extract the behaviour that I want to modify into other classes or more likely to a completely new class. If I move out a method of say 10 to 50 lines of code then that's very easy to test and things that are easy to test are easy to change by adding behaviour to it. In doing this, besides making things testable, we improve things by splitting things into smaller pieces. Smaller pieces are more easy to understand to test and to assemble into new behaviour i.e. reuse these classes elsewhere

Given that we do split the big classes into pieces as we do features then it doesn't take many stories to make our codebase a lot more maintainable and all the way we been able to work with lower level tests. All we needed to ensure is that the things we split apart are meaningful pieces that are functionally coherent. This is probably the most difficult part - extracting something meaningful. It requires being able to design code and if we don't have much practice doing it won't be very good. On the other hand if we don't start practicing this then all code we  create will just be a bigger and bigger mess. I mean there's a reason (almost) all living things grow by cell division, not by cell growth.

The actual act of extracting something is really simple. Very often it is as simple as

  1. Extract Method (automated refactoring)
  2. Create class and add it as a member of the existing class
  3. Move Method (automated refactoring)

The bottom line

The next time you touch a big class then split something out, find something meaningful you can move out and test and then change that piece. Done! The modification is safe and it's done rather quickly. We started out with a testability issue, but really it's a design issue regardless of the need to test.