Código limpio

En una suite empresarial, donde entran en juego muchos dominios e incluso muchas más  manos, hay que poner siempre unas reglas de escritura al código fuente de la aplicación. Esto se traduce en escribir código limpio o «clean code» en inglés.

Seguramente hay escritas numerosas normas para que cualquier persona que lea el código pueda rápidamente identificar si lo que está leyendo es una propiedad, un método, si es público, privado, o cuales son sus dependencias, entre otras.

Estas que voy a comentar son unas más a las muchas que hay y quizás puedan ayudar, aunque prácticamente es usar un poco el sentido común para terminar teniendo código limpio.

Las reglas que leerás muchas están extraídas de la guía de estilo de angular.

Importaciones

Básicamente lo primero que se ve un cualquier archivo de angular son los “imports”. Pueden llegar a ser bastantes (en esa clase hay demasiadas dependencias y por lo tanto muy propensa a la refactorización con lo que tendríamos que pensar en SOLID) y siempre deberían de tener un cierto orden.

El orden podría ser el siguiente:

  1. Imports del núcleo de la aplicación o que consideres como tal (angular, rxjs, …).
  2. Imports de terceros (externas).
  3. Imports otros dominio (si las hay).
  4. Imports de tu dominio de ámbito común (usado por varios módulos).
  5. Imports de tu dominio del propio módulo.

Como veremos más adelante el orden debería mantenerse en el constructor de la clase para mantener coherencia.

Ejemplo (versión ampliada):

import { Component, OnInit } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

//Third parties *********************************************************************
//BOOTSTRAP
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';

//Suite domains *******************************************************************
//ARQ
import { SuperService } from ‘arq’;
//TECH
import { FocusService, SearchService } from ‘tech’;

//MyDomain ************************************************************************
//FOO
//MyCommonServices
import { ModelService } from ‘../../../services/model.service’;
//MyParticularServices
import { DataService } from ‘./data.service’;
//Entities
import { IModel } from ‘../../../models/iModel’;

Quizás sea demasiado extensa  y se podría abreviar poniendo directamente el nombre del tercero o dominio:

import { Component, OnInit } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

//BOOTSTRAP
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';

//ARQ
import { SuperService } from ‘arq’;
//TECH
import { FocusService, SearchService } from ‘tech’;

//FOO
//Services
import { ModelService } from ‘../../../services/model.service’;
import { DataService } from ‘./data.service’;
//Entities
import { IModel } from ‘../../../models/iModel’;

Independientemente de poner el origen del «import» con los comentarios, lo que realmente importa es el orden en que se realiza la importación.

Convención de nombres (Naming conventions)

Ante la necesidad siempre de dar un nombre a un elemento (clase, método, variable, …) siempre se ha de llamar de una forma que se entienda lo que representa, por lo tanto no valen abreviaciones o atajos que valgan. Aquí van algunas reglas:

  1. Nombre descriptivo (no abreviaciones).
  2. Utilizar Palabras enteras en el nombre.
  3. Usar camelCase en los nombres de: objetos, métodos, instancias, constantes y propiedades de los objetos.
  4. Usar PascalCase en los nombres de: clases, módulos, interfaces y enumeraciones.

Los nombres de los ficheros en camelCase con sufijos:

  • Module: xxx.module.ts
  • Component: xxx.component.ts
  • Service: xxx.service.ts
  • Pipe: xxx.pipe.ts
  • Directive: xxx.directive.ts

En los tests con el sufijo ‘spec’:

  • xxx.service.spec.ts

Modificadores de acceso

En typescript si no se indica el tipo de modificador de acceso se toma por defecto el modificador ‘public’. No obstante, se puede poner de forma explícita según las situaciones.

¿Por qué ponerlo en algunas situaciones? Pues por ejemplo para una mejor comprensión del código para todos aquellos desarrolladores que vengan de otros lenguajes de programación. Si un programador ha estado trabajando en C#, sabe que los modificadores que se aplican por defecto son ‘las más restrictivas que se pueden declarar para un miembro’, así que por ejemplo en las clases si no se pone nada es de tipo ‘internal’ (o ‘private’ si está dentro de otra clase), los métodos son ‘private’, etc. y si ve código en typescript sin modificadores puede interpretarlo erróneamente.

Estructura de una clase

Después de tener las importaciones se escribe la clase (‘class’) (y una clase por archivo).

Esta clase deberá seguir la convención de nombres y puede seguir la siguiente estructura:

  1. Variables/constantes privadas
  2. Constructor (poniendo los parámetros en el mismo orden que los ‘imports‘)
  3. Implementación de los métodos de las interfaces.
  4. Resto de código.
export class ExampleComponent implements OnInit {
    private _message: number = 0;
    private _cancel: boolean = false;
 
    public constructor(
	//BOOTSTRAP
        private _bsModalService: BsModalService,
        //ARQ
        private _superService: SuperService,
        //TECH
        private _focusService: FocusService,
        private _searchService: SearchService,
        //FOO
        private _modelService: ModelService, 
        private _dataService: DataService) {
    }

    public ngOnInit(): void {
         
    }

    public doStuff(): void {
     
    }

Variables y constantes

Para los strings, se tiene que seleccionar o bien la comilla simple (‘) o las comillas dobles (“). Es decir, en todo el código tiene que existir esta homogeneidad. No puede ser que dentro de un proyecto (o solución inclusive) a veces se use de una u otra manera sin ninguna norma establecida.

Utilizar template strings cuando se pueda. Sintácticamente se usa el caracter de acento abierto (backticks) (`) básicamente por dos motivos:

  • String Interpolation. Usado para generar otra cadena combinando otras cadenas de texto con variables, … sin necesidad de usar el operador de suma (+) por ejemplo:
let myVariable: string = ‘very simple’;
let text: string = `my text is ${myVariable}`;

Usando el operador ‘+’ hubiéramos puesto:

let text: string = ‘my text is ‘ + myVariable;
  • Multilínea: Permite tener una definición de string en varias líneas.
let multiText: string = `one line
other line`;

Iteradores

Antes de usar un for, mejor siempre buscar una alternativa sobre la acción que deseamos sobre un vector (‘array‘) utilizando .map, .filter, .forEach …

Bloques de acciones

Siempre utilizar las llaves ({}) para declarar un bloque de acciones (clases, métodos, …). Aunque solamente exista una acción ponerlo entre llaves. Por ejemplo:

public simpleAction(age: number): number {
	return age * 2;
}

Si por ejemplo no existen acciones (por ejemplo en un constructor las llaves se ponen una debajo de la otra.

public constructor(private _myService: myService) {
}

Resumiendo

Como vemos, es una buena práctica (‘best practice‘) aplicar siempre el código limpio sobre lo que escribamos para poder entender mejor el código, así de simple.

Seguramente habrán muchas más normas para aplicar, pero estas reglas descritas son bastante relevantes para ponerlas en práctica.

Si en algún momento te enfrentas a un refactor, intenta siempre aplicar estas reglas y no olvides de dejar el código mejor de lo que lo encontraste 🙂

Deja un comentario

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