finally add refactoring by M. Fowler

This commit is contained in:
Fred Pauchet 2019-10-04 21:42:11 +02:00
parent 929d27fdc8
commit b42916c576
1 changed files with 31 additions and 0 deletions

View File

@ -0,0 +1,31 @@
# Refactoring
:author: Martin Fowler
## Tests (unitaires & intégration)
Construire des tests facilite le travail dans la mesure où, quand un bug arrive, les tests qui lui sont associés vont foirer. Cela indique où la modification doit être apportée. Tous ces tests doivent être automatiques, de la même manière que la compilation ou la gestion des dépendances. Ne regardez pas la sortie console, faites juste en sorte qu'un *worker* vous indique ce qui ne fonctionne plus.
Les **tests unitaires** consistent en des tests localisés: quand on reçoit un rapport de bug; on commence par faire un test qui expose le bug (ce qui évitera ensuite les régressions).
Les **tests fonctionnels** utilisent le système comme une *black box*. Idéalement, ils devraient être écrits par une équipe différente. **Pensez aux conditions sous lesquelles le système pourrait planter, et concentrez-vous dessus**.
Il y a toujours un risque qu'on rate quelque chose, mais *il vaut mieux passer un temps raisonnable à attraper la plupart des bugs, plutôt que de passer des années à leur courir après*.
## Conseils de programmation
* **Trop de paramètres ?** Construisez un objet qui les embarque comme champs. Idem quand l'algorithme n'est pas assez clair.
* Supprimer les paramètres inutiles. Voire ne pas hésiter à refactoriser en ajoutant des paramètres si deux fonctions font la même chose. Voire, remplacer des paramètres par des méthodes explicites (et éviter de décomposer un même objet en plusieurs paramètres).
* Ne pas hésiter à supprimer des setters ou à modifier la visibilité de certaines méthodes (public -> protected -> private).
* Au besoin, une factory permet aussi de gérer un constructeur vers des sous-classes (éventuellement en utilisant un brin d'introspection pour aller pêcher la bonne classe par réflexion, sur base d'une chaîne de caractères). Ou alors passer par des méthodes explicites, type `Person.newMale()` et `Person.newFemale()`.
* Eviter de retourner des objets qui ne sont pas suffisament typés. On évite ainsi de retourner `object()` plutôt que `MyClass()`. Cela évite de downcaster la variable retournée par la fonction appelante.
* Aucun code d'erreur ! Si c'est nécessaire, implémenter une gestion propre des erreurs (sauf si on finit par avoir tellement de classes qu'un test pourrait suffire...).
* Dans certains cas, le refactoring fait partie d'une nouvelle fonctionnalité. Ele fait alors partie du processus d'écriture et il est indispensable de se laisser du temps pour implémenter les choses proprement.
* *L'accumulation de décisions d'architecture à moitié comprises peut éventuellement trucider un programme*. By refactoring, you can ensure that you fully understand how the program works and should be designed.
## Conclusion
Un truc un peu lourd quand on lit ce livre, c'est que tous ces exemples "simples", on a parfois l'impression de lire quelques contradictions. Par exemple, avec la délégation simple: si une classe fait trop de délégations simples et agit comme un *middle-man*, il faut alors la dégager, parce qu'elle génère un trop grand couplage de classes. Du coup, il ne s'agit pas vraiment d'un livre de recettes à suivre, mais plus d'une concrétisation de l'intuition par l'expérience.
Plus précisément, il s'agit d'une clarification étape par étape de choses que l'expérience nous fait faire intuitivement.