Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Améliorer la qualité du code source à l’aide d...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Améliorer la qualité du code source à l’aide de la complexité cognitive

Depuis 40 ans, la Compléxité Cyclomatique est defacto le standard pour mesurer le niveau de testabilité et maintenabilité du code source. Mais cette métrique souffre de beaucoup de limitations avec les languages modernes. Pour cette raison, SonarSource a publié une nouvelle métrique en 2016 beaucoup plus représentative du niveau de maintainabilité du code source: la Complexité Cognitive.

Cette session d'introduction permet de comprendre cette nouvelle métrique au travers de nombreux exemples de code open source issues notamment de SonarCloud.io.

Vous verrez également comment produire un code de meilleur qualité et retravailler du code existant en s'appuyant sur la Complexité Cognitive.

Avatar for Xavier Bourguignon

Xavier Bourguignon

April 19, 2018

Other Decks in Programming

Transcript

  1. #DevoxxFR Améliorer la qualité du code source à l’aide de

    la complexité cognitive Xavier Bourguignon @xbourguignon 1
  2. #DevoxxFR 4 int sumOfPrimes(int max) { int total = 0;

    OUT: for (int i = 1; i <= max; ++i) { for (int j = 2; j < i; ++j) { if (i % j == 0) { continue OUT; } } total += i; } return total; }
  3. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { int total =

    0; OUT: for (int i = 1; i <= max; ++i) { for (int j = 2; j < i; ++j) { if (i % j == 0) { continue OUT; } } total += i; } return total; } 6
  4. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { // +1 int

    total = 0; OUT: for (int i = 1; i <= max; ++i) { for (int j = 2; j < i; ++j) { if (i % j == 0) { continue OUT; } } total += i; } return total; } 7
  5. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { // +1 int

    total = 0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { if (i % j == 0) { continue OUT; } } total += i; } return total; } 8
  6. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { // +1 int

    total = 0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +1 if (i % j == 0) { continue OUT; } } total += i; } return total; } 9
  7. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { // +1 int

    total = 0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +1 if (i % j == 0) { // +1 continue OUT; } } total += i; } return total; } 10
  8. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { // +1 int

    total = 0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +1 if (i % j == 0) { // +1 continue OUT; } } total += i; } return total; } // cyclomatic complexity 4 11
  9. #DevoxxFR Exemple 2 String getWords(int number) { switch (number) {

    case 1: return "one"; case 2: return "a couple"; case 3: return "a few"; default: return "lots"; } } 12
  10. #DevoxxFR Exemple 2 String getWords(int number) { // +1 switch

    (number) { case 1: return "one"; case 2: return "a couple"; case 3: return "a few"; default: return "lots"; } } 13
  11. #DevoxxFR Exemple 2 String getWords(int number) { // +1 switch

    (number) { case 1: // +1 return "one"; case 2: return "a couple"; case 3: return "a few"; default: return "lots"; } } 14
  12. #DevoxxFR Exemple 2 String getWords(int number) { // +1 switch

    (number) { case 1: // +1 return "one"; case 2: // +1 return "a couple"; case 3: return "a few"; default: return "lots"; } } 15
  13. #DevoxxFR Exemple 2 String getWords(int number) { // +1 switch

    (number) { case 1: // +1 return "one"; case 2: // +1 return "a couple"; case 3: // +1 return "a few"; default: return "lots"; } } 16
  14. #DevoxxFR Exemple 2 String getWords(int number) { // +1 switch

    (number) { case 1: // +1 return "one"; case 2: // +1 return "a couple"; case 3: // +1 return "a few"; default: return "lots"; } } // cyclomatic complexity 4 17
  15. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { // +1 int

    total = 0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +1 if (i % j == 0) { // +1 continue OUT; } } total += i; } return total; } // cyclomatic complexity 4 19
  16. #DevoxxFR Exemple 2 String getWords(int number) { // +1 switch

    (number) { case 1: // +1 return "one"; case 2: // +1 return "a couple"; case 3: // +1 return "a few"; default: return "lots"; } } // cyclomatic complexity 4 20
  17. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { int total =

    0; OUT: for (int i = 1; i <= max; ++i) { for (int j = 2; j < i; ++j) { if (i % j == 0) { continue OUT; } } total += i; } return total; } 26
  18. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { int total =

    0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { if (i % j == 0) { continue OUT; } } total += i; } return total; } 27
  19. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { int total =

    0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +2 if (i % j == 0) { continue OUT; } } total += i; } return total; } 28
  20. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { int total =

    0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +2 if (i % j == 0) { // +3 continue OUT; } } total += i; } return total; } 29
  21. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { int total =

    0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +2 if (i % j == 0) { // +3 continue OUT; // +1 } } total += i; } return total; } 30
  22. #DevoxxFR Exemple 1 int sumOfPrimes(int max) { int total =

    0; OUT: for (int i = 1; i <= max; ++i) { // +1 for (int j = 2; j < i; ++j) { // +2 if (i % j == 0) { // +3 continue OUT; // +1 } } total += i; } return total; } // cognitive complexity 7 31
  23. #DevoxxFR Exemple 2 String getWords(int number) { switch (number) {

    case 1: return "one"; case 2: return "a couple"; case 3: return "a few"; default: return "lots"; } } 32
  24. #DevoxxFR Exemple 2 String getWords(int number) { switch (number) {

    // +1 case 1: return "one"; case 2: return "a couple"; case 3: return "a few"; default: return "lots"; } } 33
  25. #DevoxxFR Exemple 2 String getWords(int number) { switch (number) {

    // +1 case 1: return "one"; case 2: return "a couple"; case 3: return "a few"; default: return "lots"; } } // cognitive complexity 1 34
  26. #DevoxxFR if (condition) { ... } else { if (une_autre_condition)

    { ... } else { if (une_3ème_condition) { ... } } } 37
  27. #DevoxxFR if (condition) { ... } else { if (une_autre_condition)

    { ... } else { if (une_3ème_condition) { ... } } } 38
  28. #DevoxxFR Collapse ! if (condition) { ... } else if

    (une_autre_condition) { ... } else if (une_3ème_condition) { ... } 39
  29. #DevoxxFR Collapse ! if (condition) { ... } else if

    (une_autre_condition) { ... } else if (une_3ème_condition) { … } 40
  30. #DevoxxFR if (condition) { ... return_value = ‘toto’ } else

    if (une_autre_condition) { ... return_value = ‘titi’ } else if (une_3ème_condition) { ... return_value = ‘tutu’ } return return_value 41
  31. #DevoxxFR if (condition) { ... return_value = ‘toto’ } else

    if (une_autre_condition) { ... return_value = ‘titi’ } else if (une_3ème_condition) { ... return_value = ‘tutu’ } return return_value 42
  32. #DevoxxFR Early return !! if (condition) { ... return ‘toto’

    } if (une_autre_condition) { ... return ‘titi’ if (une_3ème_condition) { ... return ‘tutu’ } 43
  33. #DevoxxFR Early return !! if (condition) { ... return ‘toto’

    } if (une_autre_condition) { ... return ‘titi’ if (une_3ème_condition) { ... return ‘tutu’ } 44
  34. #DevoxxFR if (my_value == 1) { ... } else if

    (my_value == 2) { ... } else if (my_value == 3) { ... } else if (my_value == 4) { … } 45
  35. #DevoxxFR if (my_value == 1) { ... } else if

    (my_value == 2) { ... } else if (my_value == 3) { ... } else if (my_value == 4) { … } 46
  36. #DevoxxFR Switch !!! switch (my_value) { case 1: ... case

    2: ... case 3: ... case 4: ... } 47
  37. #DevoxxFR Switch !!! switch (my_value) { case 1: ... case

    2: ... case 3: ... case 4: ... } 48
  38. #DevoxxFR try { ... } catch (NullPointerException ex) { logger.log(ex);

    throw ex; } catch (IOException ex) { logger.log(ex); throw ex; } catch (SQLException ex) { logger.log(ex); throw ex; } 49
  39. #DevoxxFR try { ... } catch (NullPointerException ex) { logger.log(ex);

    throw ex; } catch (IOException ex) { logger.log(ex); throw ex; } catch (SQLException ex) { logger.log(ex); throw ex; } 50
  40. #DevoxxFR try { conn = ds.getConnection(); s = conn.createStatement(); rs

    = s.executeQuery(requete); ... } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { rs.close();} catch (SQLException e) { } rs = null; } if (s != null) { try { s.close(); } catch (SQLException e) { } s = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { } conn = null; } } 53
  41. #DevoxxFR try { conn = ds.getConnection(); s = conn.createStatement(); rs

    = s.executeQuery(requete); ... } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { rs.close();} catch (SQLException e) { } rs = null; } if (s != null) { try { s.close(); } catch (SQLException e) { } s = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { } conn = null; } } 54
  42. #DevoxxFR Helpers !!!!! try { conn = ds.getConnection(); s =

    conn.createStatement(); rs = s.executeQuery(requete); ... } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(s); DbUtils.closeQuietly(rs); DbUtils.closeQuietly(conn); } 55
  43. #DevoxxFR Helpers !!!!! try { conn = ds.getConnection(); s =

    conn.createStatement(); rs = s.executeQuery(requete); ... } catch (SQLException e) { e.printStackTrace(); } finally { DbUtils.closeQuietly(s); DbUtils.closeQuietly(rs); DbUtils.closeQuietly(conn); } 56