SlideShare ist ein Scribd-Unternehmen logo
1 von 96
Downloaden Sie, um offline zu lesen
Coder propre
aka Clean CodeJoseph Pachod
https://twitter.com/joeclueless
Pourquoi ?
Raisons traditionnelles
● On lit + le code qu'on ne l'écrit
● Évolutivité de l'application
● Développer la prochaine version plutôt que de corriger
l'actuelle
● Respecter la norme ou les règles de développements
imposées
La réalité...
Code sale...
● fragile
● compliqué
● plein de (mauvaises) surprises
● effets de bord inattendus
● duplication
● illisible
● peu performant
● dur à améliorer
● ...
Dégâts perceptibles à tous les niveaux
● Chaque évolution est une nouvelle galère
● Développement laborieux, répétitif et aléatoire
● Délais et surprises pour la moindre modification (gestion
de projet peu agréable)
● Expérience utilisateur mauvaise (régressions & bugs
fréquents)
Le code sale tue...
● Les développeurs qui s'arrachent les cheveux..
● Les produits quand on ne parvient plus à les maintenir ou
faire évoluer.
● Les entreprises derrière tout cela..
La réécriture complète n'est pas la solution :
● absence de nouvelles fonctionnalités pendant l'intervalle,
● recommencer pareil donnera la même chose,
● l'existant est certainement plus riche que vous ne le
pensez..
● La concurrence sera bien plus loin d'ici là.
Coder propre ou ne pas faire d'informatique !
=> coder propre : voie de salut pour le développeur, la
gestion de projet et les utilisateurs
Comment ?
Savez vous coder propre ?
Coder sale n'apprend pas comment coder propre...
Faire complexe est facile, faire simple est difficile.
Situation paradoxale.
Mais la complexité se paie très vite...
De l'envie et le reste suivra !
Nécessité d'envie du développeur : il est seul face au
clavier !
Se poser des questions sur code, réfléchir, essayer…
Mais aussi :
Discuter, lire, écouter !
You can't dictate software quality -- quality
development has to be grown.
Bruce Eckel
Le code propre ne s'impose pas. Il s'apprend, se nourrit et
se développe.
C'est un travail d'équipe qui nécessite l'adhésion (ou la
prise de conscience) de tous.
Les chefs de projet sont généralement bien plus réceptifs
qu'on ne le croit : dur de faire pire bien souvent...
De l'engrais intellectuel pour démarrer !
Maintenant que la nécessité de code propre est partagée
(espérons!), voyons pour aider à son démarrage.
Attention : des pistes, des conseils, pas de dogmes
religieux.
Chaque langage/framework/équipe/développeur a ses
propres bonnes pratiques : se renseigner, discuter et se
mettre d'accord avec son équipe.
Pour commencer… on se détend !
La suite évoque des pistes, des conseils, pas de dogmes
religieux.
Il n'y a pas de définition précise du code propre.
Chaque langage/framework/équipe/développeur a ses
propres bonnes pratiques : se renseigner, discuter et se
mettre d'accord avec son équipe.
A chacun de trouver sa voie.
Juste des exemples
Exemples de code à venir : mise en avant de points, pas
code parfait...
Utilisation fréquente des termes « Foo » et « Bar », pour
se concentrer sur le code et non le fonctionnel. Par
exemple :
public class Foo {
public Bar doBar() {
return new Bar();
}
}
(snip) : indique que plein de code non relevant pour
l'exemple devrait être présent
=> on ne sait rien du fonctionnel, on peut parler du code
Donner du sens au code
Que fait le code qui va suivre ?
// @author setUpYourName
public class BadCodeWithComments {
private Bar var1 ;
/** Takes a bar then foo **/
public void foo() {
// on testte l'état
if( var1.state == null ||
var1.state == 0
/* foo.state == 1 || */
) {
(snip)
}
}
}
Auteur du code : manifestement faux, inutile, n'apporte rien.
Le commentaire sur la méthode semble référer à une
version antérieure, car évoque un argument plus présent.
Le commentaire sur le test décrit le détail du test : aucune
valeur ajoutée. Faute de français : distraction en plus...
Noms et valeurs d'aucune aide : var1, state, entier 0 et 1...
Génériques, interchangeables à volonté => vides de sens :
on ignore de quel « state » on parle ainsi que le sens des
valeurs testées
Qu'indique la ligne commentée ci dessous ?
/* foo.state == 1 || */
La valeur 1 n'est plus présente ?
La valeur 1 n'est plus à tester ?
Quelqu'un a fait un test et a oublié de dé commenter ?
=> soulève de nombreuses questions, alors qu'elle ne fait
rien !!
Mort aux commentaires !
Le moins possible de commentaires
● Signes d'un manque d'expressivité du code
● Faciles à bâcler, dur à écrire proprement, quasi
impossible à maintenir
- commentaires alors trompeurs et erronés
● Ne PAS commenter le code modifié
- on a un gestionnaire de source pour cela
On réessaie
public class BadCode {
private Bar var1 ;
public void foo() {
if( var1.state == null ||
var1.state == 0
) {
(snip)
}
}
}
On voit plus vite qu'on ne voit rien...
Des commentaires ne sauvent pas du mauvais
code.
Tentative d'expliciter très dure à réaliser
S'attaquer à la cause plutôt que de tenter de l'enjoliver
Indiquer l'intention
(le pourquoi)
La lecture du code doit en permettre la compréhension
directement
public class BetterCode {
private Bar last;
public void foo() {
if (last.isInProgress()) {
(snip)
}
}
}
Nommage explicite des classes, méthodes et variables
Pas de « bruit » inutile.
Bon niveau de détail :
● si on veut savoir comment est fait le test, on va voir
dans la méthode.
● Sinon on peut continuer à explorer le code actuel sans
surcharge cognitive.
Et aucun commentaire :)
Quelques bonnes pratiques
ArrayList<String> list = new ArrayList<>();
vs
List<String> names = new ArrayList<>();
Le pourquoi pas le comment
-
Le code indique le comment
Dans tout ce qu'on utilise indiquer le pourquoi (une liste,
des noms) plutôt que le comment (une liste chainées, des
chaines de caractères).
Le code permet toujours de voir le comment (quelque part).
Pas le pourquoi.
Evite également les redites et donc le risque de décalage à
terme.
status == 0
vs
isValid()
Nommer même si court
● Même une méthode d'une ligne est mieux
● Petites méthodes bien plus réutilisables
● Méthodes surchargeables…
● Méthode évolutive
if (bar.isNotDone() == false)
vs
if (bar.isDone())
Faciliter la lecture
-
Pas de double négation
Un ordinateur parvient à lire de l'assembleur : on code pas
pour lui mais pour les autres humains.
Aussi, le code doit pouvoir être lu.
Par exemple nommer positivement est préférable à la
double négation
lstUnUsd
vs
lastUnitUsed
Faciliter la prononciation
-
Noms longs pas un problème
Le code lu est une bonne chose, mais c'est encore mieux
quand on en discute. Pour cela, on doit pouvoir prononcer
les éléments du code.
Si plus clair, recherche également plus aisée.
FOXMLData fOXMLData
vs
FoXmlData foXmlData
Acronymes en camel case
-
Facilite la recherche via l'IDE
Plus lisible
La convention Sun/Oracle et Microsoft
Permet la recherche de type dans l'éditeur via camel case :
FXD → FoXmlData
Sinon :
FOXMLD → FOXMLData
Ne « crie » pas au milieu code
public int id;
vs
public Identifier<Good> id;
Typer
Les entiers sont communément utilisés : si vous voyez un
entier quelque part, cela sera t il pour autant l'identifiant
que vous cherchez ?
Si l'identifiant a des contraintes particulières, impossible de
le voir avec un entier : besoin de regarder autour/en base
pour comprendre les valeurs autorisées et le
fonctionnement.
A l'inverse, une classe dédiée :
● permet de voir tous les usages de l'identifiant en
question (via les références dans le code)
● Permet d'aisément ajouter ou supprimer des
comportements
● N'importe où dans le code où ce type est présent, on
sait de suite de quoi il s'agit ou, au pire, il suffit d'aller
voir la classe en question pour avoir le détail
return null;return null;
vs
returnreturn Collections.Collections.emptyListemptyList()();;
Eviter les mauvaises surprises
-
Ne pas provoquer de NullPointerException
public Foo getFoo(){
(snip)
return null;
}
vs
public Optional<Foo> getFoo(){
(snip)
return Optional.empty();
}
Expliciter
-
Optional empêche d'oublier qu'une valeur peut
être nulle
public Foo getFoo(){
if(foo == null){
foo = createFoo();
}
return foo;
}
vs
public Foo getOrCreateFoo(){
if(foo == null){
foo = createFoo();
}
return foo;
}
Ne rien cacher
-
Eviter les effets de bord
Un cas plus concret
public void doStuff() {
(snip)
sendEmail("admin@acme.com", "Stuff done",
"Details");
}
private void sendEmail(String to, String subject, String
text) {
String from = "system@acme.com";
String host = "smtp.acme.com";
Properties props = new Properties();
props.put("mail.smtp.host", host);
Session session = Session.getInstance(props);
Message msg = new MimeMessage(session);
(snip)
Transport.send(msg);
}
2 choses différentes au même endroit : le but initial de la
classe, doStuff, et l'envoi de mail
Conséquences
● Longueur de la classe
● Détails et mises en œuvre très différents
Plein de problèmes latents :
● Réutilisation difficile
● Changements difficiles car plein de valeurs codées en
dur
● Si le code de l'envoi de mail est copié ailleurs, sera t il
bien iso fonctionnel ?
● Quid en cas d'erreur/exception lors de l'envoi du mail ?
Impacts sur doStuff() ?
=> mauvais
private final Mailer mailer;
public Good(Mailer mailer) {
this.mailer = mailer;
}
public void doStuff() {
(snip)
mailer.sendEmail("admin@acme.com", "Stuff done",
"Details");
}
Rendre indépendant au maximum les différents modules
les uns des autres
● le service d'envoi de mail ne doit faire que ça, sans
dépendre ou appliquer des logiques relevant d'autres
choses
● Pas de logique en fonction du contexte (utilisateur
courant par exemple)
● Utilisation possible du service en dehors d'un contexte
web
=> Augmente la réutilisation
Se concentrer sur l'essentiel d'une fonctionnalité permet de
la traiter correctement
● Notamment le traitement des cas d'erreurs
● En proposant différentes méthodes correspondant aux
différents besoins d'appels
=> meilleur
Faire une chose à la fois
-
Permet de faire une fois bien
Lorsqu'on ne duplique pas la même chose plusieurs fois,
on n'a qu'un seul endroit à améliorer pour améliorer tous
les usages de la chose en question.
Qui plus est, en faisant une fois, on est plus incité à faire
bien, alors qu'une recopie de plus n'incite guère à l'effort.
Au demeurant, toutefois, il n'est pas nécessaire de faire
forcément mieux qu'on aurait fait initialement. En effet, une
énorme valeur ajoutée est de pouvoir faire mieux plus tard,
lorsqu'on aura commencé à rencontrer des problèmes.
private final Notifier notifier;
public Better(Notifier notifier) {
this.notifier = notifier;
}
public void doStuff() {
(snip)
notifier.notify(userAcme, "Details", "Stuff done");
}
Découpler
-
Tant entre classes que de l'implémentation
Bien réfléchir au nommage et au périmètre des services
● L'envoi de mails n'est qu'une des façons de notifier
● L'idée était de notifier, pas d'envoyer un mail
● Permet de généraliser : on passe désormais
l'utilisateur et non plus directement l'adresse
Ne pas hésiter à séparer la déclaration de l'implémentation
● Initialement peut être que seul l'envoi de mail marche
● Distingue bien le comment du pourquoi
=> encore meilleur
Le code doit être auto descriptif
Etat d'esprit de ce qui a été présenté.
Tout doit tendre vers cela.
final String CHRISTMAS_DAY = "25/12";
final String NEW_YEAR_DAY = "01/01";
final String FRENCH_NAT_DAY = "14/07";
final String workersDay = "1/1";
Quelle ligne a ajouté le nouveau venu dans l'équipe ?
Respecter le style en vigueur
Uniformité du style => lecture plus aisée
Code résultat d'une action collective
● par défaut, respecter le style en place
● si besoin, discuter et décider en équipe du nouveau
style et des modalités de transition
Evite de se faire haïr... et accessoire : le style en vigueur
n'a pas d'effet sur la qualité du code.
Commenter uniquement en dernier recours
Mettre des commentaires quand toutes les tentatives pour
rendre intelligible le code ont échoué.
C'est par exemple souvent requis pour des contraintes
externes.
De même une explication générale est souvent dure à
rendre uniquement par le code, même si cette explication
générale ne retire rien à bien nommer son API, des
méthodes aux exceptions.
Durer
Refactoring
-
Renommer, extraire avec l'IDE
Actualiser le code existant
● noms mis à jour
● évolutions de la structure même si besoin
=> le code doit refléter l'état actuel des connaissances
métier
Pas de connaissance en dehors du code
Refactoring
-
Modifications plus complexes ?
Changements des règles...
Réalisation d'un manque de logique quelque part..
Cas non prévu…
Problème de performances...
Refactoring toujours serein ?
Plus de refactoring : code mort
Comment être sûr de son code ?
De la première ligne après 1000 lignes...
Lors de tests manuels de son code, on exécute les bouts
qu'on vient d'écrire.
Aussi, on exécute au début le code initial, mais comment
s'assurer à la fin que ce dernier soit toujours fonctionnel ?
De la première ligne après 6 mois...
Tests automatisés !
Coder vos tests
-
En premier ou en même temps
Etre le premier utilisateur de son code
Soyez le premier utilisateur de votre code via les tests
● Avant même que le code ne soit écrit : permet de voir
si l'utilisation correspond aux attentes
● Changer d'avis ne coute alors rien !
Améliore le code
Tester son code implique de s'en servir dans un contexte
un peu différent que celui de son exécution normale.
Aussi, cela nous amène souvent à découpler et rendre le
code modulaire, ce qui est un gage de pérennité.
Documentation pour développeurs
Quelques pistes pour le code pré existant
Mocker
Tests filet
Procéder par incréments
Types de tests
Tests unitaires
-
Rapides
Portée limitée
Robustes
-
Dans l'intégration continue
Tests d'intégration
-
Lents
Plusieurs éléments
Compliqués
-
Quand les tests unitaires sont ok
Tests d'IHM
-
Aller au bout
Au plus proche des utilisateurs
Tests d'IHM avec côté serveur
-
Lents
Très fragiles
Coûteux à mettre en oeuvre
Tests d'IHM uniquement côté client
-
Rapides
Fragiles
Abordables
Spécifications par l'exemple
(Behavior Driven Development - Acceptance tests)
-
Fonctionnalités et exemples en langage métier
Spécifications par l'exemple
-
Utilisées pour spécifier
Automatiser
Sur l'ensemble du code métier
Spécifications par l'exemple
-
Documentation vivante !
Tests de performance
-
L'optimisation prématurée est la source de tous
les maux.
(Premature optimization is the root of all evil)
-
Tester quand tout va bien
Les problèmes de performances doivent être avérés,
mesurés et reproductible avant leur correction.
Bien cibler un problème de performance est primordial pour
le régler (cf outils comme JMH).
Bien souvent nos hypothèses concernant les causes de
problèmes de performances sont fausses ou non
déterminantes. La réalité est bien plus complexe, le
fonctionnement des systèmes actuels bien plus riches que
nous le supposons..
A l'inverse, tant qu'aucun problème n'est présent prendre
divers raccourcis sous prétexte de performance au
détriment du code propre n'est qu'une excuse.
Enfin, tester les performances en non régression permet de
voir au plus tôt l'introduction de code pénalisant celles ci.
Tests aussi du code propre
Tester = code cartésien
Maîtrisez votre IDE !
Votre IDE peut faire beaucoup, apprenez ses capacités,
notamment :
● génération de code
● via des templates pour des éléments récurrents (le
logger par exemple)
● en écrivant un code minimal, qui ne compile pas, et
en le laissant créer le reste
● découverte/lecture du code
● liste des appelants
● références
● hiérarchie des classes
● propositions de refactoring
● renommage & déplacements
● création de méthode
● formatage automatique
● plus simple pour relire le code du collègue
● analyse de la qualité du code
Surtout : apprenez ses raccourcis pour être efficace
Etat d'esprit
Première loi de la qualité logicielle
errors = (more code)2
e=mc2
Moins il y a de code à maintenir, mieux c'est
Du code non fréquemment exercé tend à devenir
rapidement obsolète ou contenir des erreurs
Mieux peu qui tourne que beaucoup qui plante
2000 options de configuration
vs
code facile à modifier
But : avoir du code simple facile à changer, pas du code
complexe "qui fait tout" dur à modifier.
Les besoins de demain seront différents des prévisions
d'aujourd'hui
Eviter les usines à gaz de paramétrage avec 2000 choix,
mais (généralement) pas celui désiré
Si code propre, alors modification aisée.
=> KISS (Keep It Simple Stupid)
Les 2000 options sont autant d'aveux de faiblesse quant au
comportement que doit avoir le logiciel.
Egoless programming
Critique du code != critique de soi
=> les discussions et critiques autour du code sont
primordiales. Elles ne doivent pas être prises comme des
attaques personnelles.
Etre accessible et prêt à discuter
Règle du Boy Scout
Laisser le code plus propre qu'en arrivant
Préoccupez vous du code !
Améliorer le métier du client
Objectif d'un codeur ?
- Coder ?
- Livrer un ensemble de code cohérent ?
- Livrer un produit, incluant sa vie opérationnelle ?
- Améliorer le métier du client ?
Améliorer le métier du client est la seule façon d'apporter
de la valeur via le code. Et est crucial pour un éditeur !
Retour à la réalité
Coût du coder propre
Coût intellectuel
● Remise en cause
● Changement
Coût initial
● Premières lignes codées propres laborieuses
● Beaucoup de réflexions (salutaire)
Coût au quotidien
● Léger surcoût au premier dév d'une fonctionnalité
● Gain dès qu'on a besoin de relire, retoucher ou
réutiliser
=> arrive généralement bien plus tôt qu'on ne le pense
Mieux vaut passer un peu plus de temps au début pour
bien faire que de supporter ensuite longtemps quelque
chose de mal fait !
Distribution de quasiment toutes les compétences
que nous savons mesurer…
Il n'y a pas que deux niveaux de développeurs, les
mauvais et les ninjas !
L'immense majorité d'entre nous est quelque part au
milieu de l'image.
Améliorons nous !
Lecture
● De livres, par exemple Clean code
● De code "propre" -> nombreux projets Open Source
(mais pas tous, souvent un signe de maturité, ex lucene,
wicket, jquery)
Ateliers/conférences
● Qu'ils soient dédiés au code propre (tests...)
● Ou sur un autre sujet : les échanges avec du code sont
toujours très instructifs, tout comme voir un autre coder
(et se servir de son environnement)
Ensemble
● Revue de code
● Pair programming : toujours très instructif
Conclusion
Coder propre nécessaire, mais pas suffisant.
Il suffit de s'y mettre !
Coder propre sous partie d'un tout bien plus
vaste !
Autres points à considérer :
- programmation fonctionnelle,
- capture du métier,
- ergonomie,
- prise en compte de l'opérationnel,
- ...

