Lista de Revisión de Código Angular: Todos los pasos incluidos

Todos nos esforzamos por crear aplicaciones seguras, mantenibles y de alta calidad. Tanto si está preparando un lanzamiento repleto de características como si está escalando su producto para una audiencia más amplia, las revisiones exhaustivas del código de Angular son fundamentales. ¿Por qué? Porque ayudan a descubrir problemas ocultos, a mantener un estilo de código uniforme y a mantener el flujo de desarrollo por buen camino.

En este artículo, cubriremos:

Por qué la revisión de código es importante para Angular

Angular tiene una estructura modular impulsada por TypeScript, que ya elimina muchos de los dolores de cabeza que tendrías en JavaScript normal. Incluso con esta ayuda extra, no significa que puedas saltarte las revisiones de código. Un «any» desviado, una brecha de seguridad pasada por alto o una arquitectura torpe pueden crear grandes problemas. Una revisión a fondo te ayudará:

  • Mantenga su código coherente y fácil de navegar
  • Detecte los problemas de rendimiento antes de que aumenten la factura del servidor.
  • Refuerce la seguridad, especialmente en torno a las entradas generadas por el usuario
  • Promueva un flujo predecible de datos y lógica

Si buscas aún más consejos sobre por qué son importantes las revisiones de código, deberías consultar nuestras otras listas de comprobación para Python, JavaScript y Seguridad.

Arquitectura clara del proyecto

Un proyecto Angular bien estructurado conduce a menos conflictos de fusión y una experiencia de incorporación más suave para los nuevos desarrolladores. Al separar las características en módulos, decidir cuáles se cargan de forma perezosa y mantener los nombres de archivo lógicos, se prepara el terreno para un mantenimiento y una escalabilidad sencillos.

Módulos de funciones:

  • Agrupe funcionalidades relacionadas en módulos de características dedicados para evitar la sobrecarga de su módulo principal y mantener su código detectable
  • Utilice módulos compartidos para directivas y componentes necesarios para múltiples funciones
  • Supervise sus configuraciones de enrutamiento para ver dónde la carga lenta puede aumentar el rendimiento
// Naive routing: everything is loaded at once, which makes the final bundle bigger
const routes: Routes = [
  { path: 'dashboard', component: DashboardComponent },
  { path: 'profile', component: ProfileComponent },
  // ...
];

// With lazy loading, only fetch modules on demand
const routes: Routes = [
  {
    path: 'dashboard',
    loadChildren: () => import('./dashboard/dashboard.module')
      .then(m => m.DashboardModule)
  },
  {
    path: 'profile',
    loadChildren: () => import('./profile/profile.module')
      .then(m => m.ProfileModule)
  }
];

Organización lógica de las carpetas:

  • Asigne a cada carpeta un propósito claro (componentes, servicios, tuberías, etc.) para evitar enterrar archivos en ubicaciones aleatorias
  • Nombra las carpetas según su funcionalidad (por users, products, reports), no con términos abstractos como misc o general

Versionado y CI/CD adecuados:

  • Etiqueta las versiones en Git y automatiza las comprobaciones de compilación. Esto garantiza que el nuevo código se fusione correctamente y que cualquier cambio arquitectónico se pruebe antes
  • Identifique rápidamente los posibles conflictos con una sencilla canalización CI que ejecute ng build –prod junto con comprobaciones de lint

Convenciones de codificación coherentes

Las reglas de estilo pueden parecer cosméticas, pero un estilo consistente aumenta la productividad. Herramientas como Angular ESLint y Prettier automatizan la mayor parte del trabajo, mientras que un esquema de nomenclatura estándar mantiene su aplicación uniforme.

Reglas de formato y Lint unificadas:

  • Acuerda una guía de estilo (por ejemplo, la Guía de Estilo de Angular) para que los desarrolladores no pierdan tiempo en cambios cosméticos
  • Automatice las correcciones con Prettier o ESLint. Incluso puede ejecutarlos como un gancho pre-commit para mantener limpio el repositorio. Eche un vistazo a este breve ejemplo de configuración de ESLint, que puede ampliarse fácilmente con docenas de plugins y reglas personalizadas:
{
  "root": true,
  "overrides": [
    {
      "files": [
        "*.ts"
      ],
      "parserOptions": {
        "project": [
          "tsconfig.json",
          "e2e/tsconfig.json"
        ],
        "createDefaultProgram": true
      },
      // Can add ready-to-go config of Airbnb or others styleguides
      "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:@angular-eslint/recommended",
        "plugin:@angular-eslint/template/process-inline-templates"
      ],
      "rules": {
        // ...
      }
  }]
}

