Necesidades de negocio (historias de usuario, diseño, etc)
Necesidades de negocio (requerimientos, historias de usuario, criterios de aceptación, diseño, UX/UI, análisis de impacto esfuerzo de features, refinamiento, pruebas de usuario, focus group, brainstorming, etc)
Arquitectura base (capas)
📦 Features
- Dividir la app en módulos funcionales (Feature Modules) en lugar de tener todo al mismo nivel que la carpeta
app. - core para manejar servicios singleton y configuraciones globales.
- shared para componentes, pipes y directivas reutilizables.
Los módulos deberan tener la siguiente estuctrura de carpetas:
- Carpeta models donde estaran las interfaces y tipos (Model).
- Carpeta services donde estaran los servicios que gestionan la data y se comunican con la API.
- Carpeta viewmodels donde estaran los componentes inteligentes que manejan la lógica de negocio (ViewModel).
- Carpeta views donde estaran los componentes "tontos" que solo muestran datos (View)
- Archivo de rutas, Ej:
products.routes.ts.
│── features/ # Funcionalidades organizadas
│ ├── dashboard/ # Módulo de negocio específico.
│ ├── services/ # Servicios propios del modulo
│ ├── model/ # Modelos de datos.
│ ├── viewmodels/ # Adaptadores entre modelos y vistas (comp "inteligentes")
│ ├── views/ # Componentes visuales del modulo. (comp "tontos")
Lineamientos:
| Atributo | Definición |
|---|---|
| Nombre | El nombre de la carpeta del modulo se debe declarar lo más sencillo, descriptivo y corto posible. |
| Idioma | Inglés |
| Estilo Variable | kebab-case |
| Nomenclatura | <module-name> Ejemplo: products |
| Consideraciones | - No usar espacios, tildes, caracteres especiales ni la letra ñ. Evitar el uso de abreviaturas o acrónimos. Evitar combinar palabras inglés-español. |
Nota: Ocupar el patrón standalone esta prohibido usar los archivos <name>.module.ts y <name>-rounting.module.ts
⚙️ Services
Los servicios en microfrontends (MFEs) en Angular deben ser diseñados para garantizar independencia, comunicación eficiente y escalabilidad. Por lo anterior, se deberán validar y seguir las siguientes prácticas para implementar servicios correctamente en una arquitectura basada en microfrontends.
1. Independencia de los servicios
- Cada microfrontend debe tener sus propios servicios para garantizar que los módulos sean autónomos.
- Los servicios no deben depender de otros microfrontends para evitar acoplamiento entre ellos.
- Utiliza inyección de dependencias para que los servicios sean fácilmente testeables y reutilizables.
2. Comunicación entre microfrontends
- Eventos Globales: Utiliza un bus de eventos (por ejemplo, RxJS) para permitir que los MFEs se comuniquen entre sí sin acoplarse directamente.
- Interfaz de Comunicación: Define un contrato claro y API estándar para la comunicación entre microfrontends. Asegúrate de que la comunicación sea robusta y versionada.
3. Escalabilidad
- A medida que crecen los MFEs, los servicios deben ser capaces de manejar más usuarios y más peticiones de manera eficiente.
4. Testing
- Asegúrate de que los servicios sean probados de forma aislada y sin depender de otros microfrontends.
- Utiliza pruebas unitarias, pruebas de integración y pruebas end-to-end (E2E) para asegurar que los servicios se comporten como se espera.
5. Documentación
- Documenta las APIs y servicios de manera clara y accesible para todos los equipos de desarrollo. Esto facilitará la integración y escalabilidad de los microfrontends.
Lineamientos:
| Atributos | Definición |
|---|---|
| Nombre | Se debe declarar el nombre lo más sencillo, descriptivo y corto posible. |
| Definición | Parte fundamental en el desarrollo de un componente que será usada para comunicar el aplicativo front con las APIs. |
| Idioma | Inglés |
| Estilo Variable | kebab-case |
| Nomenclatura | <name>-service.ts |
| Ejemplo | general.service.ts |
| Consideraciones | No usar espacios, tildes, caracteres especiales, ni la letra ñ. Evitar el uso de abreviaturas o acrón |
Seguir las siguientes recomendaciones a la hora construir un servicio:
- Se recomienda usar Observables en los retornos de las respuestas de los servicios.
- Se recomienda usar Interfaes en las respuestas de los servicios.
- Se recomienda hacer operaciones y transformaciones de datos con rxjs antes de pasar la información a las vistas.
Ejemplo:
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { map, Observable } from "rxjs";
import { IProductCard } from "../models/product.model";
import { IResponseAnime } from "../models/anime-api.interface";
@Injectable({ providedIn: "root" })
export class ProductsService {
constructor(private _httpClient: HttpClient) {}
getProducts(): Observable<IProductCard[]> {
return this._httpClient
.get<IResponseAnime>("https://api.jikan.moe/v4/anime?q=kimetsu&sfw")
.pipe(
map((response) => {
return response.data
.filter((item) => item.synopsis)
.map<IProductCard>((item) => ({
urlImage: item.images.jpg.image_url,
price: this._getNumberRandom(),
name: item.title,
description: item.synopsis!,
}));
})
);
}
private _getNumberRandom() {
return Math.floor(Math.random() * (500 - 1 + 1) + 1);
}
}
Cada microfrontend debe manejar su propio estado de servicio y evitar compartir instancias globales.
Comunicación entre Microfrontends
Cuando los microfrontends necesitan comunicarse los únicos mecanismos disponibles para ello será:
- Eventos
- Event Bus con RxJS
🧠 ViewModel Web
Los archivos "Viewmodel" son componentes que contienen la capa de lógica, cuya principal función es:
- Obtener y procesar datos.
- Manejar eventos.
- Formatear fechas, números, etc.
- Transformar datos para gráficos o listas
- Comunicar la vista con el modelo.
Partiendo de este enfoque, los archivos .component.ts y .component.html se convierten en componentes "tontos" que solo muestran datos y se comunican exclusivamente con el Viewmodel.
Beneficios de usar ViewModels
- Separación de responsabilidades
- Reutilización de lógica de transformación
- Evita lógica innecesaria en el componente
Lineamientos:
| Atributos | Definición |
|---|---|
| Nombre | Se debe declarar el nombre lo más sencillo, descriptivo y corto posible. |
| Definición | Son componentes inteligentes que se encargan de procesar la información de los servicios y atender las reglas de negocio. |
| Idioma | Inglés |
| Estilo Variable | kebab-case |
| Nomenclatura | <name>-viewmodel.ts |
| Ejemplo | products.viewmodel.ts |
| Consideraciones | No usar espacios, tildes, caracteres especiales, ni la letra ñ. Evitar el uso de abreviaturas o acrón |
⚙️ Componentes
Los componentes es la parte fundamental de nuestro proyecto, ya que controlan la vista (HTML) y manejan eventos del usuario. También reciben datos desde ViewModels y usan servicios para obtener datos o ejecutar lógica de negocio.
Por lo general nuestros componentes, contendran 2 archivos pricipales, los cuales son:
- Archivo HTML (vistas)
- Archivo SCSS (estilos)
A continuación se muestra el flujo de trabajo de los componentes:

