Code CompleteSébastien Combéfis
Lundi 29 février 2016
Ce(tte) œuvre est mise à disposition selon les termes de la Licence Creative CommonsAttribution – Pas d’Utilisation Commerciale – Pas de Modification 4.0 International.
Contexte
W. Strunk et E. B. White
1918B. W. Kernighan et P. J. Plauger
1974
3
Qualité de code
4
“Always code as if the guy who ends up maintainingyour code will be a violent psychopath who knowswhere you live.” — Martin Golding
“Always code as if the guy who ends up maintainingyour code will be a violent psychopath who knowswhere you live.” — Martin Golding
Cacher l’information
Deux catégories de secrets
Cacher la complexité pour le développeur
Cacher les sources de changement pour faciliter les modifs
Barrière au masquage d’information
Distribution excessive de l’information
Dépendance circulaire
Confondre variable de classe avec variables globales
6
Identifier le changement
Importance d’identifier le changement pour l’isoler
1 Identifier les éléments qui pourraient changer
2 Séparer les éléments identifiés dans une classe
3 Isoler les éléments identifiés du reste
Exemples communs qui peuvent changer
Règles business (facturation, taxe...)
Dépendances hardware
Entrée/sortie (format de fichiers produits)
Fonctionnalités non standards des langages
Zones avec des constructions difficiles
Variable statuts7
Couplage
Il faut maintenir un couplage le plus faible possible
Critères de couplage
Minimiser le nombre de connexions vers d’autres modules
Rendre les connexions visibles
Pouvoir changer les connexions par flexibilité
Types de couplage
Simple-data-parameter (passage de paramètre primitif)
Simple-object (un objet instancie un autre objet)
Object-parameter
Semantic8
Code de qualité
Focus sur la programmation orientée objet
Analyse top-down
Depuis la classe jusqu’aux instructions
Classe Méthode Instruction
9
Trouver les objets du monde réel
Identifier l’objet et ses attributs
Déterminer ce qui peut être fait avec l’objet
Identifier ce que l’objet peut faire à d’autre objets
Déterminer ce qui sera visible de l’objet
Définir l’interface publique de l’objet
10
Programmer avec des classes
Abstract Data Type
ADT
Cacher les détailsd’implémentation
Rendre les changementsindépendants du restedu programme
Le programme estauto-documenté
Le programme manipuledes entités qui modélisentle monde réel
11
Manipuler les objets du monde
getFuelLevel
isOnGroundstartEngine
startAutopilot
Abstraction
Créer une bonne abstraction de l’objet représenté
S’assurer que les détails d’implémentation soient bien cachés
L’abstraction doit former un tout cohérent et consistent
Le niveau d’abstraction doit être consistent
Abstraction — “Le fait de voir une opération complexesous une forme simplifiée”
13
Encapsulation
Minimiser l’accès aux classes et à leurs membres
Ne pas exposer les données de la classe
Ne pas exposer des détails d’implémentation
Diminuer au maximum le couplage entre classes
public class GradeReport{
private Grade[] grades;
public double getGrade (String courseName) { /∗ ... ∗/ }
private static class Grade { /∗ ... ∗/ }}
14
Composition ou héritage ? I
HAS-A
Une classe se compose àpartir d’autres
7± 2 (composants)
Surveillez le couplage
IS-A
Une classe est unespécialisation d’une autre
6 (niveaux d’héritage)
Surveillez l’encapsulation
Liskov Substitution Principle (LSP)
Si q(x) est une propriété démontrable pour tout objet x de type T ,Alors q(y) est vraie pour tout objet y de type Stel que S est un sous-type de T .
15
Composition ou héritage ? II
Vehicle
Car Wheel
is-a
has-a
16
Membres d’une classe
Limiter le nombre de méthodes
Limiter les appels de méthodes directs et indirects
En général : limiter la collaboration avec d’autres classes
Law of Demeter (LoD)
Une méthode M d’un objet O ne peut invoquer que :1 ses propres méthodes ;2 les méthodes de ses paramètres ;3 les méthodes des objets qu’elle instance ;4 et les méthodes de ses objets composants.
17
Constructeurs
Initialiser toutes les variables d’instance
Interdire la création d’instances avec un constructeur privé
Éviter les shallow copies des paramètres
public class BookStore{
private Books[] books;
public BookStore (Books[] books){
this.books = books;}
}
18
Deep or shallow copies ?public class Exam{
private Course course;private Student[] students;
public Exam (Course course, Student[] students){
this.course = course;this.students = students;
}}
public class Test{
public static void main (String[] args){
Student[] students = /∗ ... ∗/ ;Exam exam = new Exam (/∗ ... ∗/, students);Arrays.fill (students, null);
}}
19
Pourquoi une classe ?
Modéliser un objet du monde réel
Modéliser des objets abstraits
Réduire ou isoler la complexité
Limiter les impacts lors de modifications
Cacher les données et détails d’implémentation
Faciliter la réutilisation de code
20
Avoid God classesalso known as The Blob
Toute puissante et qui sait tout
Passe son temps à appeler des get et set
Classes à éviter
Éviter les classes God
Éliminer les classes hors sujet
Classes avec seulement des données
Éviter les classes dont les noms sont des verbes
Classes avec seulement des comportements
22
Programmer avec des routines
Réduire la complexité
Introduit des abstractions intermédiaire et compréhensibles
Éviter la duplication de code
Faciliter la réutilisation de code
23
Pourquoi rassembler des instructions ?
Cohésion fonctionnelleUne routine = une opération
Cohésion séquentielleSéquence d’instructions qui partagent des données
Cohésion communicationnelleOpérations qui utilisent la même donnée
Cohésion temporelleOpérations qui doivent avoir lieu en même temps
24
Choisir le bon nom
Décrire ce que fait la routine
Éviter les verbes vagues : process, handleOutput...
Ne pas différencier rien que par un numéro : test1, test2...
Ne pas hésiter sur la longueur du nom
Utiliser les opposés à bon escient : get/put, start/stop...
Fonction : décrire la valeur de retour
Procédure : verbe fort + sujet pour décrire l’action
25
Longueur d’une routine
Pas de convention globalement acceptée
Doit tenir sur un écran ou une/deux page/s (50–150 lignes)
Convention NASA pour développer un code critique
60 lignes de code maximum par routine
26
Paramètres d’une routine
39% des erreurs viennent de l’interface entre routines
Cette interface se fait lors des appels de routines
Bonnes pratiques par rapport aux paramètres
Ordre des paramètres : input/modify/output
Même ordre lorsque routines avec les mêmes paramètres
Utiliser tous les paramètres
Ne pas utiliser les paramètres comme variable de travail
Documenter les hypothèses sur les paramètres
Limiter le nombre de paramètres (environ 7)
27
Protégez-vous !
Données provenant de sources externesValeurs des paramètres des routines
Gestion des erreurs ou assertion ?
Gestion des erreursÀ utiliser pour des situations particulières qui pourraient seproduire
AssertionÀ utiliser pour des situations qui ne surviendront jamais
public Book getBook (int bookid){
for (int i = 0; i < books.length; i++){
if (books[i].getId() == bookid) { return books[i]; }}
assert false;return null;
}
29
Assertion
Le code doit rester fonctionnel sans les assertions
Vérification des préconditions et postconditions
Peut être vu comme des commentaires exécutables
30
Gestion des erreurs
Renvoyer une valeur neutre
Passer la donnée erronée
Renvoyer la même valeur que lors du dernier appel
Afficher un message d’erreur
Mécanisme d’exception pour communiquer des erreurs
Correctness <> Robustness31
One variable = One purposeOne variable = One purpose
Déclaration
Initialisation lors de la déclaration
... dans le constructeur pour les variables d’instance
Déclaration le plus proche de l’utilisation
Utilisez les constantes
33
Span et durée de vie
Le « span » mesure l’espacement de l’utilisation de la variable
La durée de vie mesure le nombre d’instructions pourlesquelles la variable existe
public void test(){
int a = 0;int b = 0;int c = 0;b = a + 1;b = b / c;
}
Variable b
Average span : (1 + 0)/2 = 0.5
Live time : 4
(les deux valeurs sont à minimiser)
34
Minimiser la portée
Initialiser les variables utilisée dans une boucle juste avant
Ne pas retarder l’initialisation d’une variable
Grouper les instructions liées (avec les mêmes variables)
Séparer les groupes d’instructions liées en routines
Toujours commencer avec la visibilité la plus faible
35
Variable
Le nom décrit contenu de la variable et la documente
Longueur optimale entre 9 et 15 caractères
Une variable utilisée pour une seule raison
Éviter les variables avec plusieurs significations selon la valeur
S’assurer que toutes les variables sont utilisées
36
Choisir les noms
Noms avec signification proche : input et inputVal
Noms similaires : clientRec et clientRep
Éviter les nombres : total1 et total2
Attention à l’orthographe !
Éviter de mélanger les langues
Éviter des caractères difficiles à lire : char1 et chartl, cOnf etc0nf, GREAT et 6REAT, tex2html et texZhtml...
37
Nom pour types de données spécifiques
Compteur des boucles i, j, k (sauf si utilisée hors boucle)
Sauf pour les longues boucles, où un nom parlant est mieux
Ne pas mettre flag dans le nom des variables de statut
Les variables temporaires sont à éviter (temp...)
Nommer les variables booléennes (done, error, found, ok,success...) avec nom qui implique true ou false
38
Data types
Nombre (1)
Éviter les nombres magiques
Hardcoder les valeurs 0 et 1 ne pose pas problème
Anticiper les divisions par zéro
Rendre les conversions de type explicite
Éviter les comparaisons de types différents
40
Nombre (2)
Nombre entier
Vérifier les divisions par zéro
Vérifier les dépassements de capacité
Diviser avant de multiplier (1e6 * 1e6 / 1e6)
Nombre flottant
Éviter addition et soustraction de nombres de magnitudes 6=
Éviter les comparaisons pour l’égalité
Anticiper les erreurs d’arrondi
41
Chaine de caractères
Éviter les caractères et chaines magiques
Attention à l’accès par indice avec les méthodes utilisées
Attention au support ou non d’Unicode
Penser à la politique d’internationalisation de l’application
42
Autres types
Booléen
Utiliser les booléens pour documenter son programme
En nommant des expressions booléennes pour les conditions
Simplifier les tests complexes avec des booléens
Tableau/Liste
S’assurer que les indices restent dans les bornes
Attention aux indices lorsque plusieurs dimensions
43
Writing programs is like writing books
Code séquentiel
Respecter l’ordre lorsqu’il a de l’importance
Rendre visible les dépendances (noms des routines, arguments)
Grouper les instructions de manière logique
45
Instructions conditionnelles
Traiter les cas normaux d’abord (avec le if) ensuite les casd’erreur (avec le else)
Faire attention à bien utiliser < ou <=
Simplifier les conditions complexes par un appel de fonction
Ordonner les cas en commençant par le plus fréquent
46
Instructions répétitives (1)
Boucles while, for et foreach
Un seul point d’entrée par boucle
Code d’initialisation juste avant la boucle
Boucle infinie avec while(true){}
Éviter les boucles vides
Mise à jour des variables de contrôle en début ou fin du corps
Une boucle = une fonction
47
Instructions répétitives (2)
S’assurer que la boucle se termine et rendre la condition determinaison claire et limpide
Ne pas faire le singe en changeant les variables de contrôlepour quitter la boucle
Ne pas dépendre de la valeur des variables de contrôle après laboucle
Utiliser les break, mais avec modération
48
Imbriquer des boucles
Attention aux noms des variables de contrôle
Limiter la portée des variables de contrôle à la boucle
Au grand maximum trois niveaux d’imbrication de boucles
On doit pouvoir lire la boucle de manière globale
49
Expressions booléennes
Comparer implicitement des booléens avec true et false
Casser des conditions trop complexes en utilisant des variablesbooléennes intermédiaires ou dans une routine
Inverser la logique pour avoir la condition du if positive
Simplifier les expression booléennes avec la loi de De Morgan
! (A || B) ≡ ( !A) && ( !B)! (A && B) ≡ ( !A) || ( !B)
50
Fundamental Theorem of Formatting
“A good visual layoutshows the logical
structure of a program”
“Any fool can write code that a computer canunderstand. Good programmers write code thathumans can understand.” — Martin Fowler
“Any fool can write code that a computer canunderstand. Good programmers write code thathumans can understand.” — Martin Fowler
Bon layout
Représenter la structure logique du code de manière précise etconsistante
Augmenter la lisibilité
Supporter et faciliter les modifications
En utilisant les blancs pour regrouper, et pour indenter et lesparenthèses pour clarifier les expressions
52
Quelques règles de layout
Une ligne de code ne devrait pas dépasser 80 caractères
Une déclaration de variable par ligne
Dans une classe : commentaire d’entête, données, méthodespublic, protected puis private
53
Les commentaires
Répétition du code
Explication du code
Marqueurs dans le code
Résumé du code (focus sur le pourquoi, et pas sur le comment)
Explication de l’intention du code (niveau problème et pas solution)
Information additionnelle non présente dans le code
“Good code is its own best documentation.” — Steve McConnell
54
Do not comment tricky code, rewrite it!Do not comment tricky code, rewrite it!
56
57
En résumé
Réduire la complexité
Écrire ses programmes pour des humains, pas pour la machine
Consistance et cohérence
Garder les éléments proches de leurs utilisations
Penser et coder au niveau du problème, pas de la solution
58
À suivre
http://geek-and-poke.com/
http://www.codinghorror.com/blog/
59
Livres de référence I
ISBN 978-0-735-61967-8 ISBN 978-0-132-35088-4 ISBN 978-0-596-51004-6
60
Livres de référence II
ISBN 978-0-201-61622-4 ISBN 978-0-321-35668-0 ISBN 978-0-201-48567-7
61
Créditshttps://www.flickr.com/photos/toolmantim/2887927385https://www.flickr.com/photos/smitty/2245445147http://www.flickr.com/photos/tetezinharomana/7152072635/http://www.flickr.com/photos/jetstarairways/6769120131/http://www.flickr.com/photos/47104521@N08/4332849715/http://www.flickr.com/photos/dunechaser/2936384313/http://www.flickr.com/photos/sillydog/287354869/https://www.flickr.com/photos/small_realm/15375289074http://www.flickr.com/photos/j1x4r/4313734090/http://www.flickr.com/photos/focx/5485671820/http://www.flickr.com/photos/cyberslayer/952153409/http://geek-and-poke.com/geekandpoke/2014/7/17/simply-explainedPhotos des livres depuis Amazon
62