Nombres significativos:

  • Utiliza variables descriptivas y nombres de funciones y evita marcadores de posición cortos como val o tmp.Angular favorece la claridad
  • Aplica nombres coherentes a clases, archivos y directorios. Por ejemplo, user-profile.component.ts or auth.service.ts indican mejor la intención que data.component.ts or logic.service.ts.

Funciones legibles:

  • Los métodos deben ser breves y útiles. Si estás abordando varias tareas en una función, divídela en partes lógicas
  • Lo mismo se aplica a clases enteras: cuando un servicio empieza a funcionar como una biblioteca de utilidades, es hora de dividirlo

Tipado estricto y uso de TypeScript

Uno de los puntos fuertes de Angular es TypeScript, que detecta errores a tiempo y hace que el flujo de datos sea explícito. El uso excesivo de “any” anula estos beneficios y convierte la depuración en conjeturas.

Aprovecha las interfaces:

  • Define estructuras de datos para saber exactamente qué entra y sale de tus funciones
  • Si estás devolviendo información de User, crea una interfaz de usuario para ello

He aquí un ejemplo rápido de cómo la tipificación va mal sin una definición adecuada:

// Bad practice: using `any` everywhere, there is spelling error, which is not catched
function submitForm(event: any): any {
  event.preventDefaulr(); // runtime error!
  // ...
  return fetch(`https://api.example.com/users/${id}`)
    .then(res => res.json());
}


// Good practice: using interfaces gives ability to avoid common errors and easily access properties
function submitForm(event: MouseEvent | Keyboard): any {
  event.preventDefault();
  const isShiftKeyPressed = event.shiftKey;
  // ...
  return fetch(`https://api.example.com/users/${id}`)
    .then(res => res.json());
}

Utilice el modo estricto:

  • Active «strict» en su tsconfig.json para simplificar la detección de errores tipográficos sutiles. Esta es una de las formas más rápidas de aumentar la fiabilidad de su código

Genéricos cuando sea apropiado:

  • Utilice clases o métodos genéricos sólo si es necesario; evite tipos simples demasiado complicados
// Bad practice: Not constraining generics 
class BadDataService {
    process(data: T): T {
        return data; // No type safety or validation
    }
}

// Good practice: Using type inference and constraints
function transformAndValidate>(
    input: T,
    transform: (data: T) => R,
    validator: (data: R) => boolean
): R | null {
    const transformed = transform(input);
    return validator(transformed) ? transformed : null;
}

Componentes y plantillas

La estructura basada en componentes de Angular facilita la división de la interfaz de usuario, pero los componentes de gran tamaño pueden resultar engorrosos. Distribuye la lógica de negocio en servicios y plantillas limpias de bucles o cálculos pesados.

Ganchos de ciclo de vida bien hechos:

  • Implementa sólo los ganchos que realmente necesites. Los ganchos no utilizados añaden desorden y confusión. Por ejemplo, desuscríbete de observables en ngOnDestroy() si te estás suscribiendo manualmente
  • No olvides usar la interfaz correcta en el componente

Limite la lógica de la plantilla:

  • Una plantilla inundada de bucles anidados y condiciones es difícil de depurar. Para solucionar esto, mueva las transformaciones repetidas a una tubería o método en la clase del componente
  • Mantenga su HTML legible aprovechando sabiamente las directivas Angular como ngIf y ngFor

Refactoriza componentes sobredimensionados:

  • Si un componente ha crecido cientos de líneas, es hora de dividirlo
  • Para mantener tu componente principal centrado, cambia el procesamiento de datos a un servicio o subcomponente

Inyección eficaz de dependencias

La inyección de dependencia es un sello distintivo de Angular, pero es fácil abusar de ella. Demasiados proveedores en el nivel raíz hincharán tu aplicación, y los singletons pueden causar efectos secundarios ocultos si están en el estado de almacén inesperadamente.

Ámbito de servicio:

  • Proporciona un servicio en el ámbito raíz sólo si estás seguro de que se utiliza en toda la aplicación. Además los singletons son geniales para la optimización ya que se incluyen en el tree-shaking (no olvides eliminar todos los enlaces directos a singleton)
  • Si no, decláralo en un módulo específico para limitar su alcance. Este enfoque también evita singletons involuntarios cuando sólo necesita instancias de servicio localizadas

Evite los vertederos:

  • Mantenga los servicios con un propósito: no combine utilidades aleatorias o lógica inconexa en un único servicio
  • Organice el código por funcionalidad: autenticación, perfiles de usuario, análisis, etc

Gestión de estados:

  • Utilice un servicio para almacenar el estado global sólo después de una cuidadosa consideración
  • Adoptar una biblioteca de gestión de estado formal como NgRx para aplicaciones más grandes; es más predecible y fácil de probar

