Herramientas de usuario

Herramientas del sitio


informatica:programacion:cursos:clean_code_aplicado_paradesarrollos_limpios_y_rentables:estilo_y_nombrado

Estilo y nombrado

Claridad con el menor esfuerzo

Si programamos para otras personas, tenemos que facilitar lo más posible el entendimiento de lo que hayamos escrito.

“Hay dos cosas difíciles en Informática: invalidar la caché y nombrar las cosas” – Phil Karlton

  1. Estilo y orden
  2. Tamaños y límites
  3. Definir con sustantivos: conceptos con los que tratamos
  4. Acciones con verbos: manipulación de los conceptos.

“El tiempo dedicado a la lectura es muy superior al de la escritura. Leemos código antiguo para escribir código nuevo. Facilitar la lectura facilita la escritura” – Robert C. Martin

Estilo y orden

“Cada línea de código debe parecer escrita por la misma persona, sin importar el número de participantes”.

Hay una serie de convenciones que hace que el código nos resulte agradable.

Características objetivas:

  • Sencillez
  • Armonía
  • Repetición

Belleza horizontal:

  • Sangría y llaves en bloques
  • Tamaño de las líneas

Belleza vertical:

  • Orden de las variables o propiedades
  • Orden de las funciones o métodos
    • revelador: públicos (al principio del fichero) → privados (al final)
    • newsletter / periódico: público → privados (métodos que dan soporte al método público) → público → privados

Belleza interna:

  • Separadores de listas e instrucciones
  • Espacios en las expresiones:
    • alrededor de los paréntesis
    • alrededor de los operadores
  • Delimitadores de cadenas

“Cuántas líneas en blanco seguidas realmente necesitas”

Tamaños y límites

Homogéneo, sin sobresaltos.

“No me gusta usar las barras de desplazamiento para leer tu código”.

Las reglas se basan en 3 principios casi psicológicos:

  • Decisión: vamos a establecer reglas (reunión de equipo).
  • Opción: vamos a fijar valores razonables.
  • Sentido: vamos a incumplirlas… pero a sabiendas.

“Define unas reglas y haz que se cumplan señalando lo que es incorrecto”.

Límites:

  • 80 - 120 caracteres por línea
  • 1 - 2 líneas en blanco seguidas
  • 100 - 200 líneas por fichero

Consistencia:

  • Mejor ser consistente con pocas normas…
  • … que cambiar de norma constantemente

Evita conflictos trasladando la decisión a otros:

  • Tabs VS spaces
  • Comillas simples o dobles
  • Posición de llaves, paréntesis, operadores…

Herramientas de limpieza:

Enlaces de referencia:

Definiciones con sustantivos

Expresa claramente una intención. Da sentido mediante los nombres.

Aquello con lo que trabajamos inicialmente son las variables, donde guardamos la información, el estado de nuestra aplicación.

Objetivo:

  • Claridad
  • Mostrar la intención
  • Explicar qué vamos a almacenar

Para variables / propiedades / constantes / clases:

  • Emplear siempre palabras completas y descriptivas.
  • Para que sean pronunciables y corregibles ortográficamente.
  • Vocabulario de entidades y propiedades de negocio.
  • Sin prefijos o sufijos técnicos.
  • Lo siento Harry, pero mejor sin magia.
int wtf = 42; # Not a good name

Ejemplo práctico

Partimos del siguiente código TypeScript:

export class client {
  regOn: Date; // ❌ complete pronounceable
  clientName: string; // ❌ redundant
  intBalance: number; // ❌ no technical prefix
  status = 2; // ❌ no magic number
  numberOfSupliedRequests: number; // ❌ same vocabulary
  clientOrders: object[]; // ❌ redundant
  processOrders(): void {
    this.clientOrders.forEach(o => {
      console.log('Start processing');
      console.log('processing things');
      console.log('Ended with' + o); // ❌ avoid mental mapping
    });
  }
}

Arreglado:

const ACTIVE = 2;
// ✔️ Bad nouns
export class Client {
  registeredOn: Date; // ✔️ complete pronounceable
  name: string; // ✔️ redundant
  balance: number; // ✔️ no technical prefix
  status = ACTIVE; // ✔️ no magic number
  numberOfSuppliedOrders: number; // ✔️ same vocabulary well spelled
  orders: object[]; // ✔️ redundant
  processOrders(): void {
    this.orders.forEach(order => {
      console.log('Start processing');
      console.log('processing things');
      console.log('Ended with' + order); // ✔️ avoid mental mapping
    });
  }
}

Acciones con verbos

Creamos un idioma para nuestro negocio.

“Expresa la lógica con verbos”.

Como queremos hacer una narrativa que exprese la intención de lo que hemos programado, necesitamos verbos para actuar. En nuestro idioma de negocio (una tienda, un blog, un videojuego…)

Objetivo: claridad, mostrar la intención.

Explica lo que vas a hacer:

  • Emplear siempre verbos que indiquen una acción.
  • Para que se lea como una historia.

Cortos y concretos en variables que actúan como flags: is, has, can, must

Obligatorios en funciones / métodos:

  • Vocabulario para relaciones y acciones.
  • Define listas permitidas para acciones comunes (y reducir así la variedad de verbos): get, set, read, write, select, insert.
  • Clarifica añadiendo sustantivos, adverbios o preposiciones.

Resumen:

  • Piensa en mí (en el siguiente “lector” / programador, que también puedes ser tú)
  • No me sorprendas.
  • No me hagas pensar.

Ejemplo práctico

Partimos del siguiente código que “huele”:

// ❌ Bad verbs
export class Client {
  pendingOrders: boolean; //❌ boolean verbs on flag variables
  lastOrderDate: Date;
  deferPayment: boolean; //❌ boolean verbs on flag variables
  //
  // Constructor
  //
  constructor() {
    this.pendingOrders = false;
  }
 
  // ❌ show intention
  pending(): object[] {
    return [];
  }
 
  // ❌ good names require no comment
  // Gets the orders by status
  getOrders(status: number): object[] {
    console.log('Getting by ', status);
    return [];
  }
 
  // ❌ return what is expected
  credit(): boolean {
    if (this.isVIP || this.deferPayment) return true;
  }
 
    // ❌ same verb for same action
  selectLastOrder(): object {
    return {};
  }
 
  // ❌ return what is expected
  isActive(): string {
    if (this.pendingOrders || this.isVIP) {
      return 'ACTIVE';
    } else {
      return 'INACTIVE';
    }
  }
  // ❌ vertical declaration order
  isVIP: boolean;
}

Lo mejoramos:

// ✔️ Bad verbs
export class Client {
  hasPendingOrders: boolean; //✔️ boolean verbs on flag variables
  lastOrderDate: Date;
  canDeferPayment: boolean; //✔️ boolean verbs on flag variables
  // ✔️ vertical declaration order
  isVIP: boolean;
  //
  // Constructor
  //
  constructor() {
    this.hasPendingOrders = false;
  }
 
  // ✔️ show intention
  getPendingOrders(): object[] {
    return [];
  }
 
  //✔️ good names require no comment
  // Gets the orders by status
  getOrdersBy(status: number): object[] {
    console.log('Getting by ', status);
    return [];
  }
 
  // ✔️ return what is expected
  hasCredit(): boolean {
    if (this.isVIP || this.canDeferPayment) return true;
  }
 
  // ✔️ same verb for same action
  getLastOrder(): object {
    return {};
  }
 
  // ✔️ return what is expected
  getActiveStatus(): string {
    if (this.hasPendingOrders || this.isVIP) {
      return 'ACTIVE';
    } else {
      return 'INACTIVE';
    }
  }
}  
informatica/programacion/cursos/clean_code_aplicado_paradesarrollos_limpios_y_rentables/estilo_y_nombrado.txt · Última modificación: por tempwin