Weitere ähnliche Inhalte

Was ist angesagt?

Domain-Specific Languages avec Groovy
Domain-Specific Languages avec GroovyDomain-Specific Languages avec Groovy
Domain-Specific Languages avec GroovyGuillaume Laforge
 
Rédaction de tests unitaires avec fakes
Rédaction de tests unitaires avec fakesRédaction de tests unitaires avec fakes
Rédaction de tests unitaires avec fakesMSDEVMTL
 
JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...
JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...
JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...Afnic
 
Patrons de conception de la programmation fonctionnelle
Patrons de conception de la programmation fonctionnellePatrons de conception de la programmation fonctionnelle
Patrons de conception de la programmation fonctionnelleAssociation Agile Nantes
 
Bbd dans le flow nov.2012
Bbd dans le flow nov.2012Bbd dans le flow nov.2012
Bbd dans le flow nov.2012guillaumeagilr
 
05 visual basic .net - variables, procedures, arguments et structures de cont...
05 visual basic .net - variables, procedures, arguments et structures de cont...05 visual basic .net - variables, procedures, arguments et structures de cont...
05 visual basic .net - variables, procedures, arguments et structures de cont...Hamza SAID
 
Chapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphismeChapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphismeAmir Souissi
 
Chapitre 5 classes abstraites et interfaces
Chapitre 5  classes abstraites et interfacesChapitre 5  classes abstraites et interfaces
Chapitre 5 classes abstraites et interfacesAmir Souissi
 