Lineamientos:
| Atributo | Definición |
|---|---|
| Nombre | Se debe declarar el nombre lo más sencillo, descriptivo y corto posible. |
| Definición | Un componente en Angular es un elemento que está compuesto por: |
- Un archivo template: <component-name>.component.html | |
- Un archivo de lógica: <component-name>.component.ts | |
- Un archivo de estilos SCSS: <component-name>.component.scss | |
- Un archivo de pruebas: <component-name>.component.spec.ts | |
| Idioma | Inglés |
| Estilo Variable | kebab-case |
| Nomenclatura | <component-name>.component |
| Ejemplos: | |
- app.component.html | |
- my-scheduler.component.ts | |
| Consideraciones | - No usar espacios, tildes, caracteres especiales ni la letra ñ. |
| - Evitar el uso de abreviaturas o acrónimos. | |
| - Evitar combinar palabras inglés-español. |
📐 Interfaces
En Angular (y en TypeScript en general), las interfaces son una herramienta fundamental para definir la estructura de los datos que se usan en la aplicación.
export interface IUser {
id: number;
name: string;
email: string;
}
🎯 ¿Para qué sirven?
- Definen contratos: Permiten establecer claramente cómo debe ser la estructura de un objeto.
- Facilitan el autocompletado y la documentación en los editores como VSCode.
- Previenen errores: Ayudan a detectar errores en tiempo de desarrollo si un objeto no cumple con la estructura definida.
- Mejoran el mantenimiento del código: Hacen que el código sea más legible y fácil de entender para otros desarrolladores.
🛠️ ¿Dónde se usan en Angular?
- Al definir los modelos de datos que vienen de APIs o se envían a ellas.
- En los servicios para tipar los datos que se reciben o envían.
- En componentes para tipar inputs, outputs, formularios, etc.
- En estructuras complejas como listas de objetos, configuraciones, etc.
getUser(): Observable<IUser> {
return this.http.get<IUser>('https://api.example.com/user');
}
Lineamientos:
| Atributo | Definición |
|---|---|
| Nombre | Se debe declarar el nombre lo más sencillo, descriptivo y corto posible. |
| Definición | Nos ayudan a definir y tipar los datos, lo que mejora la seguridad, mantenibilidad y escalabilidad del código. |
| Idioma | Inglés |
| Estilo Variable | - PascalCase (para nombrar la interface) |
- kebab-case (para nombrar el archivo) | |
| Nomenclatura | <name>.model.ts |
| Ejemplos: | |
- user.model.ts | |
- export interface <IName> {} | |
- export interface IUser {} | |
| Consideraciones | - No usar espacios, tildes, caracteres especiales ni la letra ñ. |
| - Evitar el uso de abreviaturas o acrónimos. | |
| - Evitar el uso de combinaciones inglés - español. |
📁 Estructura Completa del Proyecto
La organización del proyecto debe reflejar la separación de las capas mencionadas. A continuación, se presenta una estructura de carpetas recomendada:
src/
└── app/
│ │── config/ # Objetos de Valor utilizados en la configuración de la app
│ │── core/ # Servicios centrales y fachadas compartidas por toda la app
│ │── features/ # Funcionalidades organizadas
│ │ ├── dashboard/ # Módulo de negocio específico.
│ │ ├── services/ # Servicios propios del modulo
│ │ ├── model/ # Modelos de datos.
│ │ ├── viewmodels/ # Adaptadores entre modelos y vistas (comp "inteligentes")
│ │ ├── views/ # Componentes visuales del modulo. (comp "tontos")
│ │── pages/ # Componentes de página que orquestan vistas completas.
│ │── shared/ # Componentes, directivas y utilidades reutilizables.
│ │── app.component.ts # Componente raíz de la aplicación.
│ │── app.config.ts # Configuración general de la aplicación.
│ │── app.routes.ts # Definición de rutas principales.
│── assets/ # Archivos estáticos (imágenes, fuentes, etc).
│── environments/ # Configuraciones para distintos entornos.
└── main.ts # Punto de entrada principal de la aplicación.
🚨 Manejo de errores
Para poder manejar los errores Angular usa HttpClient para hacer peticiones HTTP. Se puede manejar errores en los llamados a la API usando el operador catchError de RxJS, que nos permite capturar los errores y realizar alguna acción en consecuencia (como mostrar un mensaje de error o redirigir al usuario).
Se recomienda hacer uso de interceptores, para el manejo de los errores. Y para ello se recomienda las siguientes consideraciones:
- El archivo interceptor, debera estar registrado en el host
- El archivo interceptor, debera ser expuesto por el host y en los remotes se debera importar
🔤 Nombramiento de métodos
A continuación se muestra los estandares para el nombramiento de métodos que se recomiendan usar:
| Prefijo | Propósito | Ejemplo |
|---|---|---|
| get | Obtener datos o una propiedad | getUser(), getOrderStatus() |
| set | Asignar o modificar datos | setUserName(), setThemeColor() |
| fetch | Obtener datos de una API o servicio asíncrono | fetchUsers(), fetchOrders() |
| load | Cargar datos o inicializar información | loadDashboard(), loadSettings() |
| create | Crear un nuevo recurso u objeto | createUser(), createTask() |
| update | Modificar un recurso existente | updateProfile(), updateOrderStatus() |
| delete | Eliminar un recurso | deleteUser(), deleteItem() |
| remove | Quitar un elemento de una colección | removeFromCart(), removeItem() |
| reset | Restaurar valores a su estado inicial | resetForm(), resetPassword() |
| toggle | Alternar un estado entre dos valores | toggleSidebar(), toggleTheme() |
| handle | Manejar eventos o acciones del usuario | handleClick(), handleInputChange() |
| can | Determinar si una acción es permitida | canActivate(), canEditPost() |
| is | Verificar un estado o condición (devuelve boolean) | isLoggedIn(), isUserAdmin() |
| should | Determinar si algo debe ocurrir (devuelve boolean) | shouldShowModal(), shouldUpdateProfile() |
| has | Comprobar si un elemento tiene una propiedad o estado | hasPermission(), hasItemsInCart() |
| validate | Validar datos o entradas | validateForm(), validateEmail() |
| save | Guardar datos en una base de datos o almacenamiento | saveUserSettings(), saveChanges() |
| subscribe | Suscribirse a un observable o evento | subscribeToNotifications(), subscribeToNewsletter() |
| unsubscribe | Cancelar una suscripción de un observable o evento | unsubscribeFromUpdates(), unsubscribeFromService() |
📦 Dependencias
A continuación se enlistan las dependencias dentro de la arquitectura:
- Prettier - Formateo de codificación
- Eslint - Linteo y detección de errores en el código
- Husky - Git Hooks para mejorar la calidad del código antes de realizar confirmaciones (git commit) o enviar cambios (git push)
- Template - Template dinamico basado con estilos de bootstrap
✨ Lintening
Para el linteo ocuparemos 2 formas de hacerlo, con Eslint mientras estamos codeando, y también con husky, al hacer un pre-commit.
A continuación se muestra el comando que se debera ocupar para lintear los archivos del todo el proyecto:
npm run lint
Y la otra forma de hacerlo, es cuando se hace un git commit convencional:
git commit -m "mensaje"
Esto detonora husky y hara un linteo por nosotros para los archivos que fueron modificados.
🔍Estandares de calidad
Para las pruebas unitarias se requiere un minimo de 85% de cobertura, para poder ser aceptado y posteriormente mergeado en un PR.
También se implementara la herramienta de Sonar para escanear y cuidar la calidad del codigo, y detectar posibles fallas o codesmells.
📏 Documentación (lineamientos)
Para la documentación del codigo, se debera ocupar JSDoc.
JSDoc es una herramienta que permite agregar comentarios estructurados en el código para documentar funciones, clases y propiedades de manera clara y comprensible. Esto facilita la colaboración en equipos y mejora la mantenibilidad del código.
A continuación se muestran diferentes ejemplos:
1. Metodo Simple
/**
* Calcula el total con descuento.
* @param {number} precio - Precio original del producto.
* @param {number} descuento - Porcentaje de descuento (0.10 = 10%).
* @returns {number} Total con descuento aplicado.
*/
calcularTotal(precio: number, descuento: number): number {
return precio - (precio * descuento);
}
Explicación:
@param {number} a y @param {number} b describen los parámetros de la función, ambos son números.
@returns {number} indica que la función devuelve un número, que es el resultado de la operación de los parametros.
2. Método que invoca otros métodos
/**
* Procesa la compra de un producto.
* Llama a métodos internos para calcular precio, generar factura y guardar en base de datos.
* @param {number} precio - Precio del producto.
* @param {number} descuento - Porcentaje de descuento.
* @returns {boolean} Devuelve `true` si la compra se procesó correctamente.
*/
procesarCompra(precio: number, descuento: number): boolean {
const total = this.calcularTotal(precio, descuento);
const factura = this.generarFactura(total);
return this.guardarFactura(factura);
}
/**
* Genera una factura con el total.
* @param {number} total - Total a facturar.
* @returns {{ total: number, fecha: Date }} Objeto factura.
*/
private generarFactura(total: number): { total: number; fecha: Date } {
return { total, fecha: new Date() };
}
/**
* Guarda la factura en la base de datos.
* @param {{ total: number, fecha: Date }} factura - Factura a guardar.
* @returns {boolean} `true` si se guardó correctamente.
*/
private guardarFactura(factura: { total: number; fecha: Date }): boolean {
console.log('Factura guardada:', factura);
return true;
}
3. Interfaz con varias propiedades
/**
* Representa un usuario en el sistema.
* @interface
*/
export interface IUsuario {
/** Identificador único del usuario. */
id: string;
/** Nombre completo del usuario. */
nombre: string;
/** Correo electrónico del usuario. */
email: string;
/** Fecha de creación del usuario. */
fechaCreacion: Date;
/** Indica si el usuario está activo. */
activo: boolean;
}
4. Constructor heredando funcionalidad
export class RemotoFormViewModel extends BaseViewModel {
/**
* Crea una instancia de `RemotoFormViewModel`, que gestiona la lógica y el estado
* del formulario para operaciones remotas.
*
* Esta clase extiende de `BaseViewModel`, heredando su funcionalidad base
* para el manejo de estados, validaciones y flujo de datos.
* La llamada a `super()` inicializa las propiedades y lógica definidas en la clase padre.
*/
constructor() {
super();
}
}
5. Inyecciónes de dependencias
/** Cliente HTTP para realizar peticiones a la API. */
private readonly http = inject(HttpClient);
/** Servicio de enrutamiento para navegar entre páginas. */
private readonly router = inject(Router);
/** Servicio de autenticación para obtener datos del usuario actual. */
private readonly authService = inject(AuthService);
/** Servicio para el registro y seguimiento de logs en la aplicación. */
private readonly logger = inject(LoggerService);
6. Declaración de variables públicas y privadas en un componente
/**
* Componente para mostrar el dashboard.
*/
export class DashboardComponent {
/** Título del dashboard que se muestra en la vista. */
public titulo: string = "Panel de control";
/** Lista de usuarios cargados desde la API. */
public usuarios: Usuario[] = [];
/** Estado interno que indica si se está cargando la información. */
private cargando: boolean = false;
/** URL base de la API. */
private readonly apiUrl: string = "https://api.midominio.com";
}
❌ En este proyecto está prohibido el uso de comentarios de una sola línea con // dentro del código TypeScript, ya que no siguen el estándar de documentación adoptado y no son procesados por herramientas automáticas como JSDoc.
❌ En este proyecto está prohibido el uso de comentarios como // TODO y // FIXME
👍 Toda la documentación debera ser en español.