Gestión de estados y flujo de datos

Los patrones de flujo de datos pueden hacer o deshacer tu proyecto Angular. Incluso si tu aplicación es pequeña ahora, un manejo de datos inconsistente podría llevar a una refactorización mayor en el futuro.

Patrones predecibles:

  • Elige un enfoque de gestión de estados (NgRx, patrones basados en sujetos de comportamiento o un enfoque más simple de servicio de almacenamiento) y cíñete a él
  • No cambies de patrón a mitad de proyecto porque puede causar confusión

Actualizaciones inmutables:

  • Mantenga los datos inmutables. Evita mutar arrays u objetos in situ para evitar problemas extraños con la detección de cambios de Angular
  • Crea nuevos objetos en lugar de modificar los existentes
// Bad practice
export class ListComponent {
  @Input() list: Todo[] = [];

  // Bad: Directly mutating input array
  toggleListCompletion(item: ListItem): void {
    todo.completed = !todo.completed; // Change detection might miss this!
  }
}


// Good practice
export class ListComponent {
  @Input() list: ListItem[] = [];
  @Output() listChange = new EventEmitter();

  // Good: Creating new array with modified item
  onToggleListItem(listItem: ListItem): void {
    const updatedList = this.list.map(item => 
      item.id === listItem.id 
        ? { ...item, completed: !item.completed }
        : item
    );
    this.listChange.emit(updatedList);
  }
}

Limpieza de suscripciones:

  • Utiliza tuberías asíncronas en las plantillas siempre que sea posible para que Angular gestione los ciclos de vida de las suscripciones por ti
  • Si se suscribe manualmente, recuerde cancelar la suscripción en ngOnDestroy()

Optimización del rendimiento

A nadie le gusta una aplicación lenta. Las optimizaciones integradas de Angular ayudan, pero puedes hacer más para reducir los tiempos de carga y mantener la UI responsive.

Carga perezosa:

  • No cargues todas las características por adelantado: esto empantana la experiencia inicial
  • Carga de forma perezosa tus módulos para que los usuarios sólo obtengan lo que necesitan. Además, utiliza una estrategia de precarga personalizada para mejorar aún más la experiencia del usuario

Echa un vistazo a este ejemplo de una gran aplicación que implementó una estrategia de precarga personalizada para equilibrar el tiempo de carga inicial con la velocidad de navegación:

// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';

const routes: Routes = [
  {
    path: 'dashboard',
    loadChildren: () => import('./dashboard/dashboard.module')
      .then(m => m.DashboardModule),
    data: { expectedRole: 'manager' }
  },
  {
    path: 'settings',
    loadChildren: () => import('./settings/settings.module')
      .then(m => m.SettingsModule),
    data: { expectedRole: 'superuser' }
  },
  // ...
];

// Custom preloading strategy which checks user role 
import { Injectable } from '@angular/core';
import { PreloadStrategy, Route } from '@angular/router';
import { Observable, of } from 'rxjs';
Import { RolesManagementService} from 'services/roles-management.service';

@Injectable({ providedIn: 'root' })
export class CustomPreloadStrategy implements PreloadStrategy{

  constructor(
    private rolesManager: RolesManagementService
  ) {}

  preload(route: Route, load: () => Observable): Observable {
    return this.rolesManager.hasRole(route.data.expectedRole).pipe(
        switchMap(hasRole => hasRole ? load() : of(null)),
      );
  }
}

Detección OnPush:

  • Utilice ChangeDetectionStrategy.OnPush para componentes que dependen de datos inmutables y observables para reducir comprobaciones innecesarias, especialmente en grandes componentes complejos (tablas, formularios) y actualizaciones de datos en tiempo real
  • Realice un perfil de su aplicación para comprobar si OnPush está reduciendo realmente las repeticiones de la reproducción y resalte los componentes que más se benefician de ello

Recorte de dependencias:

  • Analice package.json con regularidad para identificar las bibliotecas grandes que no necesita. Incluso una sola biblioteca pesada puede inflar el tamaño del paquete
  • Elimine o sustituya las dependencias que se utilicen raramente (o que puedan replicarse con métodos nativos) para que su compilación sea más pequeña y eficiente

Principios de seguridad

Angular ofrece defensas integradas como la desinfección del DOM, pero aún así debes revisar tu aplicación en busca de amenazas potenciales. Ignorar la validación de entrada del usuario o el registro de información sensible puede conducir a violaciones de datos.

Prevenir ataques XSS:

  • Utiliza la desinfección por defecto de Angular para URLs, HTML y estilos. No te saltes esto a menos que sepas exactamente por qué
  • Evita las llamadas directas innerHTML o bypassSecurityTrustHtml a menos que estés absolutamente seguro de que los datos son seguros

