├── _config.yml ├── 02_introduction_algorithms ├── chapitre_10.md ├── README.md ├── chapitre_08.md ├── chapitre_06.md ├── chapitre_09.md ├── chapitre_03.md ├── chapitre_07.md ├── chapitre_04.md ├── chapitre_01.md ├── chapitre_05.md └── chapitre_02.md ├── 03_computer_architecture ├── 02_memory_hierarchy_design.md ├── 00_introduction.md └── 01_fundamentals_of_quantitative_design_and_analysis.md ├── 01_coder_proprement ├── README.md ├── chapitre_10.md ├── chapitre_11.md ├── chapitre_04.md ├── chapitre_05.md ├── chapitre_03.md ├── chapitre_08_09.md ├── resume_complet.md ├── chapitre_13_bis.md ├── chapitre_13.md ├── chapitre_06_07.md ├── chapitre_01.md └── chapitre_02.md └── README.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_10.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 10 - Structures de données élémentaires 3 | 4 | ## Introduction à la partie 3 5 | 6 | ## Piles et queues 7 | -------------------------------------------------------------------------------- /03_computer_architecture/02_memory_hierarchy_design.md: -------------------------------------------------------------------------------- 1 | 2 | # Memory Hierarchy Design 3 | 4 | ## Introduction 5 | 6 | Principe de localité : 7 | - temporel 8 | - spatial 9 | 10 | Hériarchie de mémoire à plusieurs niveaux 11 | 12 | Type de mémoire | Taille | Vitesse 13 | --------------- | ------ | ------- 14 | Registre CPU | 1k-4k | 0,2-0,3 ns 15 | Cache L1 | 16 | -------------------------------------------------------------------------------- /02_introduction_algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Livre 02 - Introduction to Algorithms 2 | 3 | De Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest et Clifford Stein. 4 | 5 | Partie 1 - Fondations 6 | 7 | - [Chapitre 1 - The Role of Algorithms in Computing](chapitre_01.md). Séance du 26 février 2018. 8 | - [Chapitre 2 - Getting Started](chapitre_02.md). Séance du 5 mars 2018. 9 | - [Chapitre 3 - Growth of Functions](chapitre_03.md). Séance du 12 mars 2018. 10 | - [Chapitre 4 - Divide-and-Conquer](chapitre_04.md). Séances du 19 mars 2018 (parties 4.1 à 4.3) et 2 avril 2018 (parties 4.4 à 4.6). 11 | - [Chapitre 5 - Probabilistic Analysis and Randomized Algorithms](chapitre_05.md). Séance du 9 avril 2018. 12 | 13 | Partie 2 - Tri et rangs 14 | 15 | - [Chapitre 6 - Heapsort](chapitre_06.md). Séance du 16 avril 2018. 16 | - [Chapitre 7 - Quicksort](chapitre_07.md). Séance du 23 avril 2018. 17 | - [Chapitre 8 - Sorting in Linear Time](chapitre_08.md). Séance du 30 avril 2018. 18 | - [Chapitre 9 - Medians and Order Statistics](chapitre_09.md). 19 | 20 | Partie 3 - Structures de données 21 | 22 | - [Chapitre 10 - Structures de données élémentaires](chapitre_10.md). 23 | -------------------------------------------------------------------------------- /01_coder_proprement/README.md: -------------------------------------------------------------------------------- 1 | # Coder proprement, de Robert C. Martin 2 | 3 | Le premier livre choisi est "Coder proprement", de Robert C. Martin. Les seances ont lieu tous les lundi à 20h. 4 | 5 | [Résumé complet du livre et commentaire global](resume_complet.md) 6 | 7 | Voici les résumés des chapitres et des discussions : 8 | 9 | - [Chapitre 1 - Code propre](livre_01/chapitre_01.md). Séance du 16 octobre 2017. 10 | - [Chapitre 2 - Noms significatifs](livre_01/chapitre_02.md). Séance du 30 octobre 2017. 11 | - [Chapitre 3 - Fonctions](livre_01/chapitre_03.md). Séance du 6 novembre 2017. 12 | - [Chapitre 4 - Commentaires](livre_01/chapitre_04.md). Séance du 13 novembre 2017. 13 | - [Chapitre 5 - Mise en forme](livre_01/chapitre_05.md). Séance du 28 novembre 2017. 14 | - [Chapitres 6 et 7 - Objets et structures de données et Gestion des erreurs](livre_01/chapitre_06_07.md). Séance du 4 décembre 2017. 15 | - [Chapitres 8 et 9 - Limites et Tests unitaires](livre_01/chapitre_08_09.md). Séance du 8 janvier 2018. 16 | - [Chapitre 10 - Les classes](livre_01/chapitre_10.md). Séance du 15 janvier 2018. 17 | - [Chapitre 11 - Systèmes](livre_01/chapitre_11.md). Séance du 22 janvier 2018. 18 | - [Chapitre 13 - Concurrence](livre_01/chapitre_13.md). Séance du 29 janvier 2018. 19 | - [Annexe A - Concurrence](livre_01/chapitre_13_bis.md). Séance du 5 février 2018. 20 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_08.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 8 - 8 Sorting in Linear Time 3 | 4 | algos en O(n lg n) : 5 | 6 | - merge sort et heapsort dans le pire cas 7 | - quicksort dans le cas moyen 8 | 9 | def: comparison sorts = comparaison entre les elements pour trier 10 | 11 | Plan : 12 | 13 | - 8.1 : prouver que comparaison sorts sont en Omega(n lg n) 14 | - 8.2 : couting sort 15 | - 8.3 : radix sort 16 | - 8.4 : bucket sort 17 | 18 | ## 8.1 Lower bounds for sorting 19 | 20 | compare 2 elements a_i <=> a_j 21 | 22 | Postulats: 23 | 24 | - tous les elements distincts, a_i = a_j n'est pas utile 25 | - toutes les comparaisons sont inutiles, on utilise a_i <= a_j 26 | 27 | ### The decision-tree model 28 | 29 | def: full binary tree, represente les comparaison entre les elements par un algo 30 | particulier sur une entree de taille donnee 31 | 32 | Chaque noeud noté i:j et chaque feuille noté par une permutation <1,2,3>. Branche de gauche = a_i <= a_j, brache de droite = a_i > a_j. 33 | n! permutations possible pour n elements. 34 | 35 | Execution = trouver un chemin depuis la racine vers une feuille 36 | 37 | ### A lower bound for the worst case 38 | 39 | worst case = chemin le plus long entre la racine et le plus long chemin 40 | 41 | Theorem 8.1: Any comparison sort algorithm requires Omega(n lg n) comparisons in the worst case. 42 | 43 | Corollary 8.2: Heapsort and merge sort are asymptotically optimal comparison sorts. 44 | 45 | ## 8.2 Counting sort 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_10.md: -------------------------------------------------------------------------------- 1 | 2 | # les classes 3 | 4 | ## Organiser une classe 5 | 6 | ?? ordre de declaration, public puis private, separation declaration implementation 7 | ?? protected pour les tests ? 8 | ?? outils du langages pour differentier les types de classes ? interface, pod, etc 9 | 10 | ## De petites classes 11 | 12 | pouvoir decrire brievement la classe 13 | SRP = raisons d’être modifié 14 | 15 | "Faire en sorte que le logiciel fonctionne et faire en sorte que le logiciel soit propre sont deux activités très différentes" 16 | ?? remarque souvent faites au debutants sur les forums. Interet de l'apprentissage du TDD et analyse statique des le debut? 17 | ?? Comment un debutant peut evaluer la maintenabilité du code ? Comment enseigner ca ? 18 | 19 | "Faire en sorte que le logiciel fonctionne et faire en sorte que le logiciel soit propre sont deux activités très différentes" 20 | -> "Par conséquent, la question est de savoir si vous voulez que vos outils soient rangés dans des boîtes à outils avec de 21 | nombreux petits tiroirs contenant des éléments parfaitement définis et étiquetés, ou si vous voulez avoir quelques tiroirs 22 | dans lesquels vous mettez tous vos outils en vrac." 23 | 24 | ** Cohésion 25 | 26 | Maintenir la cohésion mène à de nombreuses petites classes 27 | nombre réduit de variables d’instance, separer en classes 28 | 29 | ## Organiser en vue du changement 30 | 31 | OCP 32 | ?? creation de hierarchie pour reutilisation du code? 33 | ?? approche tout object, deep hierarchie. ECS ? 34 | 35 | Cloisonner le changement 36 | introduire des interfaces et des classes abstraites pour limiter l’influence de ces détails 37 | DIP 38 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_06.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 6 - Heapsort 3 | 4 | note: tri par tas https://fr.wikipedia.org/wiki/Tri_par_tas 5 | 6 | - O(n.log n), comme merge sort et contrairement a insertion sort. 7 | - tri sur place, comme insertion sort et contrairement a merge sort 8 | 9 | nouvelle technique de conception : utiliser une structure de données (tas) 10 | 11 | ## 6.1 Heaps 12 | 13 | Tas = arbre binaire complet (tout les noeds d'un niveau sont utilisé avant de commencer les noeuds du niveau inferieur) 14 | 15 | - A = tableau 16 | - A.length = taille du tableau 17 | - A.heap-size = taille du tas. 0 <= A.heap-size <= A.length 18 | 19 | Acces aux parent et enfants, pour A[i] : 20 | 21 | - parent = A[i/2] 22 | - enfants = A[2i] et A[2i+1] 23 | 24 | implementation en utilisant les bitshift 25 | 26 | - max-heap : A[parent(i)] >= A[i] ----> heapsort 27 | - min-heap : A[parent(i)] <= A[i] 28 | 29 | height = nombre de niveau avec la racine. 30 | Pour un tas de n elements : height = Theta(log n) 31 | 32 | procédures : 33 | 34 | - MAX-HEAPIFY : O(log n) 35 | - BUILD-MAX-HEAP : linear time 36 | - HEAPSORT : O(n.log n) 37 | 38 | ## 6.2 Maintaining the heap property 39 | 40 | prendre le plus petit des sous noeuds et le descendre. Recusion 41 | 42 | ## 6.3 Building a heap 43 | 44 | applique MAX-HEAPIFY sur chaque noeud qui n'est pas une feuille (neud terminal) 45 | 46 | invariant : chaque noeud i+1, i+2,... est la racine d'un max-heap 47 | initialisation : i=[n/2], [n/2]+1, [n/2]+2,... sont des feuilles et donc des racines de max-heap 48 | maintenance : apres chaque iteration, les noeuds sont triés aussi 49 | termination : n=1, tous les noeuds sont triés 50 | 51 | BUILD-MAX-HEAP : O(n) 52 | 53 | ## 6.4 The heapsort algorithm 54 | 55 | BUILD-MAX-HEAP puis extraire chaque element avec MAX-HEAPIFY 56 | 57 | ## 6.5 Priority queues 58 | 59 | max-priority queue : 60 | 61 | - insert(S,x) 62 | - maximum(S) 63 | - extract-max(S) 64 | increase-kers(S,x,k) 65 | 66 | -------------------------------------------------------------------------------- /03_computer_architecture/00_introduction.md: -------------------------------------------------------------------------------- 1 | 2 | **Séance du 15 juillet 2020** 3 | 4 | Points importants : 5 | 6 | - plusieurs caracteristiques essentielle : temps de reponse, latence, nombre de cores, synchronisation, parallelisme 7 | - pas de meilleure algo et structure de donnees dans l'absolue, cela depend de quelle partie de l'ordi le code est 8 | effectivement executé (un core du CPU, le SIMD du CPU, le GPU, les memoires caches, les registres, le GPU, etc) 9 | - en premiere intention, faire confience au compilo. Puis mesurer. Si on trouve des problemes d'algos et structures de données, 10 | corriger cela et laisser le compilo optimiser ce qu'il peut. Puis mesurer. Et si on trouve encore des optis pertinentes (ie 11 | avec un gain significatif), alors seulement, on peut passer a des optis manuelles 12 | 13 | Chapitres : 14 | 15 | - 01 : les fondamenteux de l'analyse et du design, qu'est-ce que l'on va mesurer (performances, couts, puissance consommée, etc). 16 | - 02 : les hiérarchies de mémoire. Plusieurs types de mémoires, que l'on peut classer en fonction de leur temps d'accès et leur débits. 17 | - 03 : le paralélisme des instructions. Dans un processeur moderne, les instructions prennent du temps à être executée, donc plusieurs 18 | instructions sont executé en même temps (un peu en décalées) pour gagner du temps. 19 | - 04 : le parallélisme des données, pour optimiser lorsqu'on doit réaliser le même calcul plusieurs fois sur des données différentes. 20 | - 05 : le parallélisme des threads. Quand plusieurs cores doivent travailler sur des données partagées, utilisation des mémoires caches. 21 | - 06 : les fermes d'ordinateurs, pour le calcul distribué, le cloud, internet, etc. 22 | - 07 : les architectures spécifiques à un domaine, qui permet de concevoir une architecture optimisées pour réaliser une tâche en particulier, 23 | plutôt que pouvoir réaliser n'importe quelle tâche généraliste. 24 | 25 | Les annexes seront probablement lues en même temps que les chapitres correspondants. Annexes : 26 | 27 | - A : les jeux d'instructions, pour faire l'intermédiaire entre le code que l'on écrit et le matériel. 28 | - B : Vue d'ensemble des hiérarchie de mémoire. 29 | - C : le concept de pipeline. 30 | 31 | Les annexes suivantes ne sont pas dans le livre, mais uniquement en pdf. Vous pouvez les télécharger sur le site de l'éditeur : 32 | https://www.elsevier.com/books-and-journals/book-companion/9780128119051 33 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_09.md: -------------------------------------------------------------------------------- 1 | # Chapitre 9 - Medians and Order Statistics 2 | 3 | - def: statique d'ordre (statistic order) est le i-ème plus petit élément 4 | - def: minimum i=1, max i=n 5 | - def: mediane est le point central, lower median si pair 6 | 7 | probleme : determiner l'ordre i-eme (selection problem) 8 | 9 | - input: ensemble A d'elements distincts, 1 <= i <= n 10 | - output: element x de A, plus large que exactement i-1 autres elements de A 11 | 12 | Approche simple: O(n lg n), en triant l'ensemble, puis en prenant l'element i. 13 | 14 | plan: 15 | - 9.1: selection de min et max 16 | - 9.2: algo en O(n) en temp attendu 17 | - 9.3: algo en O(n) dans le pire des cas 18 | 19 | ## 9.1 - Minimum and maximum 20 | 21 | minimum de comparaison nécessaire = n-1 22 | 23 | algo: 24 | ``` 25 | min = A[1] 26 | pour chaque x de A: 27 | si min > x alors min = x 28 | return x 29 | ``` 30 | 31 | preuve: moins de comparaisons -> au moins 1 element n'est pas testé. Si c'est le mac, alors fails 32 | 33 | ### Simultaneous minimum and maximum 34 | 35 | ex: points 2D, besoin de trouver les limites 36 | 37 | algo: 38 | ``` 39 | 2 comparaison par element 40 | si n impaire -> prendre le premier element pour initialiser min et max. 3*|n/2| comparaisons 41 | si n pair -> faire une premiere comparaison pour determiner min et max. 3*|n-2)/2 comparaisons 42 | ``` 43 | 44 | ## 9.2 - Selection in expected linear time 45 | 46 | temps asymptotique: Theta(n). Par diviser-conquerir, basé sur quicksort 47 | 48 | RANDOMIZED-SELECT sur 1 coté de la partition, ce qui fait passer de Theta(n lg n) à Theta(n). 49 | 50 | ``` 51 | RANDOMIZED-SELECT(A ,p, r, i) 52 | si p==r 53 | return A[p] 54 | q = RANDOMIZED-PARTITION(A ,p, r) 55 | k = q-p+1 56 | si i == k: // pivot est le resultat 57 | A[q] 58 | sinon si i < k: 59 | return RANDOMIZED-SELECT(A ,p, q-1, i) 60 | sinon: 61 | return RANDOMIZED-SELECT(A ,q+1, r, i-k) 62 | ``` 63 | 64 | Worst case: Theta(n^2), puisque partioning prend Theta(n) 65 | 66 | demonstration via esperance statistique pour montrer que le cas moyen est en O(n) 67 | 68 | ## 9.3 Selection in worst-case linear tim 69 | 70 | algo: 71 | ``` 72 | partitionner en groups de 5 elements 73 | trouver la mediane de chaque groupe apres insertion sort 74 | utiliser SELECT pour trouver la mediane 75 | partitionner a partir de la mediane trouvée 76 | si i=k, retourner x. Sinon, utiliser SELECT recursivement 77 | ``` 78 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_11.md: -------------------------------------------------------------------------------- 1 | 2 | > En cours de redaction 3 | 4 | # Chapitre 11 - Systèmes 5 | 6 | ## Construire une ville 7 | 8 | - Certaines de ces personnes sont responsables de la vue d’ensemble, tandis que d’autres se focalisent sur les détails. 9 | - niveaux d’abstraction, modularité, composants 10 | 11 | ## Séparer la construction d’un système de son utilisation 12 | 13 | ``` 14 | public Service getService() { 15 | if (service == null) 16 | service = new MyServiceImpl(...); // Service par défaut suffisant return service; // pour la plupart des cas ? 17 | } 18 | ``` 19 | 20 | - fonction de creation 21 | - La compilation ne peut pas se faire sans résoudre ces dépendances, même si nous n’utilisons jamais un objet 22 | de ce type à l’exécution ! 23 | 24 | ??? est-une mauvaise chose ? Permet de verifier que le code est valide ? 25 | 26 | - Construire dans la fonction main 27 | - Fabriques 28 | - Injection de dépendance 29 | - JNDI, "mais il résout néanmoins activement la dépendance" 30 | - "Les objets dépendants réellement employés sont indiqués par l’intermédiaire d’un fichier de configuration ou par programmation dans un module de construction à usage spécial.". framework Spring. 31 | 32 | ## Grandir 33 | 34 | - agilité itérative et incrémentale 35 | - "Leur architecture peut évoluer de manière incrémentale, si nous maintenons la séparation adéquate des préoccupations." 36 | - bean entité, EJB 37 | 38 | ### Préoccupations transversales 39 | 40 | programmation orientée aspect (AOP, Aspect-Oriented Programming) 41 | 42 | ## Proxies Java 43 | 44 | Le "bon vieil objet Java tout simple" (POJO, Plain Old Java Object) 45 | 46 | ## Frameworks AOP en Java pur 47 | 48 | ## Aspects d’AspectJ 49 | 50 | ## Piloter l’architecture du système par les tests 51 | 52 | BDUF, Big Design Up Front 53 | 54 | ## Optimiser la prise de décision 55 | 56 | ## Utiliser les standards judicieusement, lorsqu’ils apportent une valeur démontrable 57 | 58 | ## Les systèmes ont besoin de langages propres à un domaine 59 | 60 | langages propres à un domaine (DSL, Domain-Specific Language) 61 | 62 | ## Conclusion 63 | 64 | ## Questions 65 | 66 | - ca parle plus de classe que de systemes ? 67 | 68 | https://www.amazon.fr/Large-Scale-Software-Design-John-Lakos/dp/0201633620 69 | 70 | - separation construction/execution 71 | 72 | - aspect ? ancienne methode/nouvelle methode ? 73 | - comment choisir/creer ces abstractions ? Ces modules ? 74 | - JNDI, Spring : fausse independance ? 75 | - faire par defaut ? 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_04.md: -------------------------------------------------------------------------------- 1 | 2 | > En cours de redaction 3 | 4 | # Chapitre 4 - Commentaires 5 | 6 | - qu'est qu'un code propres 7 | - noms significatifs 8 | - fonctions 9 | 10 | Les commentaires sont, au mieux, un mal nécessaire 11 | 12 | bien employés lorsqu’ils pallient notre incapacité à exprimer nos intentions par le code 13 | 14 | les commentaires masquent toujours nos échecs 15 | 16 | ressentez le poids de l’échec. 17 | 18 | ils mentent 19 | 20 | garder des commentaires à jour, pertinents et juste 21 | 22 | La vérité doit se trouver uniquement dans le code 23 | 24 | - Ne pas compenser le mauvais code par des commentaires 25 | 26 | - S’expliquer dans le code 27 | 28 | - Bons commentaires 29 | - - Commentaires légaux 30 | - - Commentaires informatifs 31 | - - Expliquer les intentions, les raisons d’une décision 32 | - - Clarifier 33 | - - Avertir des conséquences 34 | désactiverions le cas de test à l’aide de l’attribut @Ignore et d’une chaîne d’explication appropriée, comme @Ignore("Exécution trop longue"). 35 | - - Commentaires TODO 36 | - - Amplifier 37 | - - Documentation Javadoc dans les API publiques 38 | 39 | - Mauvais commentaires 40 | 41 | béquilles ou d’excuses à du mauvais code 42 | 43 | - - Marmonner 44 | Un commentaire qui nous oblige à consulter d’autres modules pour comprendre sa signification est un commentaire qui ne parvient pas à communique 45 | - - Commentaires redondants 46 | - - Commentaires trompeurs 47 | - - Commentaires obligés 48 | - - Commentaires de journalisation ----------> ca se fait encore ? Git? 49 | - - Commentaires parasites 50 | - - Bruit effrayant 51 | - - Ne pas remplacer une fonction ou une variable par un commentaire 52 | - - Marqueurs de position -------------------> private/public 53 | - - Commentaires d’accolade fermante --------> namespaces 54 | - - Attributions et signatures --------------> ca se fait encore ? Git? 55 | - - Mettre du code en commentaire -----------> WIP :) 56 | - - Commentaires HTML 57 | - - Information non locale 58 | - - Trop d’informations 59 | - - Lien non évident 60 | - - En-têtes de fonctions 61 | - - Documentation Javadoc dans du code non public 62 | 63 | 64 | 65 | 66 | - questions 67 | 68 | - importance du langage dans l'expressivite du code et donc la necessite d'ecrire des commentaires 69 | 70 | - "Ne pas remplacer une fonction ou une variable par un commentaire" -> verbosite vs performances ? JIT/compilation? 71 | 72 | - impact des outils recents sur les pratiques : gestionnaire de sources, doc generateur, outils de verification 73 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_05.md: -------------------------------------------------------------------------------- 1 | 2 | # Mise en forme 3 | 4 | l’élégance, la cohérence et l’attention portée aux détails 5 | 6 | règles simples, les appliquer systématiquement 7 | 8 | ## Objectif de la mise en forme 9 | 10 | important, moyen de communication 11 | 12 | "faire en sorte que cela fonctionne" n'est pas la priorité: fonctionnalités changent, lisibilité du code a un impact sur les modifications, facilité de maintenance et extension du code 13 | 14 | établir un précédent 15 | 16 | ## Mise en forme verticale 17 | 18 | très variables, quelques dizaines de lignes a plusieurs milliers 19 | 20 | taille des fichiers pas forcément en relation avec la taille des projets 21 | 22 | Petits fichiers plus simples à comprendre 23 | 24 | - Métaphore du journal -> du plus haut niveau vers les details 25 | - Espacement vertical des concepts -> ligne vide pour séparer les concepts 26 | - Concentration verticale -> ne pas séparer les mêmes concepts ensemble (commentaires, lignes vides, etc) 27 | - Distance verticale -> regrouper les concepts verticalement, regrouper dans un même fichier si cela a du sens. 28 | Variables protégées a eviter ? 29 | 30 | ## Déclarations de variables 31 | 32 | déclarées au plus près de leur utilisation. 33 | 34 | Rare cas d'exception ? 35 | 36 | ## Variables d’instance 37 | 38 | Java: au début de la classe. C++: a la fin. 39 | 40 | ## Fonctions dépendantes 41 | 42 | proches verticalement, appellant avant appellées 43 | 44 | ## Affinité conceptuelle 45 | 46 | appelant/appelées, fonctions qui réalisent une opération semblable 47 | 48 | ## Rangement vertical 49 | 50 | # Mise en forme horizontale 51 | 52 | 80 caractères arbitraires, mais conserver des lignes pas trop longue (100, voire 120) 53 | 54 | ## Espacement horizontal et densité 55 | 56 | espace dans une ligne 57 | 58 | - operateur d'affectation = 1 espace 59 | - appel de fonction = pas d'espace 60 | - espace apres virgule 61 | - addition et soustraction = espace, multiplication et division = pas d'espace 62 | 63 | ## Alignement horizontal 64 | 65 | auteur préféré non aligné 66 | 67 | ## Indentation 68 | 69 | hiérarchisation 70 | 71 | permet de lire rapidement par blocs de code 72 | 73 | ==> python obligatoire 74 | 75 | ## Rompre l’indentation 76 | 77 | auteur ne préfère pas le code sur une ligne 78 | 79 | ## Portées fictives 80 | 81 | préférer des accolades vides plutot qu'un point virgule seul 82 | 83 | # Règles d’une équipe 84 | 85 | suivre les règles de l'equipe 86 | 87 | rester coherent 88 | 89 | # questions 90 | 91 | - outils de formatage ? clang-format, git hook 92 | 93 | séparer commit mise en forme et changement dans le code ? 94 | 95 | - C++: meme ordre que interface ? 96 | 97 | A qui est destinée la déclaration de la classe ? Au l'utilisateur = mettre dans l'ordre public, protected et private 98 | 99 | Java: pas de separation interface/implementation. Fichier destinée aux utilisateurs et concepteurs de la classe. C++ = separation 100 | 101 | - guides par equipes 102 | 103 | -------------------------------------------------------------------------------- /03_computer_architecture/01_fundamentals_of_quantitative_design_and_analysis.md: -------------------------------------------------------------------------------- 1 | 2 | # 1. Fundamentals of Quantitative Design and Analysis 3 | 4 | Slides : https://www.elsevier.com/__data/assets/powerpoint_doc/0011/559721/CAQA6e_ch1.pptx 5 | 6 | ## 1.1 Introduction 7 | 8 | Amélioration des performances = amélioration des technologies de semi-conducteurs + amélioration des architectures des ordinateurs (RISC) 9 | 10 | Démocratisation des ordinateurs (au sens large : mobiles, serveurs, etc) = ensemble de facteurs : plus de puisssance, baisse des coûts (PC, mobiles), 11 | facilité de fabrication en grande quantité (circuits intégrés, microprocesseurs), langages de programmation haut niveaux (parallèle entre l'augmentation 12 | de puissance, l'évolution des besoins que permet cette évolution de technologie et les moyens de développement pour profiter de cette puissance 13 | et répondre aux besoins). 14 | 15 | Fin de l'amélioration des processeurs uniques vers 2004. Puis amélioration du parallélisme des instructions (ILP, plus de progression maintenant, 16 | implicite contrairement aux autres LP), puis parallélisme des données (DLP) et des threads (TLP), et maintenant paralèllisme des requètes (RLP). 17 | 18 | Diminution de l'augmentation des performances due à loi de Moore (doublement de la puissance tous les 18 mois, n'est plus valide), loi d'Amdahl (limitation performances paralélisme). 19 | 20 | Futur pour améliorer les coûts énergie-performance : domain-specific architecture 21 | 22 | ## 1.2 Classes of computers 23 | 24 | Selon le prix et les points critiques 25 | 26 | - internet of things et embedded computers : prix, énergie, performances spécifique à une application 27 | - personal mobile device (PMD) : coût, énergie, media performance, réactivité 28 | - desktop : prix-performance, énergie, performances graphiques 29 | - serveur : débit, disponibilité, évolutivité, énergie 30 | - clusters/warehouse-scale computers : prix-performances, débit, "energy proportionality" 31 | 32 | **Classes of Parallelism and Parallel Architectures** 33 | 34 | 2 types de parallélisme : 35 | 36 | - Data-level parallelism (DLP) 37 | - Task-level parallelism (TLP) 38 | 39 | - Instruction-level parallelism (DLP) 40 | - Vector architectures, graphic processor units (GPUs), and multimedia instruction sets (DLP) 41 | - Thread-level parallelism (DLP et TLP) 42 | - Request-level parallelism (TLP) 43 | 44 | Classification Flynn (1996) 45 | 46 | - SISD (uniprocessor) 47 | - SIMD (vectorisation, DLP, GPU) 48 | - MISD 49 | - MIMD 50 | 51 | ## 1.3 Defining Computer Architecture 52 | 53 | 1. qu'est-ce qui est important ? 54 | 2. concevoir le design en tenant compte des performances, l'efficacité énergétique, les coûts, etc 55 | 56 | **Instruction set architecture (ISA)** 57 | 58 | examples from 80x86, ARMv8, and RISC-V 59 | 60 | - classes of ISA : register-memory ISA ou load-store ISA 61 | - Memory addressing : accès généralement plus rapide si aligné 62 | - Addressing modes : register, immeditate, displacement 63 | - Types and sizes of operands : 8b, 16b, 32b etc 64 | - Operations : data transfer, arithmetic logical, control (discussed next), and floating point 65 | - Control flow instructions : conditional branches, unconditional jumps, procedure calls, and returns 66 | - Encoding an ISA : fixed length (ARM, RISC-V = 32b) and variable length (80x86) 67 | 68 | **Genuine Computer Architecture** 69 | 70 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_03.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 3 - Growth of Functions 3 | 4 | La question posée par ce chapitre est de déterminer une mesure d'efficacité : comment le temps d'exécution d'un 5 | algorithme va grandir, en fonction de ses paramètres. Cette mesure permet de comparer les performances relatives 6 | entre plusieurs alternatives d'algorithmes. 7 | 8 | Le paramètre principal est la taille des entrées `n`. On s'interesse aux comportements aux limites (analyse asymptotic), 9 | c'est-à-dire pour `n` suffisament grand. 10 | 11 | Les temps d'execution dans le plus mauvais des cases (*worst-case running time*) : 12 | 13 | - pour *merge sort* : `Theta(n lg n)`. 14 | - pour *insertion sort* : `Theta(n^2)` 15 | 16 | ## 3.1 Asymptotic notation 17 | 18 | Ce chapitre présente plusieurs démonstrations de calculs des performances des algorithmes. Reproduire ces 19 | calculs dans le résumé n'est pas pertinent. Si cela vous intéresse, il est préférable de lire ces calculs 20 | directement dans le chapitre. 21 | 22 | ### Asymptotic notation, functions, and running times 23 | 24 | Pour le tri par insertion, le détail des calculs donne des performances qui suivent une forme 25 | polynomiale : 26 | 27 | > a.n^2 + b.n + c 28 | 29 | Le comportement asymptotique suit donc une loi en `Theta(n^2)`. (Les valeurs de `b.n` et `c` sont négligeables devant 30 | `a.n^2` quand `n` est très grand). 31 | 32 | Quel est le temps d'exécution ? 33 | 34 | > Theta(g(n)) = { f(n) } : there exist positive constants c1, c2, and n0 such that 0 35 | 36 | Member d'un ensemble de fonctions = pas une seule fonction f() qui peut etre une borne de g() 37 | 38 | Theta = moyen (il existe c1.g(n) et c2.g(n) inf). asymptotically tight bound 39 | O = meilleur cas (brne inferieure), asymptotic upper bound 40 | omega= plus mauvais cas (borne sup) 41 | 42 | ### Theta notation 43 | 44 | Demonstration que a.n^2 + b.n + c ~ Theta(n^2) 45 | Demontration que 6.n^3 != Theta(n^2) 46 | 47 | Theta(1) = Theta(n^0) = constante 48 | 49 | ### O-notation (grand O, la lettre) 50 | 51 | asymptotic upper bound 52 | 53 | f = Theta(g) => f = O(g) 54 | 55 | peut etre deduit directement de l'analyse du code 56 | Par exemple, 2 boucles imbriqués = O(n^2) 57 | 58 | la limite O(n^2) sur le plus mauvais cas est egalement O(n^2) sur tous les cas. 59 | Mais pas vrai pour Theta. Par exemple, insertion sort si collection est deja triée est Theta(n) 60 | 61 | ### grand omega-notation 62 | 63 | asymptotic lower bound. best-case running time 64 | 65 | > Theorem 3.1 66 | > For any two functions f = Theta si et seulement si f = O et f = Omega 67 | 68 | En general, theoreme utilisé pour determiner Theta a partir de O et Omega 69 | 70 | ## Asymptotic notation in equations and inequalities 71 | 72 | a.n^2 + b.n + c = 2.n^2 + Theta(n) = 2.n^2 + f(n), avec f appatient a Theta 73 | a.n^2 + Theta(n) = Theta(n^2) 74 | 75 | ### o-notation 76 | 77 | Idem O, mais pas Theta 78 | 79 | exemple 2n = o(n^2), but 2.n^2 != o(n^2) 80 | 81 | f/g -> 0 pour n->oo 82 | 83 | ### petit omega-notation 84 | 85 | Idem 86 | 87 | f/g -> 00, quand n->oo 88 | 89 | ### Comparing functions 90 | 91 | - Transitivity 92 | - Reflexivity 93 | - Symmetry 94 | - Transpose symmetry 95 | 96 | Trichotomy 97 | 98 | 99 | # 3.2 Standard notations and common functions 100 | 101 | 102 | 103 | 104 | 105 | # Discussions 106 | 107 | 108 | 109 | - revenir sur le "meilleur cas" "plus mauvais cas" 110 | - asymptoic 111 | - ensemble de fonctions. petit o et petit omega 112 | - faire les demos de a.n^2 + b.n + c ~ Theta(n^2) 113 | 114 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_03.md: -------------------------------------------------------------------------------- 1 | 2 | > En cours de redaction 3 | 4 | # Chapitre 3 - Fonctions 5 | 6 | 7 | 8 | longue, code dupliqué, chaines de caracteres etranges, types de donnees, API, etc = difficile a comprendre 9 | trop d'operations, trop de niveau d'abstraction, plusieurs niveau d'imbrication 10 | 11 | # Faire court 12 | 13 | "et encore plus que ca" 14 | 15 | 25l 80c. 100l, 150c. 16 | 17 | Moins de 20 lignes. 5 lignes 18 | 19 | bloc et indentation : pas plus de 2 niveaux 20 | 21 | # Faire une seule chose 22 | 23 | "UNE FONCTION DOIT FAIRE UNE SEULE CHOSE. ELLE DOIT LA FAIRE BIEN ET NE FAIRE QU’ELLE." 24 | 25 | 1 niveau d'abstraction. Creer un nouvelle fonction ne fait que changer le nom 26 | 27 | Pas de sections 28 | 29 | # Un niveau d’abstraction par fonction 30 | 31 | - fonctions de la classe 32 | - fonctiond d'autres classes 33 | - fonction de la lib standard 34 | 35 | Lire le code de haut en bas : la règle de décroissance 36 | 37 | # Instruction switch 38 | 39 | "nous employons évidemment le polymorphisme" -> langage specifique 40 | 41 | Fabrique abstraite 42 | 43 | # Choisir des noms descriptifs = chapitre 2 44 | 45 | principe de Ward : "Vous savez que vous travaillez avec du code propre lorsque chaque 46 | fonction que vous lisez correspond presque parfaitement à ce que vous attendiez." 47 | 48 | nom long > nom court 49 | 50 | # Arguments d’une fonction 51 | 52 | ideal = 0, 1 ou 2 = ok, plus de 3 = a eviter 53 | 54 | preferer passer une variable comme membre, plutot que comme argument <= purete fonctionnelle ? 55 | 56 | Difficulite pour tester <= encore plus dur de tester un etat interne ? 57 | 58 | prefere retour de fonction plutot que argument de sortie. <= optional, monade, gestion d'erreur 59 | 60 | - Formes unaires classiques : retourner un bool ou un objet. Evenement = specifique a java? 61 | 62 | - Arguments indicateurs : a eviter 63 | 64 | - fonction diadique <= opposition fonction membre ou non, langage specifique 65 | 66 | assertEquals(expected, actual) : ordre des parametres ? <= parametres nommé? 67 | 68 | - Fonctions triadiques : cumul de problemes 69 | 70 | - Objets en argument : concept qui mérite son propre nom 71 | 72 | - Listes d’arguments (string.format) 73 | 74 | - Verbes et mots-clés 75 | 76 | assertExpectedEqualsActual(expected, actual) au lieu de assertEquals(expected, actual) 77 | 78 | # Éviter les effets secondaires 79 | 80 | fait également d’autres choses cachées dans la classe ou dans les membres <= const, passage par valeur, purete fonctionnelle 81 | 82 | couplage temporel 83 | 84 | faire une chose ? 85 | 86 | - Arguments de sortie : utilisation des membres. A proscrire, utiliser this pour la sortie 87 | 88 | # Séparer commandes et demandes 89 | 90 | Une fonction doit modifier l’état d’un objet ou retourner des informations concernant cet objet 91 | 92 | if (set("nomUtilisateur", "OncleBob"))... <= isSet, tester si un objet est valid. etentre le scope. C++17 declaration dans if. Pointeur C/C++ 93 | 94 | if (attributeExists("nomUtilisateur")) { 95 | setAttribute("nomUtilisateur", "OncleBob"); ... 96 | } <= verbosite 97 | 98 | 99 | # Préférer les exceptions au retour de codes d’erreur 100 | 101 | violation subtile de la séparation des commandes et des demande 102 | 103 | - Extraire les blocs try/catch <= séparation élégante ??? 104 | 105 | - Traiter les erreurs est une chose 106 | 107 | - L’aimant à dépendances Error.java. Probleme de dependances 108 | 109 | # Ne vous répétez pas 110 | 111 | DRY, plus de code = plus d'erreurs 112 | 113 | # Programmation structurée 114 | 115 | Dijkstra : chaque fonction, et chaque bloc dans une fonction, doit posséder une entrée et une sortie 116 | 117 | # Écrire les fonctions de la sorte 118 | 119 | 120 | # Questions 121 | 122 | apprendre de l'experience? 123 | 124 | object vs fonctionnel. parametre vs membre. Typage fort 125 | 126 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_07.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 7 - Quicksort 3 | 4 | worst-case running time of Theta(n^2) 5 | 6 | pas le meilleur dans le plus mauvais cas, mais cas moyen en Theta(n lg n) 7 | avec des constantes faibles. Et tri sur place. Et bon avec environment virtuels. 8 | 9 | ## 7.1 Description of quicksort 10 | 11 | approche divide-and-conquer. Pour trier A[p..r] 12 | 13 | - diviser : rearrange en 2 sous tableaux A[p..q-1] et A[q+1..r], avec chaque element: A[p..q-1] <= A[q] <= A[q-1..r] 14 | - conquérir : trier les sous tableau reursivement 15 | - combiner: rien a faire 16 | 17 | Algo: 18 | 19 | QUICKSORT(A,p,r): 20 | if p < r 21 | q = PARTITION(A,p,r) 22 | QUICKSORT(A,p,q-1) 23 | QUICKSORT(A,q+1,r) 24 | 25 | Pour tout trier : QUICKSORT(A,1,A.length) 26 | 27 | ### Partitioning the array 28 | 29 | PARTITION(A,p,r) 30 | x = A[r] 31 | i = p-1 32 | for j = p to r-1 33 | if A[j] <= x 34 | i = i + 1 35 | swap A[i] et A[j] 36 | swap A[i+1] et A[r] 37 | return i+1 38 | 39 | Analyse : 40 | 41 | - x=A[r] comme pivot 42 | - regroupe les elements inferieurs a x dans A[p,i] 43 | - regroupe les elements superieur a x dans A[i+1,j] 44 | 45 | Invariants de boucle : 46 | 47 | 1. si p <= k <= i (sous tableau de gauche), alors A[k] <= x 48 | 2. si i+1 <= k <= j-1 (sous tableau de droite), alors A[k] > x 49 | 3. si k = r (pivot), alors A[k] = x 50 | 51 | Preuve : 52 | 53 | - initialisation : les sous tableaux sont vides, donc les invariants 1 et 2 sont vrais. Et l'initialisation du pivot fait que l'invariant 3 est vrai. 54 | - maintenance : 2 cas, si A[j] est sup ou inf au pivot. 55 | - si A[j] > x, alors j=j+1. Les invariants restent valides. 56 | - si A[j] <= x, alors echange + incremantation de i et j. Invariants encore valides. 57 | - terminaison : a la fin, j=r. 58 | 59 | Running time de PARTITION : Theta(n) 60 | 61 | 62 | ## 7.2 Performance of quicksort 63 | 64 | proche de merge sort si partitionnement équilibré, proche de insertion sort sinon. 65 | 66 | ### Worst-case partitioning 67 | 68 | Pire cas lorsque un des sous tableaux contient 0 elements. (prouvé dans 7.4.1) 69 | 70 | T(n) = T(n-1) + T(0) + Theta(n) 71 | // sous-tableau de taille n-1, puis sous-table de taille 0, puis merge 72 | T(n) = T(n-1) + Theta(n) 73 | T(n) = Theta(n^2) 74 | 75 | Pas meilleur que insertion sort 76 | 77 | ### Best-case partitioning 78 | 79 | Equilibré = 2 sous problème de tailles n/2 et (n/2)-1 80 | 81 | T(n) = 2T(n/2) + Theta(n) 82 | T(n) = Theta(n lg n) 83 | 84 | similaire merge sort 85 | 86 | ### Balanced partitioning 87 | 88 | Meme si mal equilibré, plus proche du meilleur cas que du plus mauvais cas. (Prouvé dans 7.4) 89 | 90 | Par exemple, avec partition 9/10 et 1/10 : 91 | 92 | T(n) = T(9n/10) + T(n/10) + c.n 93 | 94 | - log_10(n) = Theta(lg n) 95 | - log_10/9(n) = Theta(lg n) 96 | 97 | Donc au final : O(n lg n). Et plus generalement pour toute partition de taille constante. 98 | 99 | ### Intuition for the average case 100 | 101 | Alternative entre bons et mauvais parttion fait que cela s'equilibre et pas trop mauvais au final. 102 | 103 | 104 | ## 7.3 A randomized version of quicksort 105 | 106 | En situation reelle, toutes les permutations ne sont pas forcement equivalentes. 107 | 108 | Randomisation des entrées comme dans 5.3 possible. Mais plus simple a analyser : random sampling : choix du pivot aleatoire dans A[p..r] et echange avec A[r] au début. 109 | 110 | RANDOMIZED-PARTITION(A,p,r): 111 | i = RANDOM(p,r) 112 | swap A[r] et A[i] 113 | return PARTITION(a,p,r) 114 | 115 | RANDOMIZED-QUICKSORT(A,p,r): 116 | if p < r 117 | q = RANDOMIZED-PARTITION(A,p,r) 118 | RANDOMIZED-QUICKSORT(A,p,q-1) 119 | RANDOMIZED-QUICKSORT(A,q+1,r) 120 | 121 | ## 7.4 Analysis of quicksort 122 | 123 | ### 7.4.1 Worst-case analysis 124 | 125 | montrer que le cas où la partition est 0 vs n-1 est le pire cas. 126 | 127 | T(n) = max (T(q) + T(n-q-1)) + Theta(n) | pour 0 <= q <= n-1 128 | 129 | On a au pire : T(n) <= c.n^2, puis faire la substitution. 130 | 131 | ### 7.4.2 Expected running time 132 | 133 | 134 | #### Running time and comparisons 135 | 136 | Lemma 7.1 137 | 138 | Let X be the number of comparisons performed in line 4 of PARTITION over the entire execution of QUICKSORT on an n-element array. Then the running time of QUICKSORT is O.n C X/. 139 | 140 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_08_09.md: -------------------------------------------------------------------------------- 1 | # Limites 2 | 3 | Deux types de limites : 4 | - le code tiers que l'on importe 5 | - le code pas encore écrit 6 | 7 | ## Le code tiers. 8 | 9 | - pas nécessairement parfaitement adapté à notre tâche 10 | - n'évolue pas forcément dans le sens que l'on recherche 11 | 12 | Idéalement : enfermer le code tiers derrière une API correspondant à 13 | la tâche que nous souhaitons réaliser. Cela robustifie la conception 14 | aux changements du code tiers. 15 | 16 | Par conséquent, on doit écrire des tests pour le code tiers : 17 | 18 | - pour le prendre en main, 19 | - pour remarquer les moments où il ne fait plus ce que l'on veut. 20 | 21 | ## Le code pas encore écrit. 22 | 23 | Moment où une partie du logiciel n'est pas encore développée. 24 | 25 | Définir l'interface que l'on voudrait de ce code. Il sera généralement 26 | assez aisé de l'adapter le jour où elle sera disponible. 27 | 28 | # Tests unitaires 29 | 30 | Chapitre fortement lié au TDD 31 | 32 | ## Trois lois 33 | 34 | - pas de code de prod avant le test d'échec, 35 | - écrire seulement le test unitaire suffisant pour échouer, 36 | - écrire seulement le code suffisant pour faire réussir le test. 37 | 38 | ## Objectif 39 | 40 | On veut écrire du code qui soit testable parce que l'on a en tête 41 | le test que l'on cherche à valider. Cela évite de ne pas savoir écrire 42 | le test qui correspond à un code que l'on vient d'écrire parce qu'on ne 43 | sait pas comment le tester. 44 | 45 | Cela permet virtuellement une couverture parfaite du code. 46 | 47 | ## Tests propres 48 | 49 | Les tests doivent rester propre pour rester utilisable. Si les tests 50 | sont sales, il finit par être difficile de savoir si un problème est dû 51 | aux tests ou au code. Résultat : les tests deviennent un handicap. 52 | 53 | Avoir des tests implique d'avoir un filin de sûreté : on n'a pas peur 54 | de modifier le code parce qu'on sait que les tests nous donneront des 55 | informations pertinentes en cas de soucis. 56 | 57 | Test propre : 58 | 59 | - LISIBLE, 60 | - doit montrer les intentions (encore), donc ne doit pas être pollué 61 | par des détails inutiles, 62 | - ne répond pas aux mêmes contraintes que le code de prod, notamment 63 | sur le plan des performances 64 | - une assertion par test (format prémisses -> conclusion) 65 | - un seul concept par test (revient à l'absence de pollution) 66 | 67 | ## FIRST 68 | 69 | - Fast : tests rapides, 70 | - Independent : pas de dépendances entre tests pour éviter les 71 | diagnostiques difficiles, 72 | - Repeatable : si le test n'est pas reproductible, il n'est pas très 73 | pertinent 74 | - Self-validating : résultat = échec ou réussite, sinon l'analyse 75 | demande une intervention, 76 | - Timely : tests écrits juste avant le code qui correspondant 77 | 78 | 79 | # Discussion - Limites 80 | 81 | Les codes de tests de prise en main : 82 | 83 | - plutôt expérimenter dans un autre projet, 84 | - besoin dépendant de la taille de la lib, 85 | - si on dépend d'un framework, c'est très difficile : c'est généralement 86 | très intrusif. 87 | 88 | Difficulté à faire évoluer les libs ? 89 | 90 | - Ex : dépendance à .Net 91 | - dépendance à des APIs REST ? 92 | -> la manière de créer l'API à un impact très fortement 93 | -> distinction forte entre celles que l'on maîtrise et les autres 94 | 95 | # Discussion - Tests unitaires 96 | 97 | Philosophie de l'entreprise : investissement dans les tests. 98 | 99 | Conseiller les décideurs : 100 | 101 | - estimer les coûts, 102 | - estimer les conséquences 103 | 104 | Formation technique des décideurs ? 105 | 106 | - parfois difficile de séparer les types de tests entre unitaires, intégration, ... 107 | - problème de fainéantise des développeurs ? 108 | 109 | Outils : 110 | 111 | - design de tests par contrat 112 | - génération automatique dirigée par le code 113 | - génération automatique dirigée par les langages 114 | 115 | TDD : pas si utilisée ? 116 | 117 | Les coûts à long terme doivent être estimés mais c'est parfois difficile. 118 | Les systèmes à longs termes marchent mieux pour les tests et la maintenance ? 119 | On a tendance à tester les cas auxquels on s'attend 120 | 121 | Fuzzer et reproductibilité -> écrire le test qui correspond fuzzing. 122 | Reproductibilité : la concurrence peut vraiment poser des problèmes. 123 | 124 | - parallélisme 125 | - réseaux, base de données (mais peut être moins unitaires) 126 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_04.md: -------------------------------------------------------------------------------- 1 | 2 | # chapitre 4 - Divide-and-Conquer 3 | 4 | exemple : merge sort 5 | 6 | 3 etapes: 7 | - diviser : le probleme en sous problemes plus petit 8 | - conquerir : resoudre le sous probleme, potentiellement en le divisant encore 9 | - combiner : les sous problemes pour resoudre le probleme 10 | 11 | def: "recursive case" = sous probleme qui peut etre divisé 12 | def: "bottoms out" = recursion qui se termine 13 | def: "base case" = sous problemes resolvables 14 | 15 | autres exemples du chapitre : 16 | - maximum-subarray problem : sous tableau contigue avec somme la plus grande 17 | - multiplication de matrices, en Theta(n^3) et Theta(n^2.81) 18 | 19 | ## Recurrences 20 | 21 | def: equation ou inegalité definie en fonction d'entrées plus petites 22 | 23 | Ex: merge sort, plus mauvais cas: 24 | 25 | T(n) = 26 | > Theta(1), si n=1 27 | > 2.T(n/2)+Theta(n), si n>1 28 | 29 | et donc T(n)=Theta(n.log n) 30 | 31 | Algo recursif par forcement avec des sous problemes de tailles equilibrés. Par exemple 1/3 et 2/3. Pas forcement non plus avec des tailles constantes. Par exemple un element de moins a chaque recursion : T(n)=T(n-1)+Theta(n). 32 | 33 | 3 methodes de resolutions de Theta ou O : 34 | - substitution method: remplace un modele math et prouve qu'il est correct 35 | - recursion-tree method: decoupage en arbre 36 | - master method: T(n)=a.T(n/b)+f(n) 37 | 38 | Parfois, on ne determine que le plus mauvais cas, et on utilise une inegalité dans ce cas. T(n)<=2.T(n/2)+Theta(n). Dans ce cas, utilisation de O. Idem pour >= avec Omega. 39 | 40 | ## Technicalities in recurrences 41 | 42 | Mettre de coté certains details techniques. Par exemple, merge sort quand nombre impaire : n/2 n'est pas entier, pas possible de diviser en 2 problemes exactement identiques. 43 | 44 | Conditions limites aussi un probleme. Suppose T(n) constant pour n petit. 45 | 46 | Plus generalement, mettre de coté les arrondis sup, inf et limites. 47 | 48 | # 4.1 The maximum-subarray problem 49 | 50 | example de la bourse. 51 | 52 | - force brute: toutes les solutions. Arrangement (n 2) en Theta(n^2) 53 | - transformation: tableau des changements plutot que tableau des valeurs. = trouver la suite continue non vide avec la plus grande somme. (maximum subarray). A(n-1 2)=Theta(n^2), pas meilleur. 54 | 55 | note: doit contenir des valeurs negatives, sinon le tableau complet est la plus grande somme. 56 | 57 | ## A solution using divide-and-conquer 58 | 59 | Division du tableau en 3 solutions, selon mid 60 | - sous tableau dans [low, mid] 61 | - sous tableau dans [mid, high] 62 | - sous tableau contenant mid 63 | 64 | ### Recherche d'une somme max dans un sous tableau contenant mid: FIND-MAX-CROSSING-SUBARRAY 65 | 66 | - parcourir de mid a low, trouver la somme max 67 | - parcourir de mid a high, trouver la somme max 68 | - retourner somme max = somme max low + somme max height 69 | 70 | Algo en Theta(n) 71 | 72 | ### recherche d'une somme max dans un sous tableau: FIND-MAXIMUM-SUBARRAY 73 | 74 | - 1 element = retourner cet element # conquire 75 | - prendre mid = (low+high)/2 76 | - FIND-MAXIMUM-SUBARRAY(low, mid) # divide 77 | - FIND-MAXIMUM-SUBARRAY(mid+1, high) # divide 78 | - FIND-MAX-CROSSING-SUBARRAY(low, mid, high) # conquire 79 | - retourner le plus élevé des 3 # combine 80 | 81 | ### Analyzing the divide-and-conquer algorithm 82 | 83 | hypothese simplificatrice : n puissance de 2. Donc division donne tout le temps un nombre entier. 84 | 85 | - T(1)=Theta(1) 86 | - Pour chaque sous probleme recursif : T(n/2) 87 | - pour FIND-MAX-CROSSING-SUBARRAY: Theta(n) 88 | - combine: Theta(1) 89 | 90 | Donc: 91 | 92 | T(n) = Theta(1) + 2.T(n/2) + Theta(n) + Theta(1) = 2.T(n/2) + Theta(n) 93 | 94 | Meme solution que merge sort: Theta(n.log n) 95 | 96 | 97 | # 4.2 Strassen’s algorithm for matrix multiplication 98 | 99 | for (i, j, k) 100 | c_i_j = sum_k(a_i_k * b_k_j) 101 | 102 | T(n) = Theta(n^3) 103 | 104 | ## A simple divide-and-conquer algorithm 105 | 106 | hypothese simplificatrice : n puisssance de 2 107 | 108 | SQUARE-MATRIX-MULTIPLY-RECURSIVE(A, B) 109 | - pour n=1, c_1_1 = a_1_1 * b_1_1 110 | - sinon, calculer les produits des sous matrices 111 | 112 | note: ne pas copier pour creer les sous matrices, mais faire du calcul d'indice. = Theta(1). 113 | 114 | - T(1) = Theta(1) 115 | - T(n) = 8.T(n/2) 116 | - combine = Theta(n^2) 117 | 118 | ## Strassen’s method 119 | 120 | Ne calculer que 7 sous matrices par recursion 121 | 122 | - diviser A, B et C en matrices n/2 * n/2 123 | - calculer 10 matrices sommes et produits, Theta(n^2) 124 | - calculer 7 matrices produits 125 | - calculer les matrices C 126 | 127 | 128 | -------------------------------------------------------------------------------- /01_coder_proprement/resume_complet.md: -------------------------------------------------------------------------------- 1 | Coder Proprement de Robert C. Martin 2 | 3 | # A propos de l'auteur 4 | 5 | Robert C. Martin, dît "Oncle Bob", est un ingénieur dans le domaine du logiciel. Il est principalement connu pour ses 6 | contributions à propos de la méthode Agile, de la gestion de projet, des principes SOLID et du développement dirigé 7 | par les tests. 8 | 9 | # Résumé du livre 10 | 11 | Partant du constat que l'on aura toujours besoin de code, car il y aura toujours des exigences à exprimer, on se pose 12 | la question des raisons et du coût du désordre dans un code. La principale cause du désordre est la pression du temps, 13 | qui nous expose au risque de sous-évaluer le coût de la maintenance future lors d'un développement. La remise "à plus 14 | tard" du nettoyage et de la mise en ordre du code entraîne progressivement un ralentissement de la productivité car le 15 | code devient difficile à comprendre et faire évoluer. Ecrire du bon code est donc une question de survie professionelle. 16 | 17 | Par la production d'un bon code, qui soit élégant, simple, efficace, explicite, et testé, on facilite l'évolution des 18 | projets de développement. Les objectifs principaux du livre sont donc de fournir des lignes directrices pour la 19 | rédaction et le formatage de code, une certaine connaissance des structures de données et les bonnes pratiques en 20 | matière de test de code. La finalité étant de pouvoir écrire du bon code, différencier le bon code du mauvais code et 21 | être capable de transformer du mauvais code en bon code. 22 | 23 | Le conseil le plus général fourni par le livre est d'écrire du code qui révèle au mieux ses intentions. Si le code est 24 | imprécis, ou cache ses intentions (avec des noms peu clairs, ou prêtant à confusion), il devient plus difficile de le 25 | comprendre et donc de le corriger ou le faire évoluer. Dans le livre, une vaste part est donc dédiée au bon nommage des 26 | éléments du code, à leur bonne organisation (notamment la concision des fonctions, et des classes, et la définition 27 | claire de leurs objectifs), ainsi qu'à sa bonne présentation (utilisation d'un format qui facilite la lecture). Ces 28 | passages sont aussi bien dédiés à la présentation de bonnes pratique qu'à l'identification des mauvaises et de moyen de 29 | les corriger. 30 | 31 | Une vaste part de ce livre est dédiée aux tests de programmes. Les tests sont aussi important que le code de production, 32 | car des tests désordonnés deviennent progressivement inutiles voir handicapant. L'auteur présente l'approche dirigée 33 | par les tests que l'on pourrait résumer à l'idée que les tests unitaires des fonctions d'un programme devrait 34 | systématiquement être écrits avant les dites fonctions, afin que celles-ci soit rédigées avec une idée claire du besoin 35 | à remplir, et avec l'optique de réussir le passage des tests. 36 | 37 | Le livre aborde également certains principes SOLID, mais aussi la distinction entre objet et structure de données (et 38 | notamment leur anti-symétrie), ainsi que la loi de Démeter ou les question de liées au code concurrent. 39 | 40 | # Synthèse des commentaires des intervenants 41 | 42 | Dans l'ensemble, la lecture de "Coder Proprement" serait bénéfique à n'importe quel développeur débutant ou 43 | intermédiaire. L'organisation globale du livre est bonne et l'on y voit bien où l'auteur veut nous emmener. Les règles 44 | exposées sont claires, pertinentes et cohérentes avec l'objectif. On note d'ailleurs que certaines pratiques qui 45 | n'étaient pas encore répandues à la sortie de ce livre sont aujourd'hui fortement rentrées dans les usages (par exemple 46 | sur le bon usage des commentaires). 47 | 48 | Le livre est plutôt porté sur l'approche objet et n'expose donc pas ce qui est généralement fait pour les approches 49 | procédurale ou fonctionnelle, pour ne citer que celles-ci. Cela impacte une partie du livre, typiquement lorsque l'on 50 | parle de classe (qui n'existent même pas dans tous les langages objets) ou de gestion des erreurs à base d'exception 51 | (qui ne sont pas forcément utilisées hors de l'objet). Par ailleurs, certaines parties du livre sont pour ainsi dire 52 | complètement concentrées sur Java, la rendant beaucoup moins utiles si vous êtes adaptes d'un autre langage, il 53 | convient alors de se renseigner sur des outils équivalents. Même en ce qui concerne les outils Java, le livre commence 54 | malgré tout à accuser son âge, présentant des technologies qui ne sont plus utilisées, ou utilisées d'une manière très 55 | différente. 56 | 57 | En conclusion, même si le livre commence à accuser son âge et reste très "Java-centré", l'apport pour un programmeur 58 | débutant est indéniable sur les notions de base. Pour les notions plus avancées, il convient de prendre les idées avec 59 | des pincettes et de se renseigner plus sur les techniques employées dans la communauté du langage que l'on utilise. 60 | 61 | Note globale : 3.5/5 62 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_01.md: -------------------------------------------------------------------------------- 1 | 2 | # Préface 3 | 4 | Chaque chapitre presente un algorithme, une technique de conception, 5 | un domaine d'application, ou un un sujet connexe. 6 | 7 | Des solutions aux exercices sont en ligne : 8 | http://mitpress.mit.edu/algorithms/ 9 | 10 | # Introduction 11 | 12 | Résumé des chapitres de la première partie : 13 | 14 | - chapitre 1 : vue d'ensemble et definition de ce qu'est une 15 | algorithme. Quelques exemples, quelques domaines. 16 | - chapitre 2 : premiers algorithmes, sur le tri d'une séquence de n nombres : 17 | les tri par insertion (*insertion sort*) et tri fusion (*merge 18 | sort*), et la technique "Diviser pour régner" 19 | (*divide-and-conquer*). 20 | - chapitre 3 : chapitre sur la complexité : comparaisons asymptotiques de fonctions 21 | - chapitre 4 : Présentation d'un principe général algorithmique : diviser pour mieux régner 22 | - chapitre 5 : introduction à l'analyse probabiliste et aux algorithmes 23 | aléatoires. 24 | - annexes A à D : compléments mathématiques. 25 | 26 | # Chapitre 1 - The Role of Algorithms in Computing. 27 | 28 | ## Généralités 29 | 30 | Definition : procédure de calcul qui reçoit en entrée des valeurs et produit en 31 | sortie des valeurs. Suite d'opérations qui transforme les entrées en 32 | sorties. 33 | 34 | À l'heure actuelle, il n'y a pas de consensus sur la 35 | définition *formelle* de ce qu'est un algorithme. Ce qu'on apelle 36 | *opération* dépend du contexte : on considère très souvent que 37 | l'addition est primitive alors que ce n'est pas forcément le cas pour 38 | les processeurs qui éxécutent l'algorithme. 39 | 40 | Outils pour résoudre des problèmes calculatoires, défini en termes 41 | généraux. Contrairement aux algorithme, le problème peut être 42 | formellement défini. Exemple : calculer la moyenne de n entiers par 43 | exemple. 44 | 45 | Algorithme correct : étant donné un problème, un algorithme est 46 | correct vis-à-vis de ce problème si pour toute instance d'entrée, il 47 | calcule la sortie attendue. Les algorithmes incorrects ne sont pas 48 | nécessairement inutiles si le taux d'erreur est contrôlé par exemple. 49 | 50 | Lorsque le problème est un problème d'optimisation (on chercher à 51 | maximiser ou à minimiser une certaine valeure), les algorithmes ont 52 | souvent beaucoup de solution candidates, trouver la meilleure solution 53 | est très souvent difficile. Les algorithmes généralement ont des 54 | applications pratiques. 55 | 56 | Le livre présente quelques structures de données. Il présente 57 | également des techniques d'approximation pour des problèmes où il 58 | n'existe pas de solution exacte ou bien que la solution exacte est 59 | trop longue à calculer en pratique. Il présente également quelques 60 | problèmes NP-difficiles. 61 | 62 | ## Les algorithmes en tant que technologie 63 | 64 | Même avec des machines infiniment rapides, on aurait quand même besoin 65 | d'étudier l'algorithmique, rien que pour montrer qu'un algo fonctionne 66 | (termine, et avec la bonne solution). 67 | 68 | Efficacité : pour un problème donné, un algorithme pourra être très 69 | rapide alors qu'un autre sera beaucoup plus lent. On utilise la notion 70 | de complexité, pour *prédire* le comportement de l'algorithme. Cette 71 | complexité dépend d'un paramètre (ou parfois plusieurs 72 | paramètres). Très souvent, ce paramètre sera la *taille* de l'entrée, 73 | par exemple pour un algorithme qui trie un tableau de nombre, le 74 | paramètre pourra être la taille du tableau. 75 | 76 | Les algorithmes et les autres technologies : choisir et réaliser des 77 | algorithmes efficaces est aussi important que le choix du hardware par 78 | exemple. De toute façon, même le hardware nécessite des algorithmes. 79 | 80 | # Discussions 81 | 82 | Qu'attendez vous de ce livre ? De ce type de livre ? D'un livre en 83 | general ? 84 | 85 | ## NP-difficile vs NP-complet : 86 | 87 | En théorie de la complexité, un problème NP-complet est un problème de 88 | décision, c'est à dire dont la réponse peut-être *oui* ou *non* 89 | vérifiant les propriétés suivantes : 90 | 91 | - Il est possible de vérifier une solution efficacement (en temps 92 | polynomial) ; la classe des problèmes vérifiant cette propriété est 93 | notée NP ; 94 | - Tous les problèmes de la classe NP se ramènent à celui-ci via une 95 | réduction polynomiale ; cela signifie que le problème est au moins 96 | aussi difficile que tous les autres problèmes de la classe NP. 97 | 98 | Un problème NP-difficile est un problème qui remplit la seconde 99 | condition, et donc peut être dans une classe de problème plus large et 100 | donc plus difficile que la classe NP. 101 | 102 | Exemple de problème NP : étant donné un graphe, est-il possible de 103 | parcourir tous les noeuds du graphes sans passer deux fois par le même 104 | noeud ? Ce problème est aussi connu sous le nom de *chemin 105 | hamiltonien*. 106 | 107 | ## Complexité 108 | 109 | - Quid des performances -> bien comprendre que complexité et 110 | performances sont des notions différentes (théorie vs pratique), 111 | - Importance de la complexité en espace. 112 | - voir les coûts en consommation d'énergie. 113 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_05.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 5 - Probabilistic Analysis and Randomized Algorithms 3 | 4 | ## The hiring problem 5 | 6 | On doit recruter un employé. L'agence envoie chaque jour un employé, on paie 7 | l'agence, et si on recrute : on paie plus cher. Pour avoir toujours le meilleur 8 | on recrute toujours la personne si elle est plus compétente que le précédent 9 | employé. 10 | 11 | La question est "combien ça va coûter à peu près ?". 12 | 13 | L'algo est simple : avec une entrée en nombre de jour. Chaque jour on regarde 14 | si l'employé est meilleur et on l'embauche si c'est le cas. 15 | 16 | Ce qui change par rapport aux autres chapitre et ce que l'on détermine comme 17 | étant le coût qui nous intéresse : ici ce n'est pas le temps d'exécution mais 18 | l'argent dépensé. 19 | 20 | La technique est cependant semblable, on regarde combien de fois un certain 21 | coût est cumulé. Avec ci le coût d'interview et ch le coût de recrutement, et n 22 | le nombre de jour et m le nombre de recrutement, on a : 23 | 24 | O(ci * n + ch * m). 25 | 26 | ### Pire cas 27 | 28 | On recrute à chaque fois: O(ch * n). 29 | Sauf que le candidat n'est pas toujours meilleur 30 | 31 | ### Analyse probabiliste 32 | 33 | Idée: faire l'analyse par la connaissance de la distribution de l'entrée (ou en 34 | faisant des suppositions son propos). Il faut noter que c'est un cas moyen et 35 | pas un pire cas (qui n'est pas probabiliste en soi). 36 | 37 | Naturellement, la loi de probabilité doit être choisie avec attention sinon 38 | l'analyse risque d'être complètement faussée. 39 | 40 | Ici, on peut considérer qu'il est possible de trouver un ordre total sur la 41 | qualité des employés et qu'une entrée est une permutation de cet ordre. Ici, 42 | on a une permutation aléatoire et uniforme. 43 | 44 | ### Algorithmes randomisés 45 | 46 | Pour pouvoir utiliser une analyse probabiliste, on a souvent besoin de connaître 47 | quelque chose à propos de la distribution des entrées, ce qui n'est pas toujours 48 | le cas. Dans ce cas, on peut se contenter de "forcer" la distribution à 49 | respecter cette proposition : en mélangeant par exemple. 50 | 51 | ## Indicator random variables 52 | 53 | Variable utilisée pour passer des probabilités aux effets attendus sur l'entrée. 54 | Par exemple, on peut avoir: 55 | Xf la variable nous indiquant "le nombre" de "face" lors d'un lancement de 56 | pièce. Que l'on définit par : 57 | 58 | Xf = I{Face} 59 | Xf = | 1 si c'est face 60 | | 0 si c'est pile 61 | 62 | On peut ainsi calculer l'espérance du lancer : 63 | 64 | E[Xf] = E[I{Face}] 65 | = 1 * Pr{Face} + 0 * Pr{Pile} 66 | = 1/2 67 | 68 | Lemme important: Xa = I{a} => E[Xa] = Pr{a} 69 | Preuve simple par généralisation de l'exemple au dessus. 70 | (Les références à l'annexe C pourrissent un peu la vie) 71 | 72 | ## Example with the hiring problem 73 | 74 | Avec X le nombre de fois où l'on recrute. 75 | 76 | E[X] = Sum(1, n, x * Pr{X = x}) 77 | 78 | Mais calculer ça, c'est pas pratique. Alors on utilise une indicator random 79 | variable. 80 | 81 | Xi = I{candidat i recruté} 82 | = | 1 si i est recruté 83 | | 0 sinon 84 | 85 | Et X = X1 + X2 + ... + Xn 86 | 87 | Par le lemme, on a : 88 | 89 | E[Xi] = Pr{candidat i recruté} 90 | 91 | Et on doit regardé la probabilité de recrutement. Le candidat i est recruté 92 | quand il est meilleur que tous les candidats 0 à i-1. Qui ont tous les mêmes 93 | probabilité d'être les meilleurs. Le candidat i a une chance sur i d'être 94 | meilleur. 95 | 96 | E[Xi] = 1/i 97 | 98 | E[X] = E[ Sum(i: 1, n, Xi) ] 99 | = Sum(i: 1, n, E[Xi]) 100 | = Sum(i: 1, n, 1/i) 101 | = ln(n) + O(1) (voir l'annexe A) 102 | 103 | Ce qui veut dire que même si l'on interviewe tout le monde, on en recrute 104 | ln n en moyenne. 105 | 106 | (Et en multipliant par le coût de recrutement, on arrive au coût global). 107 | 108 | ## Algorithmes randomisés 109 | 110 | Idée : forcer l'entrée à avoir la forme voulue d'un point de vue proba. 111 | Par exemple pour l'algorithme de recrutement : on mélange les arrivants. 112 | Et montrer que la complexité est O(ch ln n) est facile : on a créé la 113 | condition correcte sur l'entrée. 114 | 115 | ### Permutation aléatoire de tableau 116 | 117 | #### Permutation par le tri 118 | 119 | On crée aléatoirement des priorités pour chaque valeur et on trie le tableau 120 | d'origine en prenant comme clés les valeurs du tableau de priorités. 121 | (Donc en temps O(n log n)). 122 | 123 | Ensuite, on prouve la propriété importante que le résultat a une probabilité 124 | de 1/n!. L'intuition est que la probabilité pour un élément d'être à la case 125 | 1 est de 1/n, et son suivant 1/(n-1) -> ... 1/1 soit 1/n!. 126 | 127 | Note: montrer que la probabilité pour chaque case est de 1/n est insuffisant. 128 | 129 | #### Permutation en place 130 | 131 | Pour i de 1 à n swap A[i] avec une case entre i et la fin. 132 | 133 | Pour prouver l'algo, on prouve un invariant montrant que le début du tableau 134 | (jusqu'à i) est une (i-1)-permutation du tableau, et qu'en instanciant i à n 135 | (fin de l'exécution), on arrive à une proba 1/n! 136 | 137 | ## Analyse probabiliste et autres usages des indicator random variables 138 | 139 | ### The birthday paradox 140 | 141 | Combien de personne dans une pièce pour avoir 50% de chance d'avoir un 142 | anniversaire commun ? 143 | Résultat assez connu, l'idée est qu'il faut se pencher sur les chances que les 144 | autres n'aient pas le même anniversaire que soi. 145 | 146 | # Annexe C 147 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_13_bis.md: -------------------------------------------------------------------------------- 1 | 2 | # Annexe A - Concurrence II 3 | 4 | ## Exemple client/serveur 5 | 6 | On note que la question immédiate est de savoir si la raison de la lenteur est la vitesse de calcul ou les entrées sorties (dans le premier cas, on est plus rapidement limité en accélération). 7 | 8 | equilibre usage CPU et reseau 9 | 10 | En revanche, si le traitement est limité par les entrées/sorties, la concurrence peut améliorer l’efficacité. 11 | Pendant qu’une partie du système attend que les entrées/sorties soient disponibles, une autre partie peut en 12 | profiter pour effectuer une autre opération et ainsi employer plus efficacement le processeur. ??? 13 | 14 | Le premier choix est de lancer un thread par client, le choix est discutable parce que cela peut lancer beaucoup de threads, mais surtout parce que l'on a pas de contrôle sur le scheduling et parce que la classe a un gros paquet de responsabilité. 15 | 16 | On montre ensuite comment séparer la partie scheduling dans une classe dédiée à laquelle on poste les demandes de connexions, il est ensuite facile de changer le scheduler. 17 | 18 | Ajouter des threads 19 | Observations concernant le serveur 20 | 21 | - gestion de la connexion par socket ; 22 | - traitement du client ; 23 | - stratégie de gestion des threads ; 24 | - stratégie d’arrêt du serveur. 25 | 26 | le code traverse allègrement plusieurs niveaux d’abstraction différents > ???? 27 | la gestion des threads doit se trouver en quelques endroits parfaitement maîtrisés > ??? 28 | 29 | A faire a priori ??? 30 | 31 | ## Chemins d’exécution possibles 32 | 33 | Le bytecode généré par le programme en question est surprenant. Il y a beaucoup d'instructions, et certaines paraissent moyennement raisonnables. On a ensuite la présentation du calcul du nombre de chemin qui revient simplement à déterminer le nombre de permutations. 34 | 35 | n = (NT)! / N!^T 36 | 37 | ## Résultat surprenant : deux threads ==> augmentation de 1 seulement. 38 | 39 | Ce problème est simplement dû au fait que les lectures et écritures ne sont pas atomiques et donc on peut avoir deux threads qui lisent la même valeur et font leur écriture avec la même valeur à nouveau (car même incrément). 40 | 41 | [NOTE]: En réalité la situation peut être bien pire, le langage Java, comme les autres langages un peu raisonnables, autorise les comportements faibles. 42 | 43 | # Connaître sa bibliothèque. 44 | 45 | [PAS DANS LE LIVRE] 46 | ## New-IO 47 | 48 | Regarder de plus près. 49 | Basé sur une technique de polling, permet de s'affranchir des threads lorsque l'on fait des IOs. 50 | [FIN] 51 | 52 | ## Executor 53 | 54 | Présentation succincte du framework Executor qui permet de poster un certain nombre de tâches à réaliser dans un pool. Il décharge ensuite les tâches postées (notamment en permettant d'implémenter la notion de futures). 55 | 56 | ## Non blocking atomic operation 57 | 58 | Présentation des opérations comme compare_and_swap ou fetch_and_add qui permettent de réaliser un certain nombre d'opérations atomiques. On peut se référer à compare and swap qui est basiquement : si la variable que je veux set à la valeur recherché, écrire atomiquement la valeur voulue, sinon renvoyer la valeur trouvée. 59 | 60 | ## Présentation ultra-succintes de quelques collections sûres 61 | 62 | Lorsque l'on a besoin d'utiliser des éléments non-sûrs, 63 | 64 | - on peut synchroniser côté client, 65 | [Note]: ce qui est généralement une bombe à retardement 66 | - faire une classe wrapper 67 | - utiliser une classe safe équivalente 68 | [pas dans le livre] - Possibilité de créer un objet synchronisé à partir d'un objet pas synchronisé. 69 | 70 | # Impact des dépendances entre méthodes. 71 | 72 | Présentation d'un exemple où de multiples appels provoquent des interférences principalement dus au fait que l'on peut reposer sur une connaissance qui est rapidement invalide. 73 | 74 | [Note]: C'est l'invariant de la classe qui ne tient pas trop la route. On ne peut pas reposer sur le fait que la connaissance est toujours valide. 75 | 76 | - Tolérer la panne 77 | 78 | Technique de sagouin. 79 | 80 | - Verrouillage côté client 81 | 82 | On présente l'opération a possibilité d'échec qui devrait en fait être encapsulée. 83 | 84 | - Verrouillage côté serveur 85 | 86 | On introduit la possibilité d'échouer pour l'opération next. Ici, c'est réalisé à travers un adapteur, qui peut être une bonne manière de transformer un objet non-safe en objet safe. 87 | 88 | # Augmenter le débit 89 | 90 | Présente simplement une manière d'estimer les gains en multi-thread, mais la technique n'est pas très réaliste. Dans l'idée : on calcule le chevauchement maximum que l'on peut avoir entre IO et calcul et on obtient un temps minimum. 91 | 92 | # Interblocage 93 | 94 | Condition d'un interblocage : 95 | 96 | - exclusion mutuelle : même ressources (en quantité limitée) pour différents threads qui ne peuvent pas être utilisées en même temps, 97 | - détention et attente : on obtient une ressource et on en attend d'autre sans libérer, 98 | - pas de préemption : on ne peut pas piquer une ressource à un thread, 99 | - attente circulaire : T1 a pris R1 et veut R2, T2 a pris R2 et veut R1. 100 | 101 | ## Briser l'exclusion mutuelles 102 | 103 | - ressource simultannées, 104 | - augmenter le nombre de ressources, 105 | - vérifier que tout est libre avant de prendre. 106 | 107 | ## Briser la détention et l'attente 108 | 109 | On peut refuser l'attente, mais on a alors risque de famine ou livelock. 110 | 111 | ## Briser la préemption 112 | 113 | Système de requête pour demander les ressources occupées. On a quasiment les mêmes risques pour avant. 114 | 115 | ## Briser la circularité 116 | 117 | On évite l'interblocage par la mise en place de stratégie qui cassent les cycles. Par exemple en prenant toujours les ressources dans le même ordre. 118 | 119 | # Tester du code MT 120 | 121 | BOF, beaucoup d'aberrations. 122 | 123 | Framework de test permettant de simuler le scheduling. 124 | 125 | https://deadlockempire.github.io/ 126 | 127 | What about Pony ? 128 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_13.md: -------------------------------------------------------------------------------- 1 | 2 | > En cours de redaction 3 | 4 | # Chapitre 13 - Concurrence 5 | 6 | Idée de la concurrence : Stratégie de découplage entre les actions réalisées et le moment où elles sont réalisées. Le fait d'avoir plusieurs piles sémantiques (plusieurs "programmes") avec une part de mémoire partagée permet d'effectuer des tâches différentes potentiellement en même temps. On peut avoir des systèmes ou plusieurs programmes coopèrent à résoudre une tâche plus globale. On peut gagner en organisation ou encore en performances. 7 | 8 | "Il est difficile, même très difficile, d’écrire des programmes concurrents propres." 9 | 10 | "en apparence, semble parfait, mais qui soit défectueux à un niveau plus profond." 11 | 12 | ## Raisons de la concurrence 13 | 14 | - lien fort entre quoi et comment 15 | 16 | ### Mythes et idées fausses 17 | 18 | Faux : 19 | 20 | - La concurrence améliore toujours les performances. 21 | - L’écriture de programmes concurrents n’a pas d’impact sur la conception. 22 | - La compréhension des problèmes liés à la concurrence n’est pas importante lorsqu’on travaille 23 | avec un conteneur comme un conteneur web ou EJB. 24 | 25 | Vrai : 26 | 27 | - La concurrence implique un certain surcoût 28 | - Une bonne mise en œuvre de la concurrence est complexe 29 | - Les bogues de concurrence ne sont généralement pas reproductibles 30 | - La concurrence implique souvent un changement fondamental dans la stratégie de conception. 31 | 32 | ## Se prémunir des problèmes de concurrence 33 | 34 | ### Principe de responsabilité unique 35 | 36 | - Le code lié à la concurrence possède son propre cycle de développement 37 | - Le code lié à la concurrence présente ses propres défis 38 | - Les causes de dysfonctionnement du code concurrent mal écrit suffisent amplement à compliquer son écriture 39 | 40 | ### Corollaire : limiter la portée des données 41 | 42 | Avoir un maximum de localité pour les données évite d'augmenter la quantité de code susceptible de créer des problèmes de concurrence. Les données accessibles à un thread ne doivent être (logiquement) accessibles par personne excepté le thread, sauf pour les structures de données concurrentes qui doivent renforcer une telle encapsulation. 43 | 44 | utiliser le mot-clé synchronized pour protéger une section critique du code qui utilise l’objet partagé 45 | 46 | risques : 47 | 48 | - Vous oublierez de protéger un ou plusieurs de ces endroits 49 | - Vous devrez redoubler d’efforts pour vous assurer que toutes les protections sont bien en place 50 | - Il sera difficile de déterminer les sources de dysfonctionnements 51 | 52 | ### Corollaire : utiliser des copies des données 53 | 54 | A l'entrée des structures concurrentes, forcer la copie permet d'empêcher un thread externe de créer un partage non voulu. 55 | 56 | - copies + map-reduce 57 | 58 | ### Corollaire : les threads doivent être aussi indépendants que possible 59 | 60 | ## Connaître la bibliothèque 61 | 62 | ### Collections sûres vis-à-vis des threads 63 | 64 | Concurrent Programming in Java [Lea99] et "java.util.concurrent" 65 | 66 | autres : ReentrantLock, Semaphore, CountDownLatch 67 | 68 | ## Connaître les modèles d’exécution 69 | 70 | - Ressources bornées 71 | - Exclusion mutuelle 72 | - famine 73 | - Interblocage (deadlock) 74 | - Interblocage actif (livelock) 75 | 76 | ### Producteur-consommateur 77 | 78 | https://fr.wikipedia.org/wiki/Probl%C3%A8me_des_producteurs_et_des_consommateurs 79 | 80 | ### Lecteurs-rédacteurs 81 | 82 | https://fr.wikipedia.org/wiki/Probl%C3%A8me_des_lecteurs_et_des_r%C3%A9dacteurs 83 | 84 | ### Dîner des philosophes 85 | 86 | https://fr.wikipedia.org/wiki/D%C3%AEner_des_philosophes 87 | 88 | ## Attention aux dépendances entre des méthodes synchronisées 89 | 90 | Recommandation : évitez d’utiliser plusieurs méthodes sur un objet partagé. 91 | 92 | - Verrouillage basé sur le client 93 | - Verrouillage basé sur le serveur 94 | - Serveur adapté 95 | 96 | ## Garder des sections synchronisées courtes 97 | 98 | Recommandation : conservez des sections synchronisées les plus courtes possible. Cela permet entre autre d'avoir un code concurrent plus simple (car moins long à lire et comprendre) mais surtout d'éviter de bloquer tout le monde pendant trop longtemps ce qui ruine les performances. 99 | 100 | ## Écrire du code d’arrêt est difficile 101 | 102 | Il existe un risque important qu'un thread soit en attente de quelque chose et qu'il ne reçoive jamais le signale d'arrêt. 103 | 104 | ## Tester du code multithread 105 | 106 | Il est peu réaliste de vouloir prouver que du code est correct. # Kass'peuk 107 | 108 | - Considérer les faux dysfonctionnements comme des problèmes potentiellement liés au multithread 109 | - Commencer par rendre le code normal opérationnel 110 | - Faire en sorte que le code multithread soit enfichable 111 | - Faire en sorte que le code multithread soit réglable 112 | - Exécuter le code avec plus de threads que de processeurs 113 | - Exécuter le code sur différentes plates-formes 114 | - Instrumenter le code pour essayer et forcer des échecs, manuel et/ou automatique 115 | 116 | ## Questions 117 | 118 | - lire l'annexe A lundi prochain ? 119 | - alternative a la programmation concurrente ? events, agents, atomic, signaux-slots, etc. 120 | - plus generalement, structures et algos concurrents ? 121 | - concurrence et conception, methodes pour eviter d'avoir a tout repenser ? Framework de concurrence 122 | - copies de donnees : prog fonctionnelle, données non mutable 123 | - depuis Java 5 ? Autres langages 124 | - modèle memoire et concurrence 125 | - tester du code multithread : mais si pas reproductible, a quoi ca sert ? Quoi faire ? Prioritaire ? 126 | - enseignement de la programmation concurrente 127 | - http://diy.inria.fr/herd/herding-cats-bw.pdf 128 | - http://ceur-ws.org/Vol-1639/paper-04.pdf 129 | - https://en.wikipedia.org/wiki/Bulk_synchronous_parallel 130 | - https://rephrase-eu.weebly.com/ 131 | 132 | ![Java vs C++](http://img.ibxk.com.br/ns/rexposta/2015/03/07/07115101647000.gif) 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | *Rejoindre le [discord NaN](https://discordapp.com/invite/zcWp9sC)* 3 | 4 | # Club de lecture du discord NaN 5 | 6 | Bonjour à tous. 7 | 8 | Tout développeur le sait : il est parfois difficile d'avancer dans ses lectures lorsqu'on cherche à 9 | apprendre de nouvelles notions. Il peut être également difficile de bien choisir la ressource 10 | qui traite de ces notions. De plus, nous n'avons, pendant la lecture, que notre point de vue et celui 11 | de l'auteur (ou du moins ce que l'on en comprend) pour juger de la pertinence des informations qu'on lit. 12 | 13 | C'est pourquoi des membres de la communauté Nan proposent de se réunir à intervalles réguliers pour discuter 14 | d'un livre, sur le discord [Groupe #NaN](https://discordapp.com/invite/zcWp9sC) dans les canaux 15 | "Club de lecture" et "Vocal". 16 | 17 | Les objectifs sont les suivants : 18 | 19 | - avoir un groupe pour se motiver mutuellement à avancer dans la lecture ; 20 | - avoir des points de vue différents, d'autres habitudes, d'autres langages ; 21 | - produire des commentaires pertinents à propos de diverses ressources. 22 | 23 | Pour rester ouvert à un maximum de personnes différentes (autant d'un point de vue du langage que du niveau), 24 | le livre choisi devra : 25 | 26 | - parler d'un thème de l'informatique au sens large (y compris conception, gestion de projet, etc), indépendant 27 | d'un langage (même si l'illustration par un langage particulier convient) ; 28 | - posséder un intérêt pour des développeurs de tout niveau (le but est d'avoir matière à débattre y compris pour 29 | des débutants, pas de faire du question-réponse) ; 30 | - être dispo quelque part en PDF. 31 | 32 | Le livre est choisi par tout ceux qui le souhaitent, en deux temps : 33 | 34 | - on propose des livres qui semblent intéressant à lire ; 35 | - on discute et on vote pour choisir le livre. 36 | 37 | Le club de lecture se réunit un mercredi toutes les 2 semaines, de 20h à 21h30, sur le discord. Vous pouvez simplement 38 | être présent pour écouter les conversations, ou intervenir à l'écrit sur le canal Club de lecture ou à l'oral 39 | sur le vocal. 40 | 41 | Chaque séance aborde un chapitre du livre. Au début de la séance, un volontaire fait un résumé du chapitre 42 | pendant 15 à 20 minutes, puis nous discutons de ce chapitre. En fin de séance, les notes prises sont publiées 43 | sur le [GitHub](https://github.com/GuillaumeBelz/club-lecture). 44 | 45 | ## Coder proprement, de Robert C. Martin 46 | 47 | Le premier livre choisi était ["Coder proprement", de Robert C. Martin](01_coder_proprement/README.md). 48 | 49 | [Résumé complet du livre et commentaire global](01_coder_proprement/resume_complet.md) 50 | 51 | Voici les résumés des chapitres et des discussions : 52 | 53 | - [Chapitre 1 - Code propre](01_coder_proprement/chapitre_01.md). Séance du 16 octobre 2017. 54 | - [Chapitre 2 - Noms significatifs](01_coder_proprement/chapitre_02.md). Séance du 30 octobre 2017. 55 | - [Chapitre 3 - Fonctions](01_coder_proprement/chapitre_03.md). Séance du 6 novembre 2017. 56 | - [Chapitre 4 - Commentaires](01_coder_proprement/chapitre_04.md). Séance du 13 novembre 2017. 57 | - [Chapitre 5 - Mise en forme](01_coder_proprement/chapitre_05.md). Séance du 28 novembre 2017. 58 | - [Chapitres 6 et 7 - Objets et structures de données et Gestion des erreurs](01_coder_proprement/chapitre_06_07.md). Séance du 4 décembre 2017. 59 | - [Chapitres 8 et 9 - Limites et Tests unitaires](01_coder_proprement/chapitre_08_09.md). Séance du 8 janvier 2018. 60 | - [Chapitre 10 - Les classes](01_coder_proprement/chapitre_10.md). Séance du 15 janvier 2018. 61 | - [Chapitre 11 - Systèmes](01_coder_proprement/chapitre_11.md). Séance du 22 janvier 2018. 62 | - [Chapitre 13 - Concurrence](01_coder_proprement/chapitre_13.md). Séance du 29 janvier 2018. 63 | - [Annexe A - Concurrence](01_coder_proprement/chapitre_13_bis.md). Séance du 5 février 2018. 64 | 65 | ## Introduction to Algorithms - 3rd Edition, de T. Cormen 66 | 67 | Le livre actuellement en cours de lecture est ["Introduction to Algorithms"](02_introduction_algorithms/README.md) de Thomas H. Cormen, 68 | Charles E. Leiserson, Ronald L. Rivest et Clifford Stein. 69 | 70 | - [Chapitre 1 - The Role of Algorithms in Computing](02_introduction_algorithms/chapitre_01.md). Séance du 26 février 2018. 71 | - [Chapitre 2 - Getting Started](02_introduction_algorithms/chapitre_02.md). Séance du 5 mars 2018. 72 | - [Chapitre 3 - Growth of Functions](02_introduction_algorithms/chapitre_03.md). Séance du 12 mars 2018. 73 | - [Chapitre 4 - Divide-and-Conquer](02_introduction_algorithms/chapitre_04.md). Séance du 19 mars 2018. 74 | - [Chapitre 5 - Probabilistic Analysis and Randomized Algorithms](02_introduction_algorithms/chapitre_05.md). Séance du 9 avril 2018. 75 | - [Chapitre 6 - Heapsort](02_introduction_algorithms/chapitre_06.md). Séance du 16 avril 2018. 76 | - [Chapitre 7 - Quicksort](02_introduction_algorithms/chapitre_07.md). Séance du 23 avril 2018. 77 | - [Chapitre 8 - Sorting in Linear Time](02_introduction_algorithms/chapitre_08.md). Séance du 30 avril 2018. 78 | - [Chapitre 9 - Medians and Order Statistics](02_introduction_algorithms/chapitre_09.md). 79 | - [Chapitre 10 - Structures de données élémentaires](02_introduction_algorithms/chapitre_10.md). 80 | 81 | ## Computer Architecture : A Quantitative Approach, 6ème édition, de John Hennessy 82 | 83 | - [Chapitre 1 - Fundamentals of Quantitative Design and Analysis](03_computer_architecture/01_fundamentals_of_quantitative_design_and_analysis.md). Séance prévue le 29 juillet 2020. 84 | - Chapitre 2 - Memory Hierarchy Design 85 | - Chapitre 3 - Instruction-Level Parallelism and Its Exploitation 86 | - Chapitre 4 - Data-Level Parallelism in Vector, SIMD, and GPU Architectures 87 | - Chapitre 5 - Thread-Level Parallelism 88 | - Chapitre 6 - Warehouse-Scale Computers to Exploit Request-Level and Data-Level Parallelism 89 | - Chapitre 7 - Domain-Specific Architectures 90 | - Annexe A - Instruction Set Principles 91 | - Annexe B - Review of Memory Hierarchy 92 | - Annexe C - Pipelining: Basic and Intermediate Concepts 93 | 94 | Annexes hors version papier 95 | 96 | - Annexe D - Storage Systems 97 | - Annexe E - Embedded Systems 98 | - Annexe F - Interconnection Networks 99 | - Annexe G - Vector Processors in More Depth 100 | - Annexe H - Hardware and Software for VLIW and EPIC 101 | - Annexe I - Large-Scale Multiprocessors and Scientific Applications 102 | - Annexe J - Computer Arithmetic 103 | - Annexe K - Survey of Instruction Set Architectures 104 | - Annexe L - Advanced Concepts on Address Translation 105 | - Annexe M - Historical Perspectives and References 106 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_06_07.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 6 - Objets et structures de données 3 | 4 | ## Abstraction de données 5 | 6 | Pour l'auteur, une classe n'est pas simplement un agrégat de données, mais impose également comment utiliser ces données 7 | (lecture valeurs seules, écriture atomique). En cela, il distingue les classes et les structures de données. 8 | 9 | Le but de l'encapsulation est de manipuler l’essence des données, sans avoir à en connaître l’implémentation. 10 | Et donc ne pas exposer les détails de nos données. 11 | 12 | La base de ce chapitre est de faire une réflexion sérieuse sur la meilleure manière de représenter les données 13 | contenues dans un objet 14 | 15 | ## Antisymétrie données/objet 16 | 17 | Les objets cachent leurs données derrière des abstractions et fournissent des fonctions qui manipulent ces données. 18 | Les structures de données exposent directement leurs données et ne fournissent aucune fonction significative. 19 | 20 | Un code procédural (un code qui utilise des structures de données) facilite l’ajout de nouvelles fonctions sans 21 | modifier les structures de données existantes. Un code orienté objet facilite l’ajout de nouvelles classes sans 22 | modifier les fonctions existantes. 23 | 24 | Un code procédural complexifie l’ajout de nouvelles structures de données car toutes les fonctions doivent être 25 | modifiées. Un code orienté objet complexifie l’ajout de nouvelles fonctions car toutes les classes doivent être 26 | modifiées. 27 | 28 | Parfois, nous voulons réellement de simples structures de données avec des procédures qui les manipulent. 29 | 30 | ## Loi de Déméter 31 | 32 | Un module ne doit pas connaître les détails internes des objets qu’il manipule. 33 | 34 | Une méthode `f` d’une classe `C` ne doit appeler que les méthodes des éléments suivants : 35 | 36 | - `C` ; 37 | - un objet créé par `f` ; 38 | - un objet passé en argument à `f` ; 39 | - un objet contenu dans une variable d’instance de `C`. 40 | 41 | Voici une exemple de code qui ne respecte pas cette loi : 42 | 43 | ``` 44 | String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath(); 45 | ``` 46 | 47 | L'auteur qualifié un tel code, qui appel en chaîne plusieurs méthodes, de "catastrophe ferroviaire". 48 | 49 | Les structures hybrides commulent le pire des deux monde. 50 | 51 | ### Cacher la structure 52 | 53 | Il faut se poser la question de savoir si la solution est de retourner une structure (donc ne plus avoir de 54 | contraintes d'accès aux membres) ou mettre toutes les methodes dans le classe qui appelle toutes ces fonctions 55 | en chaîne. Et pour l'auteur, la réponse est non. 56 | 57 | Il ne faut pas demander quelque chose concernant ses détails internes, mais laisse la classe le faire. 58 | Il ne faut pas mélanger différents niveaux de détails (voir les chapitres précedents). 59 | 60 | ## Objets de transfert de données, DTO, Data Transfer Object 61 | 62 | En Java, il est classique de créer des "beans" : ce sont des structures de données, avec ses membres en privée, 63 | un constructeur public qui prend en paramètre tous ces membres, et proposent des getters sur ces membres. 64 | 65 | ### Enregistrement actif 66 | 67 | Pour terminer ce chapitre, une remarque sur les "enregistrements actifs" : ils contiennent des methodes comme 68 | `find` ou `save`, ce qui en fait des structures hybride. 69 | 70 | ## Conclusion 71 | 72 | Les deux types de données suivent des approches differentes pour l'evolution du code : ajouter des classes 73 | ou ajouter des fonctions. 74 | 75 | ## Discussions 76 | 77 | - le "method chaining" (ou "named parameter idiom") ne doit pas être confondu avec la "catastrophe ferrovière", 78 | même si les syntaxes sont proches. La difference est que le "method chaining" retourne le même objet après chaque 79 | appel, ce qui respecte la loi de Demeter. 80 | 81 | ``` 82 | QString("bla bla").arg(123).arg(123) 83 | std::cout << 1 << 123 << std::endl; 84 | ``` 85 | 86 | - les choix de design des langages peuvent avoir une importance choix par rapport au respect des accès aux données. 87 | Certains langages permettront de renforcer les acces (ou autre contraire ne pas les respecter), proposer des modeles 88 | pour la structure de donnees (`Interface` en Java, meta-classes du C++20, etc). 89 | 90 | À noter, le C ne propose pas de syntaxe pour l'acces au membres, mais il est possible de créer des structures 91 | opaques pour cacher le définition. 92 | 93 | ``` 94 | struct opaque; 95 | void f(struct opaque* o); 96 | ``` 97 | 98 | 99 | # Chapitre 7 - Gestion des erreurs 100 | 101 | La gestion des erreurs constitue une tâchs indispensable dans un programme, tous les programmes peuvent 102 | avoir des entrées anormales, la lecture sur un périphériques peuvent échouer, ou bien d'autres raisons. 103 | 104 | La gestion de certaines erreurs peut être automatique, mais le developpeur reste responsables du bon 105 | comportement de notre code, qui doit suivre les specifications attendues. 106 | 107 | Le traitement des erreurs est important, mais il ne doit pas masquer la logique du code. 108 | 109 | 110 | ## Utiliser des exceptions à la place des codes de retour 111 | 112 | separation code de gestion des erreurs et le traitement des donnees 113 | 114 | ## Commencer par écrire l’instruction try-catch-finally 115 | 116 | exception = définissent une portée à l’intérieur du programme. try = transactions (bof?) 117 | catch doit laisser le programme dans un état cohérent, quel que soit ce qui s’est produit dans la partie try 118 | 119 | code d'exemple = TDD 120 | - creer le test 121 | - creer un stub/bouchon (fonction qui n'est pas implementé, mais qui compile = le test échoue) 122 | - implementation 123 | - refactoring (separation try-catch-finaly) 124 | 125 | tester les exceptions 126 | 127 | ## Employer des exceptions non vérifiées 128 | 129 | exception verifiee = liste des throws dans la signature. Pas en C#, C++, python, ruby 130 | 131 | violation de OCP : modificaiton de details internes (throw dans la signature) doit etre propagé aux codes appelant. cascade de modifications qui commence aux niveaux inférieurs du logiciel et remonte vers les niveaux les plus élevés 132 | 133 | ## Fournir un contexte avec les exceptions 134 | 135 | déterminer l’origine et l’emplacement de l’erreur 136 | 137 | ## Définir les classes d’exceptions en fonction des besoins de l’appelant 138 | 139 | classifier les erreurs: 140 | - origine 141 | - type 142 | - la manière de les intercepter 143 | 144 | creer des "enveloppes" (wrapper) : 145 | - diminue les dependances 146 | - facilite les tests 147 | 148 | ## Définir le flux normal 149 | 150 | séparation entre la logique métier et le traitement des erreurs. Mais déplacer la détection des erreurs à la lisière du programme. 151 | 152 | Creer des cas particulier pour conserver le flux normal lisible 153 | 154 | ## Ne pas retourner null 155 | 156 | Retourner un objet "qui ne fait rien" 157 | 158 | ## Ne pas passer null 159 | 160 | ## Conclusion 161 | 162 | 163 | - "nouvelles" methodes de gestion des donnees : retour de fonctions, exception, monades (Maybe), optional 164 | 165 | - RAII et exception, equivalent de finally 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_01.md: -------------------------------------------------------------------------------- 1 | 2 | > Merci à Ksass'Peuk pour ce resumé. 3 | 4 | # Chapitre 1 - Code propre 5 | 6 | "Coder Proprement" est un livre de Robert C. Martin, dît "Oncle Bob". Il est principalement connu pour ses contributions 7 | à propos de la méthode Agile, de la gestion de projet et des principes SOLID. Ses autres livres sont également intéressants, 8 | il ne faut pas hésiter à les lire aussi. 9 | 10 | Les objectifs généraux de ce livre sont de fournir : 11 | 12 | - des guidelines pour la rédaction de code: noms, fonctions, commentaires, mise en forme, 13 | - une certaine connaissance des structures de données, 14 | - la bonne pratique qu'est "tester" le coder. 15 | 16 | Avec pour finalité d'être capable : 17 | 18 | - de différencier le bon et le mauvais code, 19 | - d'écrire du bon code, 20 | - de transformer du mauvaise code en bon code. 21 | 22 | ## Introduction 23 | 24 | Le but de ce chapitre est de commencer à répondre à la question "qu'est ce qu'un code propre ?", à travers trois 25 | questions générales: 26 | 27 | - pourquoi aura-t-on toujours besoin de code ? 28 | - que le coût du désordre ? 29 | - qu'est-ce qui caractérise un code propre ? 30 | 31 | ## Il y aura toujours du code : 32 | 33 | L'abstraction augmente et l'on semble avoir de moins en moins besoin de coder, mais le code n'est finalement qu'un langage dans lequel on exprime nos exigences et il y aura toujours des exigences à exprimer. 34 | 35 | ## Le coût du désordre : 36 | 37 | ### Causes 38 | 39 | Les raisons entraînant la création d'un mauvais code sont très souvent reliées à un problème plus général dans tout 40 | projet : la pression du temps. C'est généralement du code réalisé trop vite pour répondre le plus rapidement possible à 41 | un besoin sans tenir compte de la maintenance future, on remet "à plus tard" le fait de rendre le code propre, mais 42 | "plus tard" signifie "jamais". 43 | 44 | ### Conséquences 45 | 46 | Il s'en suit un ralentissement de la productivité à cause de d'un code négligé dans lequel il est difficile d'avancer, 47 | car il est difficile à comprendre et aucune modification n'est négligeable. Surtout que reprendre à 0 est généralement 48 | complètement impossible et mène simplement aux mêmes travers. 49 | 50 | Produire du bon code est une question de survie professionnelle. 51 | 52 | ### Fausses causes, attitude 53 | 54 | Le relationnel avec les décideurs et les nouveaux développeurs est important. Les développeurs ont une trop forte 55 | tendance à rejeter la faute sur les décideurs qui les pressent mais il est de leur devoir : 56 | 57 | - de dire non lorsque quelque chose est impossible, 58 | - de s'assurer qu'il sera rare de devoir dire non à une demande faisable (avec un bon code). 59 | 60 | ## Code propre : 61 | 62 | Regroupement de plusieurs point de vue à propos de la rédaction de code. Un code propre doit être : 63 | 64 | - élégant : un code agréable à lire est plus facile à lire et donc plus facile à écrire. 65 | - simple : il y a une certaine idée de minimalisme (principe KISS), relié au point suivant ... 66 | - efficace : optimal en un certain sens, rien ne permet de l'améliorer de manière évidente, 67 | - explicite : il doit être assez expressif pour ne cacher aucune intention du développeur, 68 | - destiné à être partagé : fait pour être lu par des humains, et le désordre appelle le désordre. 69 | - testé : on assure qu'il fait ce que l'on veut (et les tests ré-expriment les besoins). 70 | 71 | Règle du boyscout : le code doit être plus propre que quand on est arrivé. Nous sommes reponsables d'écrire du code 72 | propre, de le maintenir propre et au besoin de le nettoyer. 73 | 74 | # Questions abordées pendant les discussions : 75 | 76 | ## Q1 : il parle d'un style d'écriture, de manière de concevoir. 77 | 78 | Il faut que le code soit conçu pour être compréhensible, mais cela va plus loin que juste la bonne architecture et la 79 | bonne organisation. On revient sur l'expressivité : le code montre clairement l'intention du développer, il ne cache 80 | rien, il est limpide. 81 | 82 | ## Q2 : bonnes pratiques dans les langages à travers des guidelines. 83 | 84 | Elles parlent à la fois : 85 | 86 | - de style d'écriture, 87 | - de bonne manière de concevoir. 88 | 89 | Exemples dans certains langages : 90 | 91 | - C++ https://github.com/isocpp/CppCoreGuidelines 92 | - C# https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions 93 | - Python : Python Enhancement Proposals https://www.python.org/dev/peps/ 94 | - Google Python Style Guide https://google.github.io/styleguide/pyguide.html 95 | 96 | Les designs patterns sont un exemple dans le point sur la conception. Ils peuvent néanmoins aussi aider d'autres 97 | codeurs à comprendre ce qu'on a voulu exprimer parce que ce sont des schémas connus (sans être figés ! Il sont sujets 98 | à adaptation). Le principal second intérêt des DP est de comprendre comment on a abouti à leur conception. 99 | 100 | L'utilisation des commentaires est un exemple sur le style d'écriture. Les commentaires ne doivent pas servir à 101 | comprendre l'intention du code. Ils doivent seulement aider à faire comprendre éventuellement des point des détails 102 | du code qui ne sont pas exprimables par le langage. Lorsqu'un code a besoin de commentaires expliquant le patch d'un 103 | patch, d'un patch, c'est le signe que l'on travaille sur un mauvais code. 104 | 105 | Documenter est délié de la notion de commentaire. Ce n'est pas parce que le langage fournit la documentation par 106 | l'intermédiaire du commentaire (au sens du langage) que l'on est effectivement en face de commentaires. 107 | 108 | ## Q3 : Relation avec les décideurs : de la difficulté à être entendu avec les décideurs. 109 | 110 | C'est important d'avoir un bon relationnel et être capable : 111 | 112 | - d'expliquer à d'autres, 113 | - d'apprendre aux autres à gérer ces problématiques. 114 | 115 | La méthode AGILE est une tentative de résolution par l'introduction du "business" au niveau de la production du code. 116 | Les dérives courantes sont l'utilisation de cette méthode pour reconstituer un modèle non agile où les développeurs 117 | exécutent sans se faire entendre. 118 | 119 | Il est important de présenter de manière concrète des fonctionnalités auprès des décideurs mais surtout aux destinataires 120 | du projet. Idéalement les réunions business et fonctionnalités devraient être complètement séparées pour éviter ce 121 | type de dérive. 122 | 123 | Addedum de discussion : l'UML (ou formalisme équivalent) n'est pas toujours adapté pour la compréhension mais peut aider 124 | pour le dialogue avec des non-initiés. 125 | 126 | ## Q4 : Relation avec les apprenants : problème de formation des personnes. 127 | 128 | Apprentissage : projet jetable, problème pour acquérir de la compétence sur la maintenance de projet. 129 | Nécessité de formation personnalisées pour former les gens au plus près et ne pas les lâcher complètement dans la nature 130 | avec un faux sentiment de compréhension. 131 | 132 | Problématique de l'enseignement "classique" vs les formations internet : impossible de créer et suivre des 133 | projets sur le long terme. C'est possible sur les formation internet, mais pas souvent fait. 134 | 135 | ## Autres questions non abordées : 136 | 137 | **Opposition entre code efficace vs premature optimisation** 138 | 139 | Certains experts cités dans ce premier chapitre indiquent que pour eux, un code propre est un code efficace. 140 | L'idée est qu'un code qui est déjà optimal n'aura pas besoin d'être modifié et donc demandera moins de maintenance. 141 | 142 | Est-ce que cette idée de code optimial ne s'oppose pas au problème de _premature optimisation_ ? 143 | 144 | **Choix du langage de programmation** 145 | 146 | Deux approches sont possibles pour choisir le langage de programmation (mais on peut étendre cette question a tous 147 | les choix technologiques sur un projet) : 148 | 149 | - utiliser le langage le plus adapté à un problème. Donc potentiellement un langage que l'on ne maîtrise pas. 150 | - utiliser un langage que l'on maitrise, meme s'il n'est pas le plus adapté à un problème. (Dans la limite du raisonnable, 151 | on ne va pas créer un site web en assembleur). 152 | 153 | Quel choix feriez-vous et dans quels contextes ? 154 | 155 | ## Strawpolls : 156 | 157 | Répondus : 158 | 159 | - Pensez-vous que votre propre code est propre ? http://www.strawpoll.me/14162994 160 | - Êtes-vous... http://www.strawpoll.me/14163039 161 | - C'était cool ? http://www.strawpoll.me/14163936 162 | 163 | Non proposé : 164 | 165 | - Quel(s) langage(s) de programmation utilisez-vous ? http://www.strawpoll.me/14163066 166 | -------------------------------------------------------------------------------- /02_introduction_algorithms/chapitre_02.md: -------------------------------------------------------------------------------- 1 | 2 | # Chapitre 2 - Get started 3 | 4 | Le but du chapitre est de se familiariser avec le pseudo-code utilisé dans le livre et avec les 5 | notations liées à la complexité algorithmique. Les deux principaux exemples sont : 6 | 7 | - le tri par insertion (*insertion sort*) 8 | - le tri-fusion (*merge sort*) 9 | 10 | ## Tri par insertion 11 | 12 | Note à propos du pseudo-code : le but est d'être précis tout en s'abstrayant des détails quand cela 13 | permet de mieux comprendre l'algorithme en lui-même. Par exemple, on peut remplacer certaines 14 | instructions par une phrase en langue naturelle. 15 | 16 | Le code peut être trouvé à peu près n'importe où. Il consiste à chaque tour de boucle à 17 | prendre le prochain élément non trié, à faire glisser tous les éléments qui lui sont supérieurs 18 | vers la fin du tableau et finalement l'insérer juste après le premier élément inférieur. 19 | 20 | ### La notion d'invariant de boucle 21 | 22 | Un invariant de boucle est une propriété qui est vraie avant de commencer chaque itération de boucle 23 | (comprenant l'invalidation de la condition de boucle). Trois propriété à montrer : 24 | 25 | - vrai à l'initialisation, 26 | - si vrai au rang i, vrai au rang i+1, 27 | - vrai à la terminaison. 28 | 29 | ### Invariant du tri par insertion 30 | 31 | A chaque itération i, le sous-tableau allant du début à i-1 (i inclu ou exclu) correspond 32 | à une permutation triée des éléments qui étaient précédemment présents dans ce sous-tableau. 33 | 34 | Intuition de preuve : 35 | 36 | 1) un tableau à un élément est trié. 37 | 2) récurence : 38 | - les éléments du sous-tableau à i sont triés, les faire glisser conserve le tri. 39 | - on ajoute l'élément en sous des éléments qu'on a fait glissé, 40 | - et au dessus du premier élément plus petit. 41 | - le tableau final est donc trié. 42 | 3) à la fin, i vaut taille du tableau donc tous les éléments jusqu'à taille du tableau sont triés 43 | 44 | ### Exercices 45 | 46 | 1) appliquer l'algo sur papier 47 | 2) changer la condition pour faire glisser (et la preuve reste la même, modulo le sens de l'inégalité) 48 | 3) linear-search : 49 | - invariant : pour tout élément avant i, ce n'est pas celui-cherché. 50 | - avec une variable intermédiaire, la preuve est plus directe. 51 | 4) dernier algo, un peu plus compliqué. 52 | 53 | ## Analyser des algorithmes 54 | 55 | On considère une machine abstraite qui a ses instructions en commun avec une vraie machine. Cependant, 56 | on évacue les questions de concurrence, parallélisme, caches, etc. On considère des mots de la taille 57 | d'un entier. 58 | 59 | Taille de l'entrée : généralement on considère que le nombre d'éléments en entrée est une 60 | bonne entrée. Mais par exemple, dans le cas de l'addition de deux entiers en bit à bit, ce sera le 61 | nombre de bits. Cela doit être précisé pour chaque problème. 62 | 63 | Le temps de calcul : nombre de pas primitifs exécutés, ici nous considérerons généralement les 64 | instructions 65 | 66 | Note : c'est une triche assez commune, pour les algos de graphs par exemple, de considérer 67 | qu'on peut vérifier l'existence d'un élément dans un set en O(1). 68 | 69 | ### Runtime du tri par insertion 70 | 71 | - Meilleur cas : les éléments sont déjà triés (on obtient un O(n)) 72 | - Pire cas : les éléments sont à l'envers (an²+bn+c ~ O(n²)) 73 | 74 | On se concentre généralement sur le pire cas. Il donne une borne supérieure et c'est le plus 75 | intéressant en général. Le cas moyen peut être intéressant parfois quand il est facile de l'obtenir 76 | et que les résultats sont très bon sur celui-ci. 77 | 78 | ### Croissance 79 | 80 | On simplifie la vue que l'on a de la complexité en ne gardant que l'élément d'ordre maximal. 81 | 82 | Notation : Theta 83 | 84 | ### Exercices 85 | 86 | 1) n cube 87 | 2) récurence : 88 | - l'algo est en n² (best et worse sont équivalents) 89 | - l'invariant est sensiblement le même que selection sort 90 | - l'élément final est nécessairement supérieur puisque : 91 | - soit on l'a échangé avec le précédent parce que le précédent était plus grand 92 | - soit on ne l'a pas échangé par le final était plus grand 93 | 3) dans le meilleur des cas 1. Dans le pire, tous 94 | 4) vérifier en premier lieu si c'est OK ? 95 | 96 | ## Design des algorithmes 97 | 98 | Présentation de l'approche "diviser pour régner" (*divide and conquer*). 99 | 100 | Généralement, des algorithmes récursifs qui vont : 101 | 102 | - diviser le sous problème en instances réduites 103 | - résoudre ces sous-problèmes récursivement 104 | - combiner les solutions pour obtenir la solution au problème original 105 | 106 | ### Exemple avec tri fusion 107 | 108 | - on coupe le tableau en deux 109 | - on trie chacun des tableaux avec tri fusion 110 | - on fusionne les deux tableaux triés 111 | 112 | La récursion s'arrête pour les tableaux de taille 1 ou moins : ils sont déjà triés. 113 | 114 | Note : la sentinelle complique le code plus qu'elle ne le simplifie AMHA. 115 | 116 | Invariant : tous les éléments jusqu'au rang "n" de l'algo sont triés, et tous les éléments 117 | restant dans les tableaux sont plus grand que le dernier ajouté. 118 | 119 | 1) initialisation : il n'y a pas d'élément 120 | 2) récurence 121 | - tous les éléments jusqu'à n sont triés et ceux restant sont supérieur, 122 | - on prend le plus petit des deux et on l'ajoute donc : 123 | - les éléments sont triés à n+1 124 | - et comme on a pris le plus petit des éléments restant, tous les autres sont plus grands 125 | 3) fin: quand on arrive à la taille tous les éléments sont triés. 126 | 127 | ### Analyse d'un algo diviser pour régner 128 | 129 | On utilise généralement des équations de récurrence. 130 | 131 | Généralité : 132 | 133 | > T(n) = | O(1) si n <= c 134 | > 135 | > T(n) = | aT(n/b) + D(n) + C(n) sinon 136 | 137 | Avec `a` le nombre de sous-problèmes, `b` la taille des sous-problèmes, `D` le temps de division et 138 | `C` le temps de combinaison. 139 | 140 | Pour merge sort : 141 | 142 | La procédure de séparation en deux est en temps constant, la procédure de fusion est linéaire (on 143 | visite chaque élément). Chaque étage de la récursion est donc en temps N (on voit une fois chaque 144 | élément). On a ensuite (log n) récursion (puisqu'on casse en deux à chaque tour) donc : 145 | 146 | > T(n) = | O(1) si n = 1 147 | > 148 | > T(n) = | 2T(n/2) + O(n) si n > 1 149 | 150 | La complexité finale est O(n log n) (à voir dans le chapitre 4) 151 | 152 | ### Exercices 153 | 154 | 1) Faire une exécution de merge-sort à la main 155 | 2) La même chose sans les sentinelles 156 | 3) Par induction sur k 157 | 4) Ça ne change rien, mais on peut construire le raisonnement 158 | 5) Si ksass'peuk a le temps, il mettra le *binary search* avec Frama-C quelque part 159 | 6) Ça ne change rien au fait qu'il faut glisser les éléments 160 | 7) ? 161 | 162 | ### Problèmes 163 | 164 | A voir. 165 | 166 | # Discussion 167 | 168 | ## Preuve de terminaison 169 | 170 | Utilisation de variant de boucle. 171 | 172 | Note à propos de la récurrence, qui est équivalente à une boucle. 173 | 174 | ## Exemple d'élémemts qui différencient de la machine RAM 175 | 176 | - Cache pour les mémoire 177 | - Execution *out of order* 178 | 179 | Pertinence de l'analyse : 180 | 181 | - Typiquement en rapport à la taille des mots 182 | - Forte complexité -> impact moindre des caches 183 | - Attention à bien regarder tout ce qui se passe et ne pas abstraire les mauvaises idées 184 | - WCET sur du vrai matériel, possible mais très coûteux. 185 | 186 | ## Tri adaptatif en fonction des entrées 187 | 188 | Et de manière générale, algo peut être adapté quand l'entrée à des propriétés connues. 189 | 190 | Par exemple pour le tri, on peut choisir le bon algorithme en fonction de la taille du 191 | tableau. 192 | 193 | ## Différence entre bas et haut niveau à la fois sur la preuve et la complexité 194 | 195 | A bas niveau, on a souvent des détails supplémentaires qui sont plus ou moins intéressants : 196 | 197 | - pour la complexité, il faut être capable de faire un tri pertinent entre ce qui est 198 | coûteux et ce qui ne l'est pas. 199 | - pour la preuve, aucun détail ne peut être ignoré généralement (notamment la sûreté des 200 | accès), mais on peut progressivement s'en abstraire à l'aide de propriété de plus 201 | haut niveau. 202 | 203 | À haut niveau, on a moins de détails et on compose des traitements plus larges, cela 204 | facilite généralement les raisonnements. 205 | 206 | - en complexité il faut faire attention : certains détails des couches inférieures 207 | pourraient nous permettre d'avoir un calcul plus précis. 208 | - en preuve, tant qu'on prouve qu'on respecte correctement les pré-conditions, on peut 209 | raisonner abstraitement et prendre les post-conditions sans réfléchir. 210 | -------------------------------------------------------------------------------- /01_coder_proprement/chapitre_02.md: -------------------------------------------------------------------------------- 1 | 2 | > Merci à Ksass'Peuk pour ce resumé. 3 | 4 | # Chapitre 2 - Noms significatifs 5 | 6 | Le but de ce chapitre est d'établir un certain nombre de règles simples pour 7 | avoir un bon nommage des différents éléments d'un programme (variables, 8 | fonctions, classes, etc). 9 | 10 | Les différents points abordés par ce chapitre sont : 11 | 12 | - noms révélateurs d'intentions 13 | - éviter la désinformation 14 | - faire des distinctions significatives 15 | - choisir des noms prononçables 16 | - choisir des noms compatibles avec une recherche 17 | - éviter la codification 18 | - éviter les associations mentales. 19 | - noms des méthodes 20 | - noms des classes 21 | - ne pas faire le malin 22 | - choisir un mot par concept 23 | - éviter les jeux de mots 24 | - choisir des noms dans le domaine de la solution 25 | - choisir des noms dans le domaine du problème. 26 | - ajouter un contexte significatif 27 | - ne pas ajouter de contexte inutile 28 | 29 | ## Noms révélateurs d'intentions 30 | 31 | Un bon nom doit exprimer, pour l'élément qu'il nomme : 32 | 33 | - la raison de son existence, 34 | - son rôle, 35 | - son utilisation. 36 | 37 | Typiquement, s'il y a besoin d'un commentaire pour expliquer cela, le nom est 38 | mauvais. Non seulement il est important de trouver un bon nom mais il faut 39 | être prêt à changer quand on en trouve un meilleur. 40 | 41 | Une nouvelle fois le point crucial est de révéler les intentions du code. 42 | Le problème n'est généralement pas dans la trop importante simplicité du code 43 | mais plutôt dans la quantité d'informations implicites qu'il renferme, cela 44 | implique du lecteur la connaissance d'informations qui ne sont pas expliquées 45 | par le code. 46 | 47 | Exemples typiques : 48 | 49 | - signification de valeur numériques en dur dans le code, 50 | - signification d'un indice pour un tableau, 51 | - manière particulière d'utiliser une variable ou une fonction. 52 | 53 | ## Éviter la désinformation 54 | 55 | Le nom ne doit pas risquer de détourner le sens du code. Mieux vaut éviter, 56 | par exemple d'utiliser un mot comme "liste" dans un nom si on ne désigne pas 57 | précisément une liste (qui a un sens particulier en programmation). 58 | 59 | Il faut également faire attention à ne pas utiliser des noms trop proches qui 60 | peuvent induire en erreur car l'on ne remarque pas immédiatement les différences 61 | qui peuvent apparaître. 62 | 63 | Un bon nom implique que l'on n'a pas la nécessité d'aller voir les commentaires 64 | avant d'auto-compléter un nom (et pas le besoin d'aller voir une liste de 65 | fonctionnalités proposées par exemple). 66 | 67 | Caractères prise de tête si mal utilisés: 68 | 69 | - "o" majuscule (facilement confondu avec zéro) 70 | - "L" minuscule (facilement condondu avec un) 71 | 72 | ## Faire des distinctions significatives 73 | 74 | Modifier un nom pour le compilateur, c'est aller aux devants de problèmes. 75 | Exemple typique : renommage d'une variable "qui a le même sens" qu'une autre 76 | pour éviter le conflit de nom. Si les variables ne sont pas les mêmes, elles 77 | n'ont nécessairement pas le même sens. 78 | 79 | Mauvaises pratiques : 80 | 81 | - introduction de faute volontaire dans un mot pour le différencier, 82 | - utilisation de numéros, 83 | - utilisation de mots parasites. 84 | 85 | Généralement, on ne provoquera pas de désinformation mais au minimum, on 86 | n'exprime pas clairement les intentions du code. 87 | 88 | Le mots comme "info" ou "data" ne sont pas précis. Difficulté par exemple de 89 | différencier correctement "MachinData" et "Machin", rendant difficile le fait 90 | de savoir laquelle des deux on doit utiliser pour obtenir une information 91 | particulière quand on utilise l'une ou l'autre. 92 | 93 | Conseil : ne jamais mettre le mot variable dans le nom d'une variable, ou 94 | array dans un tableau, ou string dans une chaîne, etc. 95 | 96 | ## Choisir des noms prononçables 97 | 98 | Besoin dû principalement au fait que notre cerveau est câblé pour mieux 99 | manipuler des choses prononçable. Cela permet entre autre d'avoir une 100 | conversation intelligible avec une autre personne. 101 | 102 | ## Choisir des noms compatibles avec une recherche 103 | 104 | Éviter par exemple les noms d'une seule lettre et ou les constantes numérique, 105 | qui sont difficiles à rechercher dans un texte. Par ailleurs l'inversion de 106 | chiffres dans une grande constante peut rendre cette constante impossible à 107 | détecter. 108 | 109 | La longueur d'un nom doit correspondre à la taille de sa portée. 110 | 111 | Plus le nom est susceptible d'être recherché à plusieurs endroit, plus il doit 112 | être facile à rechercher. 113 | 114 | ## Éviter la codification 115 | 116 | La codification doit être apprise, ce qui est une charge de travail inacceptable 117 | quand on doit déjà se taper l'apprentissage de la base de code sur laquelle on 118 | arrive. D'autant que les noms codifiés sont souvent imprononçables et sujets 119 | aux erreurs de saisies. 120 | 121 | ### Notation hongroise 122 | 123 | Importante dans l'API C Windows, créée à un moment où la vérification de type 124 | était pour ainsi dire inexistante, et que l'on avait besoin d'un mécanisme 125 | explicite dans le nommage pour mémoriser les types. 126 | 127 | Ce n'est plus le cas aujourd'hui, la plupart des langages étant fortement typés 128 | ou inversement, certains langages rendant la distinction de type généralement 129 | inutile. 130 | 131 | Bref : la notation hongroise, aujourd'hui, ne sert plus à rien. 132 | 133 | ### Préfixe des membres 134 | 135 | Préfixage "m_" pour les membres inutile : les classes et fonctions doivent être 136 | assez courtes pour qu'une telle disctinction soit inutile. Ce préfixe 137 | représenterait alors un foullis inutile. 138 | 139 | ### Interfaces et implémentations 140 | 141 | Mieux vaut éviter de commencer une interface avec "I". Au choix, il est plus 142 | pertinent de signaler une implémentation (par un suffixe "Imp" par exemple). 143 | 144 | ## Eviter les associations mentales. 145 | 146 | C'est le problème des noms qui sont insuffisamment explicites au sens où le 147 | développeur doit faire lui même un effort pour réassocier le nom à un autre nom 148 | plus explicite correspondant au concept réel. 149 | 150 | Exemple : initiales de plusieurs mots que le développeur doit lui même réassocier 151 | à ces mots pour finalement atteindre le concept. 152 | 153 | ## Noms des classes 154 | 155 | Nommer les classes par des groupe nominaux (pas de verbe). 156 | 157 | Éviter les mots trop généraux comme : Manager, Processor, Data, Info, etc. 158 | 159 | ## Noms des méthodes 160 | 161 | Choisir des mots auquels on s'attend : 162 | 163 | - get pour recevoir de l'information, 164 | - is pour exprimer un prédicate, 165 | - etc. 166 | 167 | ## Ne pas faire le malin 168 | 169 | Éviter l'humour lorsque l'on nomme des éléments d'un programme. Si la blague est 170 | oubliée, cela peut porter à confusion. Dites ce que vous pensez, et pensez ce que 171 | vous dites. 172 | 173 | ## Choisir un mot par concept 174 | 175 | Et s'y tenir ! Typiquement éviter de faire cohabiter : fetch, retrieve et get. 176 | Les noms doivent être autonomes et cohérent, si les concepts sont similaires, 177 | les écritures de ces concepts doivent être simulaires, et inversement. 178 | 179 | Cela constitue le lexique du programme et il ne doit pas perturber le lecteur. 180 | 181 | ## Éviter les jeux de mots 182 | 183 | Lorsqu'un mot peut avoir deux sens différents, mieux vaut le bannir. Par exemple 184 | lorsque le concept est semblable mais agit de manière sensiblement différente, 185 | mieux vaut choisir un autre mot. 186 | 187 | ## Choisir des noms dans le domaine de la solution 188 | 189 | Le domaine du problème n'est généralement pas le domaine des développeurs du 190 | code. Mieux vaut choisir des mots qui sont dans le domaine de la solution (donc 191 | typiquement des termes informatiques). 192 | 193 | ## Choisir des noms dans le domaine du problème 194 | 195 | Lorsque le concept n'appartient PAS au domaine informatique, ne pas essayer de 196 | simplifier et vulgariser. Mieux vaut utiliser le terme technique exacte du 197 | problème pour pouvoir faire appel à un expert du domaine le cas échéant. 198 | 199 | ## Ajouter un contexte significatif 200 | 201 | La plupart des noms ne sont pas significatifs en l'état. Il faut leur redonner 202 | un contexte à travers des classes, fonctions ou espaces de noms appropriés. Voir 203 | d'ajouter un préfixe en dernier ressort. 204 | 205 | ## Ne pas ajouter de contexte inutile 206 | 207 | Éviter de mettre de l'information redondante (le nom de l'application elle-même 208 | par exemple) ou hors de propos (distinctions adresse postale d'un client ou d'un 209 | fournisseur). 210 | 211 | ## Mots de la fin 212 | 213 | Le choix des noms est difficile et nécessite 214 | 215 | - une bonne aptitude à décrire, 216 | - une culture générale partagée, 217 | - un bon enseignement. 218 | 219 | Beaucoup de développeurs ont peur du renommage, mais nous ne mémorisons 220 | généralement pas réellement les noms dans un programmes. Nous les traitons et 221 | les oublions quand nous avons fini de travailler sur une zone particulière du 222 | programme. 223 | 224 | # Questions abordés pendant les discussion 225 | 226 | Nous avons globalement eu moins de discussions pendant cette séance, le chapitre 227 | énonçant finalement des usages qui sont déjà assez fortement présents chez les 228 | développeurs pros. 229 | 230 | ## Q1: Point de désaccord sur la présence de mots comme "list" dans un nom 231 | 232 | Par exemple pour distinguer un élément d'une collection VS une collection 233 | elle-même. D'un côté l'utilisation du pluriel peut parfois être dure à 234 | remarquer. D'un autre côté, l'ajout d'autres mots "parasites" comme "group_of" 235 | ou "bunch_of" conduit à de l'imprécision. Au cas par cas, cette règle peut 236 | sembler un peu forte. 237 | 238 | ## Q2: Choix des noms prononçables, portage de vieux code 239 | 240 | Certains code dans des langages comme Cobol imposent des contraintes fortes 241 | sur le nommage des variables qui ont souvent mené à des dérives comme des 242 | noms composés quasi-exclusivement d'initales et de chiffres. Ces noms 243 | imprononçables sont très généralement source de confusion, lors d'un portage 244 | mieux vaut complètement renommer ces éléments. 245 | 246 | ## Q3: Point sur la codification VS la création d'un lexique 247 | 248 | Ne pas confondre l'utilisation d'un lexique commun et la codification. Si 249 | l'importance du lexique devient telle que l'apprendre et le comprendre n'est 250 | plus triviale alors ce lexique tire vers la codification ce qui est une 251 | mauvaise chose. 252 | 253 | ## Q3b: notation hongroise 254 | 255 | Cette notation a en plus le défaut de ne pas être robuste à la maintenance, 256 | si l'on change légèrement le typage des éléments, on peut se retrouver à 257 | devoir changer le nom de la variable alors que son utilisation et son sens 258 | n'ont pas changé. 259 | 260 | ## Q4: Contexte de noms : les espaces de noms 261 | 262 | Les espaces de noms sont très utiles pour organiser les éléments d'un 263 | programme cependant tous les langages ne possèdent pas la même notion d'espace 264 | de nom (pas le même contexte d'utilisation et pas le même impact sur le code), 265 | et même la présence d'un tel mécanisme ne garantit pas que les développeurs 266 | vont l'utiliser. 267 | 268 | Pour comparaison, on peut prendre la notion d'espace de noms à la C++ et la 269 | notion de package à la Java. Java y définit une notion de visibilité, ce qui 270 | n'est pas le cas de C++, et malgré le fait que cette notion d'espace de nom 271 | permettent de donner plus de sens au code (par la visibilité justement), cette 272 | notion ne semble pas être si utilisée par la communauté Java. 273 | --------------------------------------------------------------------------------