7 puanteurs de code que tout développeur doit éviter

Pragmatic Nerdz
Nov 15, 2023 - 4 Minutes

Si vous codez comme un porc, vous allez créer du code qui fonctionne mais qui va dégager des odeurs nauséabondes qui indiquent des problèmes potentiels dans votre application. Il est donc important de reconnaître les modèles de code qui causent ces puanteurs. 

Any fool can write code that a computer can understand. Good programmers write code that humans can understand

Martin Fowler

Les superflues

Les puanteurs superflues sont des ajouts inutiles, dont l'absence rendrait le code plus propre, efficace et facile à comprendre.

1. Les commentaires

Les commentaires sont souvent ajoutés avec de bonnes intentions pour clarifier du code incompréhensible. Les commentaires sont utilisés comme un désodorisant pour masquer la mauvaise odeur du code.

Au lieu de rajouter des commentaires, re-écrivez plutôt votre code pour qu'il soit facile à comprendre, en déplaçant les blocs de code commentés dans des fonctions dont le nom est inspiré du commentaire.

Code puant

class ReportGenerator {
  fun run(){
     // Create the report
     val template = loadReportTemplate(...)
     val data = loadReportData(...)
     val report = merge(template, data)

     // Send the report
     val email = createEmailMessage(report)
     sendEmail(email)
  }
}

Solution

class ReportGenerator {
  fun run(){
     val report = createReport()
     sendReport(report)
  }

  private fun generateReport() {
     val template = loadReportTemplate(...)
     val data = loadReportData(...)
     val report = merge(template, data)
     return report
  }

  private fun sendReport(report){
     val email = createEmailMessage(report)
     sendEmail(email)
  }
}

2. Peur de l'échec

Cette puanteur apparaît lorsqu'une méthode retourne un statut en cas d'erreur, ce qui force le code appelant à toujours vérifier si une erreur qui est survenue lors de l'appel.

Il faut plutôt fail fast en cas d'erreur et lever une exception.

Code puant

fun save(request: CreateUserRequest): CreateUserResponse {
   val response = http.post('/v1/users', request)
   if (response.statusCode != 200){
      return CreateUserResponse(success=false) 
   } else {
      return CreateUserResponse(success=true, userId=response.body.userId) 
   }
}
...

val response = save(request)
if (response.success){
   // Handle failure
   ...
} else {
   ...
}

Solution

fun save(request: CreateUserRequest): CreateUserResponse {
   val response = http.post('/v1/users', request)
   if (response.statusCode != 200){
      throw Exception(...)
   }
   return CreateUserResponse(userId=response.body.userId) 
}
...

val response = save(request)
...

Les ballonnements 

Les ballonnements sont des puanteurs où des fragments de code, des méthodes et des classes qui ont atteint des proportions si gargantuesques qu'il est difficile de travailler avec eux.

3. Expression booléenne compliquée

Avoir des expressions if - else ayant plusieurs conditions et combinaisons de AND, OR ou NOT rend le code difficile à comprendre.

Il faut plutôt extraire les conditions dans des fonctions, car il est plus facile de lire des mots déclaratifs que de calculer des instructions logiques.

Code puant

fun archive(event: Event){
  if (event.endDate != null && event.endDate > today && event.ageInYears > 8){
    ...
  }
}

Solution

fun archive(event: Event){
  if (canArchive(event){
    ...
  }
}

private fun canArchive(event: Event){
  return event.endDate != null && event.endDate > today && event.ageInYears > 8
}

4. Longue liste de paramètres

Cette puanteur apparaît lorsque vous avez des fonctions qui ont plus que quatre à cinq paramètres, ce qui rend le code plus difficile à comprendre.

Receive my Stories your e-mail inbox as soon as I publish them.
Subscribe to my Blog

On peut simplifier le code en regroupant plusieurs paramètres dans une classe, et ainsi réduire le nombre de paramètres en passant un objet à la fonction.

Code puant

class UserService{
  fun updateUser(
    userId: Long,
    street1: String,
    street2: String,
    city: String,
    zipCode: String,
    country: String
  ): Double {
    ...
  }
}

Solution

class Address{
  street1: String
  street2: String
  city: String
  zipCode: String
  country: String
}

class UserService{
  fun updateUser(
    userId: Long,
    address: Address
  ): Double {
    ...
  }
}

Les coupleurs

Les coupleurs sont les puanteurs qui contribuent à un couplage excessif entre les classes

5. Envie de fonctionnalités

Cette puanteur apparaît lorsqu'une méthode accède aux données d’un autre objet plus qu’à ses propres données.  Dans ce cas, il faut déplacer la méthode dans l'autre classe.

Code puant

class Phone{
  val number: String

  fun areaCode(): String {
    return number.substring(0, 3)
  }
  fun prefix(): String {
    return number.substring(3, 6)
  }
  fun localNumber(): String {
    return number.substring(6)
  }
}

class Customer {
   val phone: Phone

   fun phoneNumber(): String{
     return "(" + phone.areaCode() + ") " +
        phone.prefix() + "-" +
        phone.localNumber()
   }
}

Solution

class Phone{
  val number: String

  fun areaCode(): String {
    return number.substring(0, 3)
  }
  fun prefix(): String {
    return number.substring(3, 6)
  }
  fun localNumber(): String {
    return number.substring(6)
  }

   fun formattedNumber(): String{
     return "(" + areaCode() + ") " +
        prefix() + "-" +
        localNumber()
   }
}

class Customer {
   val phone: Phone

   fun phoneNumber(): String {
     return phone.formattedNumber()
   }
}

6. Intimité inappropriée

Cette puanteur apparaît lorsqu'une méthode accède aux champs ou méthodes internes d'une autre classe.

Code puant

class Address{
   street: String
   city: String
   country: String
}

class Job {
   address: Address
}

class Candidate {
   job: Job

   fun printJobAddress(){
      println(job.address.street)
      println(job.address.city)
      println(job.address.country)
   }
}

Solution

class Address{
   street: String
   city: String
   country: String

   fun print(){
      println(street)
      println(city)
      println(country)
   }

}

class Job {
   address: Address

  fun printAddress(){
    address.print()
  }
}

class Candidate {
   job: Job

   fun printJobAddress(){
      job.printAddress()
   }
}

Autres

7. Les nombres magiques

Les nombres magiques et les valeurs codées en dur et utilisées dans des expressions, instructions ou paramètres. Ils rendent le code difficile à comprendre et maintenir.

Remplacer les nombre magiques par des constantes car elles ajoutent de la sémantique au code et augmentent la lisibilité.

Code puant

class PriceCalculator{
  fun computeTotal(subTotal: Double): Double {
    val total = subTotal + 450
    return total + total * .020
  }
}

Solution

class PriceCalculator{
  const SHIPPING_FEES = 450
  const SALES_TAX = .020

  fun computeTotal(subTotal: Double): Double {
    val total = subTotal + SHIPPING_FEES
    return total + total * SALES_TAX
  }
}

Si vous voulez en apprendre plus sur les puanteur de code je vous recommande Refactoring Guru qui contient d'excellentes ressources

Si vous avez aimé l'article, montrez votre soutien avec un ❤️ et abonnez vous a mon blog! Votre engagement m’inspire!

Clean Code
Code Smell