Was ist angesagt? (10)

Domain-Specific Languages avec Groovy
Domain-Specific Languages avec GroovyDomain-Specific Languages avec Groovy
Domain-Specific Languages avec Groovy
 
Rédaction de tests unitaires avec fakes
Rédaction de tests unitaires avec fakesRédaction de tests unitaires avec fakes
Rédaction de tests unitaires avec fakes
 
JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...
JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...
JCSA2013 01 Tutoriel Stéphane Bortzmeyer "Tout réseau a besoin d'identificate...
 
Patrons de conception de la programmation fonctionnelle
Patrons de conception de la programmation fonctionnellePatrons de conception de la programmation fonctionnelle
Patrons de conception de la programmation fonctionnelle
 
Langage C#
Langage C#Langage C#
Langage C#
 
Bbd dans le flow nov.2012
Bbd dans le flow nov.2012Bbd dans le flow nov.2012
Bbd dans le flow nov.2012
 
Microsoft07coursbaptiste
Microsoft07coursbaptisteMicrosoft07coursbaptiste
Microsoft07coursbaptiste
 
05 visual basic .net - variables, procedures, arguments et structures de cont...
05 visual basic .net - variables, procedures, arguments et structures de cont...05 visual basic .net - variables, procedures, arguments et structures de cont...
05 visual basic .net - variables, procedures, arguments et structures de cont...
 
Chapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphismeChapitre 4 heritage et polymorphisme
Chapitre 4 heritage et polymorphisme
 
Chapitre 5 classes abstraites et interfaces
Chapitre 5  classes abstraites et interfacesChapitre 5  classes abstraites et interfaces
Chapitre 5 classes abstraites et interfaces
 

Ähnlich wie Coder propre !

Design poo togo_jug_final
Design poo togo_jug_finalDesign poo togo_jug_final
Design poo togo_jug_finalDuchess France
 
Design poo togo_jug_final
Design poo togo_jug_finalDesign poo togo_jug_final
Design poo togo_jug_finalagnes_crepet
 
Tdd en action - découverte
Tdd en action - découverteTdd en action - découverte
Tdd en action - découverteEric Mignot
 
Tester du legacy code, mission impossible ?
Tester du legacy code, mission impossible ?Tester du legacy code, mission impossible ?
Tester du legacy code, mission impossible ?CGI Québec Formation
 
C'est quoi, du bon code ?
C'est quoi, du bon code ?C'est quoi, du bon code ?
C'est quoi, du bon code ?Rémi Lesieur
 
Scripting Linux avec Python partie1.pptx
Scripting Linux avec Python partie1.pptxScripting Linux avec Python partie1.pptx
Scripting Linux avec Python partie1.pptxFrancisRUKAN
 
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...Guillaume Saint Etienne
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logiciellecyrilgandon
 
Test unitaires - refactoring - clean code
Test unitaires - refactoring - clean codeTest unitaires - refactoring - clean code
Test unitaires - refactoring - clean codeHadrien Blanc
 
intro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APPintro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APPfrwebhelp
 
Javascript un langage supérieur
Javascript un langage supérieurJavascript un langage supérieur
Javascript un langage supérieurFredy Fadel
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowMathias Kluba
 
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !Paris Salesforce Developer Group
 
Développement piloté par les tests - DDD
Développement piloté par les tests - DDDDéveloppement piloté par les tests - DDD
Développement piloté par les tests - DDDPyxis Technologies
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovyguest6e3bed
 

Ähnlich wie Coder propre ! (20)

Cours Ynov JS B1_1
Cours Ynov JS B1_1Cours Ynov JS B1_1
Cours Ynov JS B1_1
 
Design poo togo_jug_final
Design poo togo_jug_finalDesign poo togo_jug_final
Design poo togo_jug_final
 
Design poo togo_jug_final
Design poo togo_jug_finalDesign poo togo_jug_final
Design poo togo_jug_final
 
Tdd en action - découverte
Tdd en action - découverteTdd en action - découverte
Tdd en action - découverte
 
Tester du legacy code, mission impossible ?
Tester du legacy code, mission impossible ?Tester du legacy code, mission impossible ?
Tester du legacy code, mission impossible ?
 
C'est quoi, du bon code ?
C'est quoi, du bon code ?C'est quoi, du bon code ?
C'est quoi, du bon code ?
 
Scripting Linux avec Python partie1.pptx
Scripting Linux avec Python partie1.pptxScripting Linux avec Python partie1.pptx
Scripting Linux avec Python partie1.pptx
 
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logicielle
 
Qualité de code et bonnes pratiques
Qualité de code et bonnes pratiquesQualité de code et bonnes pratiques
Qualité de code et bonnes pratiques
 
Test unitaires - refactoring - clean code
Test unitaires - refactoring - clean codeTest unitaires - refactoring - clean code
Test unitaires - refactoring - clean code
 
intro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APPintro-csharp developement master 2 IF APP
intro-csharp developement master 2 IF APP
 
Td pascal tdD
Td pascal tdDTd pascal tdD
Td pascal tdD
 
Javascript un langage supérieur
Javascript un langage supérieurJavascript un langage supérieur
Javascript un langage supérieur
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - Specflow
 
Tour d'horizon des tests
Tour d'horizon des testsTour d'horizon des tests
Tour d'horizon des tests
 
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
La Tooling API, est-ce pour moi ? Bien sûr, viens voir pourquoi !
 
Développement piloté par les tests - DDD
Développement piloté par les tests - DDDDéveloppement piloté par les tests - DDD
Développement piloté par les tests - DDD
 
Anatomie du test
Anatomie du testAnatomie du test
Anatomie du test
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 

