La programmation défensive (ou l’art de ne pas (se) faire confiance)

La programmation défensive (ou l’art de ne pas (se) faire confiance)

Douze années d'expérience dans les métiers du développement PHP : beaucoup de ressenti, des succès, des échecs. Des projets internes, pour des tiers, des audits, de la formation, seul, (dans|au dessus|a coté) d'une équipe. Bref, un lot d'aventures qui forgent le caractère.

Tout cela a profondément marqué ma façon d'écrire des lignes de code, ajusté mon critère "qualité" et plus généralement, ma façon de concevoir des applications PHP. Comment est-ce que j'en suis arrivé à ne plus faire confiances aux autres (moi compris) et pourquoi ? Qu'est-ce que je cherche à garantir au travers de cette approche du développement ?

Nous verrons ensemble comment utiliser les règles de la programmation défensive et comment "protéger son code" dans le but d'en assurer la pérénnité tout en garantissant les objectifs suivants : un niveau de qualité sur le long terme, la possibilité de faire des évolutions simplement et un code sur lequel on aime intervenir.

12fad6dce4099a21ed70cf4409fe2271?s=128

Alexandre Balmes

June 24, 2020
Tweet

Transcript

  1. 2.
  2. 3.
  3. 4.
  4. 5.
  5. 6.
  6. 7.
  7. 8.
  8. 9.
  9. 10.
  10. 11.
  11. 12.
  12. 13.
  13. 14.
  14. 15.
  15. 16.
  16. 17.
  17. 18.
  18. 19.
  19. 20.
  20. 21.
  21. 22.
  22. 23.
  23. 24.
  24. 25.
  25. 26.
  26. 27.
  27. 28.
  28. 29.
  29. 30.
  30. 31.
  31. 32.
  32. 33.
  33. 34.
  34. 35.
  35. 36.
  36. 37.
  37. 38.
  38. 39.
  39. 41.
  40. 42.
  41. 43.
  42. 44.
  43. 45.
  44. 46.
  45. 47.
  46. 48.
  47. 49.
  48. 51.
  49. 52.
  50. 53.

    use Webmozart\Assert\Assert; class Employee { public function __construct($id) { Assert::integer($id,

    'The employee ID must be an integer. Got: %s'); Assert::greaterThan($id, 0, 'The employee ID must be a positive integer. Got: %s'); } }
  51. 54.

    new Employee('foobar'); // => InvalidArgumentException: // The employee ID must

    be an integer. Got: string new Employee(-10); // => InvalidArgumentException: // The employee ID must be a positive integer. Got: -10
  52. 55.
  53. 56.
  54. 57.
  55. 58.
  56. 59.
  57. 60.
  58. 61.
  59. 62.
  60. 63.
  61. 64.
  62. 65.
  63. 66.
  64. 67.
  65. 68.
  66. 69.
  67. 70.
  68. 71.
  69. 72.
  70. 73.
  71. 74.
  72. 75.
  73. 76.
  74. 77.
  75. 78.
  76. 79.
  77. 80.
  78. 81.

    use function Safe\file_get_contents; use function Safe\json_decode; // This code is

    both safe and simple! $content = file_get_contents('foobar.json'); $foobar = json_decode($content);
  79. 82.
  80. 85.
  81. 86.
  82. 87.
  83. 88.

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.5.0 <0.7.0; contract C {

    function f(uint a, uint b) public pure returns (uint) { return a * (b + 42); } }
  84. 89.

    <?php /** @psalm-external-mutation-free */ class Counter { private int $count

    = 0; public function increment() : void { $this->count++; } public function getCount() : int { return $this->count; } }
  85. 90.

    <?php /** @psalm-pure */ function makeCounter() : Counter { $a

    = new Counter(); $a->increment(); // this is fine return $a; }
  86. 91.

    <?php /** @psalm-pure */ function takeCounter(Counter $a) : Counter {

    $a->increment(); // Counter already exists, this is a mutation return new Counter(); }
  87. 92.
  88. 93.
  89. 94.
  90. 95.
  91. 96.
  92. 97.
  93. 98.
  94. 99.