Pourquoi le code review n'est pas une question de critiques, mais de qualité
\nImaginez : vous ouvrez une pull request d'un collègue. Il y a 500 lignes de code, ça sent le copier-coller, et à un endroit, quelqu'un a oublié de fermer une ressource. Votre tâche n'est pas seulement de trouver des bugs, mais d'améliorer le code. Le code review en Java n'est pas une surveillance policière, mais une création collective. Un bon relecteur sauve l'équipe de la dette technique, un mauvais la démotive ou laisse passer des vulnérabilités.
\nDans cet article, je vais vous expliquer quoi vérifier dans un code review en Java, pour ne pas perdre de temps sur des détails, mais sans rien laisser passer de critique. Vous obtiendrez une checklist prête à l'emploi et des exemples concrets.
\n\nArchitecture et conception : regarder à la racine
\nAvant de plonger dans les détails, évaluez la vue d'ensemble. Une mauvaise architecture ne se soigne pas avec du formatage.
\nViolation de SOLID
\nVérifiez si la classe ne s'est pas transformée en « objet divin ». Exemple de violation du principe de responsabilité unique :
\npublic class OrderService {\n public void createOrder(Order order) {\n // validation\n // calcul de la remise\n // envoi d'email\n // journalisation\n // sauvegarde en BDD\n }\n}\n\nIci, cinq raisons de modification. La bonne pratique est de déplacer la journalisation et l'envoi dans des services séparés.
\nComplexité excessive
\nParfois, le code résout un problème simple de manière complexe. Demandez-vous : « Puis-je faire plus simple ? » Si oui, écrivez-le dans la revue. Rappelez-vous le principe KISS.
\n\nSécurité : les failles à ne pas laisser passer
\nLa revue de code Java doit impérativement inclure une vérification de la sécurité. Même si le projet est interne.
\nInjections SQL
\nLa concaténation de chaînes, c'est le mal :
\n// MAUVAIS\nString query = "SELECT * FROM users WHERE name = '" + userName + "'";\nStatement stmt = connection.createStatement();\nResultSet rs = stmt.executeQuery(query);\n\nLa bonne pratique est d'utiliser PreparedStatement :
// BON\nString query = "SELECT * FROM users WHERE name = ?";\nPreparedStatement pstmt = connection.prepareStatement(query);\npstmt.setString(1, userName);\nResultSet rs = pstmt.executeQuery();\n\nFuite de données sensibles
\nVérifiez que les mots de passe, jetons ou numéros de carte ne sont pas journalisés. Utilisez @ToString.Exclude dans Lombok ou une exclusion explicite.
Comparaison non sécurisée d'objets
\n// MAUVAIS (comparaison de références)\nif (password == storedPassword) { ... }\n// BON\nif (password.equals(storedPassword)) { ... }\n\n\nPerformance : les goulots d'étranglement
\nN'optimisez pas prématurément, mais ne laissez pas non plus passer les ralentissements évidents.
\nOpérations inutiles dans les boucles
\n// MAUVAIS : length() est appelé à chaque fois\nfor (int i = 0; i < list.size(); i++) { ... }\n// BON\nint size = list.size();\nfor (int i = 0; i < size; i++) { ... }\n\nUtilisation de Stream pour des tâches simples
\nParfois, une boucle classique est plus lisible et plus rapide :
\n// Trop complexe\nlist.stream().filter(x -> x > 5).collect(Collectors.toList());\n// Simple\nList<Integer> result = new ArrayList<>();\nfor (int x : list) {\n if (x > 5) result.add(x);\n}\n\nFuite de mémoire
\nVérifiez que InputStream, Connection ou Session n'ont pas été oubliés. Utilisez try-with-resources :
try (Connection conn = getConnection();\n PreparedStatement stmt = conn.prepareStatement(sql)) {\n // travail\n} catch (SQLException e) {\n log.error("Erreur BDD", e);\n}\n\n\nLisibilité et style : le code comme un livre
\nLa checklist de code review inclut obligatoirement la lisibilité. Le code s'écrit une fois, se lit des dizaines de fois.
\nNombres et chaînes magiques
\n// MAUVAIS\nif (status == 3) { ... }\n// BON\nprivate static final int STATUS_COMPLETED = 3;\nif (status == STATUS_COMPLETED) { ... }\n\n