Coder propre !

  • 1. Coder propre aka Clean CodeJoseph Pachod https://twitter.com/joeclueless
  • 3. Raisons traditionnelles ● On lit + le code qu'on ne l'écrit ● Évolutivité de l'application ● Développer la prochaine version plutôt que de corriger l'actuelle ● Respecter la norme ou les règles de développements imposées
  • 5. Code sale... ● fragile ● compliqué ● plein de (mauvaises) surprises ● effets de bord inattendus ● duplication ● illisible ● peu performant ● dur à améliorer ● ...
  • 6. Dégâts perceptibles à tous les niveaux ● Chaque évolution est une nouvelle galère ● Développement laborieux, répétitif et aléatoire ● Délais et surprises pour la moindre modification (gestion de projet peu agréable) ● Expérience utilisateur mauvaise (régressions & bugs fréquents)
  • 7. Le code sale tue... ● Les développeurs qui s'arrachent les cheveux.. ● Les produits quand on ne parvient plus à les maintenir ou faire évoluer. ● Les entreprises derrière tout cela.. La réécriture complète n'est pas la solution : ● absence de nouvelles fonctionnalités pendant l'intervalle, ● recommencer pareil donnera la même chose, ● l'existant est certainement plus riche que vous ne le pensez.. ● La concurrence sera bien plus loin d'ici là.
  • 8. Coder propre ou ne pas faire d'informatique ! => coder propre : voie de salut pour le développeur, la gestion de projet et les utilisateurs
  • 9. Comment ? Savez vous coder propre ? Coder sale n'apprend pas comment coder propre...
  • 10. Faire complexe est facile, faire simple est difficile. Situation paradoxale. Mais la complexité se paie très vite...
  • 11. De l'envie et le reste suivra ! Nécessité d'envie du développeur : il est seul face au clavier ! Se poser des questions sur code, réfléchir, essayer… Mais aussi : Discuter, lire, écouter !
  • 12. You can't dictate software quality -- quality development has to be grown. Bruce Eckel Le code propre ne s'impose pas. Il s'apprend, se nourrit et se développe. C'est un travail d'équipe qui nécessite l'adhésion (ou la prise de conscience) de tous. Les chefs de projet sont généralement bien plus réceptifs qu'on ne le croit : dur de faire pire bien souvent...
  • 13. De l'engrais intellectuel pour démarrer ! Maintenant que la nécessité de code propre est partagée (espérons!), voyons pour aider à son démarrage. Attention : des pistes, des conseils, pas de dogmes religieux. Chaque langage/framework/équipe/développeur a ses propres bonnes pratiques : se renseigner, discuter et se mettre d'accord avec son équipe.
  • 14. Pour commencer… on se détend ! La suite évoque des pistes, des conseils, pas de dogmes religieux. Il n'y a pas de définition précise du code propre. Chaque langage/framework/équipe/développeur a ses propres bonnes pratiques : se renseigner, discuter et se mettre d'accord avec son équipe. A chacun de trouver sa voie.
  • 15. Juste des exemples Exemples de code à venir : mise en avant de points, pas code parfait... Utilisation fréquente des termes « Foo » et « Bar », pour se concentrer sur le code et non le fonctionnel. Par exemple : public class Foo { public Bar doBar() { return new Bar(); } } (snip) : indique que plein de code non relevant pour l'exemple devrait être présent => on ne sait rien du fonctionnel, on peut parler du code
  • 16. Donner du sens au code
  • 17. Que fait le code qui va suivre ?
  • 18. // @author setUpYourName public class BadCodeWithComments { private Bar var1 ; /** Takes a bar then foo **/ public void foo() { // on testte l'état if( var1.state == null || var1.state == 0 /* foo.state == 1 || */ ) { (snip) } } } Auteur du code : manifestement faux, inutile, n'apporte rien. Le commentaire sur la méthode semble référer à une version antérieure, car évoque un argument plus présent. Le commentaire sur le test décrit le détail du test : aucune valeur ajoutée. Faute de français : distraction en plus... Noms et valeurs d'aucune aide : var1, state, entier 0 et 1... Génériques, interchangeables à volonté => vides de sens : on ignore de quel « state » on parle ainsi que le sens des valeurs testées Qu'indique la ligne commentée ci dessous ? /* foo.state == 1 || */ La valeur 1 n'est plus présente ? La valeur 1 n'est plus à tester ? Quelqu'un a fait un test et a oublié de dé commenter ? => soulève de nombreuses questions, alors qu'elle ne fait rien !!
  • 19. Mort aux commentaires ! Le moins possible de commentaires ● Signes d'un manque d'expressivité du code ● Faciles à bâcler, dur à écrire proprement, quasi impossible à maintenir - commentaires alors trompeurs et erronés ● Ne PAS commenter le code modifié - on a un gestionnaire de source pour cela On réessaie
  • 20. public class BadCode { private Bar var1 ; public void foo() { if( var1.state == null || var1.state == 0 ) { (snip) } } } On voit plus vite qu'on ne voit rien...
  • 21. Des commentaires ne sauvent pas du mauvais code. Tentative d'expliciter très dure à réaliser S'attaquer à la cause plutôt que de tenter de l'enjoliver
  • 22. Indiquer l'intention (le pourquoi) La lecture du code doit en permettre la compréhension directement
  • 23. public class BetterCode { private Bar last; public void foo() { if (last.isInProgress()) { (snip) } } } Nommage explicite des classes, méthodes et variables Pas de « bruit » inutile. Bon niveau de détail : ● si on veut savoir comment est fait le test, on va voir dans la méthode. ● Sinon on peut continuer à explorer le code actuel sans surcharge cognitive. Et aucun commentaire :)
  • 25. ArrayList<String> list = new ArrayList<>(); vs List<String> names = new ArrayList<>();
  • 26. Le pourquoi pas le comment - Le code indique le comment Dans tout ce qu'on utilise indiquer le pourquoi (une liste, des noms) plutôt que le comment (une liste chainées, des chaines de caractères). Le code permet toujours de voir le comment (quelque part). Pas le pourquoi. Evite également les redites et donc le risque de décalage à terme.
  • 28. Nommer même si court ● Même une méthode d'une ligne est mieux ● Petites méthodes bien plus réutilisables ● Méthodes surchargeables… ● Méthode évolutive
  • 29. if (bar.isNotDone() == false) vs if (bar.isDone())
  • 30. Faciliter la lecture - Pas de double négation Un ordinateur parvient à lire de l'assembleur : on code pas pour lui mais pour les autres humains. Aussi, le code doit pouvoir être lu. Par exemple nommer positivement est préférable à la double négation
  • 32. Faciliter la prononciation - Noms longs pas un problème Le code lu est une bonne chose, mais c'est encore mieux quand on en discute. Pour cela, on doit pouvoir prononcer les éléments du code. Si plus clair, recherche également plus aisée.
  • 34. Acronymes en camel case - Facilite la recherche via l'IDE Plus lisible La convention Sun/Oracle et Microsoft Permet la recherche de type dans l'éditeur via camel case : FXD → FoXmlData Sinon : FOXMLD → FOXMLData Ne « crie » pas au milieu code
  • 35. public int id; vs public Identifier<Good> id;
  • 36. Typer Les entiers sont communément utilisés : si vous voyez un entier quelque part, cela sera t il pour autant l'identifiant que vous cherchez ? Si l'identifiant a des contraintes particulières, impossible de le voir avec un entier : besoin de regarder autour/en base pour comprendre les valeurs autorisées et le fonctionnement. A l'inverse, une classe dédiée : ● permet de voir tous les usages de l'identifiant en question (via les références dans le code) ● Permet d'aisément ajouter ou supprimer des comportements ● N'importe où dans le code où ce type est présent, on sait de suite de quoi il s'agit ou, au pire, il suffit d'aller voir la classe en question pour avoir le détail
  • 37. return null;return null; vs returnreturn Collections.Collections.emptyListemptyList()();;
  • 38. Eviter les mauvaises surprises - Ne pas provoquer de NullPointerException
  • 39. public Foo getFoo(){ (snip) return null; } vs public Optional<Foo> getFoo(){ (snip) return Optional.empty(); }
  • 40. Expliciter - Optional empêche d'oublier qu'une valeur peut être nulle
  • 41. public Foo getFoo(){ if(foo == null){ foo = createFoo(); } return foo; } vs public Foo getOrCreateFoo(){ if(foo == null){ foo = createFoo(); } return foo; }
  • 42. Ne rien cacher - Eviter les effets de bord
  • 43. Un cas plus concret
  • 44. public void doStuff() { (snip) sendEmail("admin@acme.com", "Stuff done", "Details"); } private void sendEmail(String to, String subject, String text) { String from = "system@acme.com"; String host = "smtp.acme.com"; Properties props = new Properties(); props.put("mail.smtp.host", host); Session session = Session.getInstance(props); Message msg = new MimeMessage(session); (snip) Transport.send(msg); } 2 choses différentes au même endroit : le but initial de la classe, doStuff, et l'envoi de mail Conséquences ● Longueur de la classe ● Détails et mises en œuvre très différents Plein de problèmes latents : ● Réutilisation difficile ● Changements difficiles car plein de valeurs codées en dur ● Si le code de l'envoi de mail est copié ailleurs, sera t il bien iso fonctionnel ? ● Quid en cas d'erreur/exception lors de l'envoi du mail ? Impacts sur doStuff() ? => mauvais
  • 45. private final Mailer mailer; public Good(Mailer mailer) { this.mailer = mailer; } public void doStuff() { (snip) mailer.sendEmail("admin@acme.com", "Stuff done", "Details"); } Rendre indépendant au maximum les différents modules les uns des autres ● le service d'envoi de mail ne doit faire que ça, sans dépendre ou appliquer des logiques relevant d'autres choses ● Pas de logique en fonction du contexte (utilisateur courant par exemple) ● Utilisation possible du service en dehors d'un contexte web => Augmente la réutilisation Se concentrer sur l'essentiel d'une fonctionnalité permet de la traiter correctement ● Notamment le traitement des cas d'erreurs ● En proposant différentes méthodes correspondant aux différents besoins d'appels => meilleur
  • 46. Faire une chose à la fois - Permet de faire une fois bien Lorsqu'on ne duplique pas la même chose plusieurs fois, on n'a qu'un seul endroit à améliorer pour améliorer tous les usages de la chose en question. Qui plus est, en faisant une fois, on est plus incité à faire bien, alors qu'une recopie de plus n'incite guère à l'effort. Au demeurant, toutefois, il n'est pas nécessaire de faire forcément mieux qu'on aurait fait initialement. En effet, une énorme valeur ajoutée est de pouvoir faire mieux plus tard, lorsqu'on aura commencé à rencontrer des problèmes.
  • 47. private final Notifier notifier; public Better(Notifier notifier) { this.notifier = notifier; } public void doStuff() { (snip) notifier.notify(userAcme, "Details", "Stuff done"); }
  • 48. Découpler - Tant entre classes que de l'implémentation Bien réfléchir au nommage et au périmètre des services ● L'envoi de mails n'est qu'une des façons de notifier ● L'idée était de notifier, pas d'envoyer un mail ● Permet de généraliser : on passe désormais l'utilisateur et non plus directement l'adresse Ne pas hésiter à séparer la déclaration de l'implémentation ● Initialement peut être que seul l'envoi de mail marche ● Distingue bien le comment du pourquoi => encore meilleur
  • 49. Le code doit être auto descriptif Etat d'esprit de ce qui a été présenté. Tout doit tendre vers cela.
  • 50. final String CHRISTMAS_DAY = "25/12"; final String NEW_YEAR_DAY = "01/01"; final String FRENCH_NAT_DAY = "14/07"; final String workersDay = "1/1"; Quelle ligne a ajouté le nouveau venu dans l'équipe ?
  • 51. Respecter le style en vigueur Uniformité du style => lecture plus aisée Code résultat d'une action collective ● par défaut, respecter le style en place ● si besoin, discuter et décider en équipe du nouveau style et des modalités de transition Evite de se faire haïr... et accessoire : le style en vigueur n'a pas d'effet sur la qualité du code.
  • 52. Commenter uniquement en dernier recours Mettre des commentaires quand toutes les tentatives pour rendre intelligible le code ont échoué. C'est par exemple souvent requis pour des contraintes externes. De même une explication générale est souvent dure à rendre uniquement par le code, même si cette explication générale ne retire rien à bien nommer son API, des méthodes aux exceptions.
  • 53. Durer
  • 54. Refactoring - Renommer, extraire avec l'IDE Actualiser le code existant ● noms mis à jour ● évolutions de la structure même si besoin => le code doit refléter l'état actuel des connaissances métier Pas de connaissance en dehors du code
  • 55. Refactoring - Modifications plus complexes ? Changements des règles... Réalisation d'un manque de logique quelque part.. Cas non prévu… Problème de performances...
  • 57. Plus de refactoring : code mort
  • 58. Comment être sûr de son code ?
  • 59. De la première ligne après 1000 lignes... Lors de tests manuels de son code, on exécute les bouts qu'on vient d'écrire. Aussi, on exécute au début le code initial, mais comment s'assurer à la fin que ce dernier soit toujours fonctionnel ?
  • 60. De la première ligne après 6 mois...
  • 62. Coder vos tests - En premier ou en même temps
  • 63. Etre le premier utilisateur de son code Soyez le premier utilisateur de votre code via les tests ● Avant même que le code ne soit écrit : permet de voir si l'utilisation correspond aux attentes ● Changer d'avis ne coute alors rien !
  • 64. Améliore le code Tester son code implique de s'en servir dans un contexte un peu différent que celui de son exécution normale. Aussi, cela nous amène souvent à découpler et rendre le code modulaire, ce qui est un gage de pérennité.
  • 66. Quelques pistes pour le code pré existant
  • 73. Tests d'IHM - Aller au bout Au plus proche des utilisateurs
  • 74. Tests d'IHM avec côté serveur - Lents Très fragiles Coûteux à mettre en oeuvre
  • 75. Tests d'IHM uniquement côté client - Rapides Fragiles Abordables
  • 76. Spécifications par l'exemple (Behavior Driven Development - Acceptance tests) - Fonctionnalités et exemples en langage métier
  • 77. Spécifications par l'exemple - Utilisées pour spécifier Automatiser Sur l'ensemble du code métier
  • 79. Tests de performance - L'optimisation prématurée est la source de tous les maux. (Premature optimization is the root of all evil) - Tester quand tout va bien Les problèmes de performances doivent être avérés, mesurés et reproductible avant leur correction. Bien cibler un problème de performance est primordial pour le régler (cf outils comme JMH). Bien souvent nos hypothèses concernant les causes de problèmes de performances sont fausses ou non déterminantes. La réalité est bien plus complexe, le fonctionnement des systèmes actuels bien plus riches que nous le supposons.. A l'inverse, tant qu'aucun problème n'est présent prendre divers raccourcis sous prétexte de performance au détriment du code propre n'est qu'une excuse. Enfin, tester les performances en non régression permet de voir au plus tôt l'introduction de code pénalisant celles ci.
  • 80. Tests aussi du code propre
  • 81. Tester = code cartésien
  • 82. Maîtrisez votre IDE ! Votre IDE peut faire beaucoup, apprenez ses capacités, notamment : ● génération de code ● via des templates pour des éléments récurrents (le logger par exemple) ● en écrivant un code minimal, qui ne compile pas, et en le laissant créer le reste ● découverte/lecture du code ● liste des appelants ● références ● hiérarchie des classes ● propositions de refactoring ● renommage & déplacements ● création de méthode ● formatage automatique ● plus simple pour relire le code du collègue ● analyse de la qualité du code Surtout : apprenez ses raccourcis pour être efficace
  • 84. Première loi de la qualité logicielle errors = (more code)2 e=mc2 Moins il y a de code à maintenir, mieux c'est Du code non fréquemment exercé tend à devenir rapidement obsolète ou contenir des erreurs Mieux peu qui tourne que beaucoup qui plante
  • 85. 2000 options de configuration vs code facile à modifier But : avoir du code simple facile à changer, pas du code complexe "qui fait tout" dur à modifier. Les besoins de demain seront différents des prévisions d'aujourd'hui Eviter les usines à gaz de paramétrage avec 2000 choix, mais (généralement) pas celui désiré Si code propre, alors modification aisée. => KISS (Keep It Simple Stupid) Les 2000 options sont autant d'aveux de faiblesse quant au comportement que doit avoir le logiciel.
  • 86. Egoless programming Critique du code != critique de soi => les discussions et critiques autour du code sont primordiales. Elles ne doivent pas être prises comme des attaques personnelles. Etre accessible et prêt à discuter
  • 87. Règle du Boy Scout Laisser le code plus propre qu'en arrivant Préoccupez vous du code !
  • 88. Améliorer le métier du client Objectif d'un codeur ? - Coder ? - Livrer un ensemble de code cohérent ? - Livrer un produit, incluant sa vie opérationnelle ? - Améliorer le métier du client ? Améliorer le métier du client est la seule façon d'apporter de la valeur via le code. Et est crucial pour un éditeur !
  • 89. Retour à la réalité
  • 90. Coût du coder propre Coût intellectuel ● Remise en cause ● Changement Coût initial ● Premières lignes codées propres laborieuses ● Beaucoup de réflexions (salutaire) Coût au quotidien ● Léger surcoût au premier dév d'une fonctionnalité ● Gain dès qu'on a besoin de relire, retoucher ou réutiliser => arrive généralement bien plus tôt qu'on ne le pense Mieux vaut passer un peu plus de temps au début pour bien faire que de supporter ensuite longtemps quelque chose de mal fait !
  • 91. Distribution de quasiment toutes les compétences que nous savons mesurer… Il n'y a pas que deux niveaux de développeurs, les mauvais et les ninjas ! L'immense majorité d'entre nous est quelque part au milieu de l'image.
  • 92. Améliorons nous ! Lecture ● De livres, par exemple Clean code ● De code "propre" -> nombreux projets Open Source (mais pas tous, souvent un signe de maturité, ex lucene, wicket, jquery) Ateliers/conférences ● Qu'ils soient dédiés au code propre (tests...) ● Ou sur un autre sujet : les échanges avec du code sont toujours très instructifs, tout comme voir un autre coder (et se servir de son environnement) Ensemble ● Revue de code ● Pair programming : toujours très instructif
  • 94. Coder propre nécessaire, mais pas suffisant.
  • 95. Il suffit de s'y mettre !
  • 96. Coder propre sous partie d'un tout bien plus vaste ! Autres points à considérer : - programmation fonctionnelle, - capture du métier, - ergonomie, - prise en compte de l'opérationnel, - ...