Credenciales ocultas:

  • Nunca guarde claves API o tokens privados en su código fuente
  • Compruebe los archivos de entorno, los registros de la consola y las sentencias de depuración en busca de fugas

Análisis de dependencias:

  • Supervise y actualice los paquetes de terceros obsoletos; pueden exponer toda su aplicación
  • Herramientas como npm audit o SonarQube detectan vulnerabilidades para que pueda parchearlas con antelación
  • Integre comprobaciones automatizadas en su proceso CI/CD, bloqueando fusiones si aparecen vulnerabilidades críticas

Pruebas exhaustivas

Un conjunto de pruebas sólido detecta las regresiones antes de que lleguen a producción. Cubra sus componentes, servicios y lógica de enrutamiento, centrándose primero en las rutas críticas.

Pruebas unitarias:

  • Utiliza el TestBed de Angular para los componentes, centrándose en cómo interactúan con los servicios y la entrada del usuario
  • Para los servicios, prueba cada método a fondo, simulando llamadas de red o dependencias externas para aislar la lógica

Pruebas de integración y E2E:

  • Utilice marcos de trabajo como Cypress o Protractor (tenga en cuenta el modo de mantenimiento de Protractor) para simular flujos de usuario reales y asegurarse de que todo funciona a la perfección
  • Escriba pruebas para recorridos de usuario clave, como la inscripción, el pago y la gestión de perfiles, para descubrir problemas que podrían no surgir en pruebas unitarias aisladas

Cobertura significativa:

  • Un porcentaje de cobertura es sólo un número. Es necesario comprobar que las pruebas verifican realmente el comportamiento y no se limitan a pasar líneas de código
  • Centrarse en la calidad más que en la cantidad. Es mejor tener menos pruebas, más significativas, que cubran la lógica crítica y los casos extremos, que un gran número de pruebas superficiales que sólo inflan las estadísticas de cobertura

Su socio Angular: Servicios de desarrollo y auditoría

Llevamos utilizando Angular desde sus inicios, ofreciendo soluciones a medida para empresas tecnológicas de todo el mundo.

En el caso de nuestro cliente C!A, utilizamos Angular para construir un front-end robusto para su web-app Current. Current es un sistema de prestación de servicios públicos utilizado por funcionarios de más de 10 agencias estatales y de condado de EE.UU. para gestionar miles de solicitudes de servicios en todo el país. Si quieres saber más, echa un vistazo al caso práctico.

Nuestro trabajo con CDP Blitz consistió en refactorizar la lógica compleja en componentes y servicios sencillos, aumentar la estabilidad, reducir los tiempos de carga de las páginas y detectar los cuellos de botella ocultos desde el principio.

Mientras tanto, con PageFreezer -una solución de cumplimiento y archivo digital- ayudamos a integrar la gestión avanzada de permisos de usuario, perfeccionar los flujos de trabajo de archivo de datos e introducir pruebas sistemáticas para mantener alta la calidad del código bajo grandes cargas de datos. No dude en consultar el caso práctico completo para obtener más información.

En cada proyecto, nuestro objetivo es perfeccionar las aplicaciones Angular para que se mantengan estables, seguras y listas para nuevas funciones. Si tienes curiosidad por saber cómo abordamos las tareas frontales en Angular, React o Vue, visita nuestra página de desarrollo web o pásate por nuestro blog para obtener más información. Y si estás pensando en actualizar tu código Angular o construir algo desde cero, estamos aquí para convertir tus ideas en soluciones reales.

Siguiendo esta lista de comprobación de revisión de código de Angular, crearás aplicaciones mantenibles y de alto rendimiento que superarán la prueba del tiempo. Siga perfeccionando sus procesos a medida que evolucionan sus marcos de trabajo y póngase en contacto con nosotros si está listo para ampliar aún más los límites de su proyecto. Nos encanta trabajar con gente que, como nosotros, disfruta convirtiendo buenas ideas en un gran software.

Conclusiones

Esto concluye nuestra Lista de Revisión de Código de Angular condensada. Siguiendo estos puntos, evitarás muchas trampas ocultas (y obvias) a lo largo de tu viaje. Recuerda mantener un ojo en el estilo del código, vigilar tus dependencias y nunca olvidarte de la seguridad. Si detectas algún problema o te sientes atascado, conéctate con nosotros. Nos encanta ayudar a otros desarrolladores a perfeccionar y mejorar sus aplicaciones.

Llevamos haciendo esto desde 2005, y estamos deseando ver crecer tu proyecto Angular. Cuando tu código es claro, tus usuarios lo sienten. Hagamos que eso suceda.