Clean Code – una guía rápida

Existen dos tipos de desarrolladores, los que programan y los que programan bien.

Todos sabemos programar, al fin y al cabo nos han enseñado que para llegar a una solución hay muchos caminos. Incluso el peor código posible es capaz de darnos la resolución al problema.

Es hora de adentrarse en el camino de baldosas amarillas, es hora de Programar Bien.

A continuación dejo una serie de pautas a tener en cuenta para entrar de lleno en el mundo del Clean Code. A modo de cheat sheet, graba estas ideas en tu mente, cuélgalas de tu tablón en la oficina, ponlas en la nevera de casa, haz con ella lo que quieras, pero tenlas en cuenta siempre a la hora de desarrollar.

Consideraciones generales a tener en cuenta sobre tu código:

  • Hace UNA COSA y la hace BIEN
  • Es SIMPLE y directo
  • No está duplicado
  • Se puede leer
  • Piensa en tí como un escritor
  • Programar es un arte, un trabajo de artesanía
  • Tu código te importa
  • Es bonito
  • Deja el código más limpio de como lo encontraste
  • Mejora tu código con la práctica

 

Creando buenos nombres
  • Un nombre debe responder todas las preguntas
  • Debe revelar su intención
  • Debe tener significado
  • Debe ser pronunciable
  • Se debe poder buscar dentro del código
  • Los nombres de una letra SÓLO como variables locales en métodos cortos
  • Los nombres de las clases deben ser SUSTANTIVOS en singular
  • Los nombres de los métodos deben ser VERBOS
  • Usar siempre sólo una palabra por concepto (no usar get y fetch para hacer lo mismo)
  • Evitar usar la misma palabra para diferentes propósitos
  • No usar prefijos en nombres de clases (GSD_Address)

MAL:

class Wizards {
   let m:Int //mana available
   let typmgc:String //type of magic wizard use
   var l:Int //lives

   func lose(x:Int) {
      self.l -= x
   }
   ...
}

BIEN:

class Wizard {
   let manaAvailable:Int
   let typeOfMagic:String
   var lives:Int

   func loseLives(livesLost:Int) {
      self.lives -= livesLost
   }
   ...
}

 

Clean Code en Funciones
  • Una función debe hacer UNA COSA. Y la debe hacer BIEN
  • El control de errores ya es UNA COSA
  • Deben ser pequeñas (de 1 a 5 líneas máximo)
  • Con nombre descriptivo que indica lo que hace
  • No más de 3 argumentos
  • Si requiere más de 3 argumentos, usa una clase
  • Lo ideal son 0 argumentos
  • No usar argumentos de salida, usar returns
  • Sólo un nivel de abstracción
  • Usar excepciones, no devolución de códigos de error
  • Estructuras if, else, where … con sólo una línea (llamada a otra función)

MAL

class Wizard {
   let manaAvailable:Int
   let typeOfMagic:String
   var lives:Int

   func castSpell(name:String, manaRequired:Int, lifeCost:Int) {
      if manaRequired <= self.manaAvailable {
         print("Spell \(name) casted")
         self.lives -= lifeCost
         if self.lives <= 0 {
            print("You lost the game")
         }
      } else {
         print("Spell \(name) failed")
      }
   }
   ...
}

BIEN:

class Spell {
   let name:String
   let manaRequired:Int
   let lifeCost:Int

   func cast(manaUsed:Int) -> Bool {
       if self.manaRequired <= manaUsed {
           print("Spell \(self.name) casted")
           return true
       } else {
           print("Spell \(self.name) failed")
           return false
       }
   }
   ...
}

class Wizard {
   let manaAvailable:Int
   let typeOfMagic:String
   var lives:Int

   func castSpell(spell:Spell) {
       if spell.cast(manaUsed:self.manaAvailable) {
           self.loseLives(livesLost:spell.lifeCost)
       }
   }
 
   func loseLives(livesLost:Int) {
       self.lives -= livesLost
       self.checkDeath()
   }
 
   func checkDeath() {
       if self.lives <= 0 {
           print("You lost the game")
       }
   }
   ...
}

 

Clean Code y los Comentarios
  • NO hacen falta. Exprésate usando el código
  • Son difíciles de mantener
  • Los comentarios mienten (pueden referirse a una situación anterior)
  • La verdad sólo está en el código
  • Usar comentarios sólo para situaciones de Warnings o To-Do

MAL:

   //check if the wizard is dead
   func dead() {
      //if wizard's lives are below 0, wizard dies and lost the game
      if self.lives <= 0 { 
         print ("You lost the game") //print message
      }
   }
   //function ends

BIEN:

   func checkDeath() {
       if self.lives <= 0 {
           print("You lost the game")
       }
   }

 

Clean Code en Clases
  • NO exponer detalles de las Clases
  • Usar abstracciones
  • NO usar getters y setters para todas las propiedades
  • No todas las propiedades tienen que ser públicas
  • Los objetos ESCONDEN sus datos y EXPONEN sus métodos
  • Las estructuras de datos EXPONEN sus datos y no tienen comportamientos
  • Evitar híbridos, mitad objetos mitad estructura de datos

 

Formato de código
Vertical
  • Ficheros pequeños (pocas líneas por fichero)
  • El nombre del fichero debe ser explicativo
  • Usar saltos de líneas en blanco para separar conceptos
  • Declarar variables cerca de donde van a ser usadas
  • En funciones, declarar variables en la parte superior
  • Las propiedades de las clases en la parte superior
  • Mantener cerca las funciones que llaman a otras funciones
  • La función llamadora antes de la función llamada
  • Mantener cerca funciones de concepto similar
Horizontal
  • Mantener líneas cortas, no más de 120 caracteres
  • Evitar scroll hacia la derecha
  • Separar operadores con espacios en blanco ( a = b + c )
  • Mantener juntos el nombre de la función con su paréntesis ( callFunction(parameter) )
  • Usar sangría en cada ámbito
  • Usar apertura de llave de ámbito al final de la línea ( if a == b { )
  • Separar argumentos en funciones con espacios tras coma ( print(a, b, c) )

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *