La arquitectura "EleganFlow" se destaca por su modularidad y separación clara de responsabilidades. En este artículo, exploraremos la primera etapa del flujo: la Verificación, una fase crucial para asegurar la integridad y validez de los datos antes de que pasen por las etapas de procesamiento y presentación.
Módulo de Verificación
El módulo de verificación tiene como objetivo principal garantizar que los datos proporcionados por los usuarios o sistemas cumplan con los criterios de calidad y consistencia necesarios para ser procesados correctamente. Este proceso se divide en dos niveles:
1. Verificación de Sintaxis
La validación inicial de la estructura y los tipos de datos se realiza mediante DTOs (Data Transfer Objects).
2. Verificación de Semántica
Una validación más profunda basada en las reglas de negocio, asegurando que los datos sean lógicamente consistentes con las expectativas del sistema.
Flujo de Trabajo
El proceso de verificación comienza en el controlador y se complementa en el servicio. A continuación, se detalla el flujo:
- Controlador: Los datos entrantes son recibidos y validados a nivel de sintaxis utilizando los DTOs. Si la validación falla, se responde de inmediato con los errores correspondientes.
- Servicio: Los datos validados a nivel de sintaxis son enviados al servicio, donde se ejecuta la validación semántica utilizando un conjunto de reglas de negocio. Si alguna regla falla, se detiene el flujo y se notifica al usuario con retroalimentación clara.
Interfaces y DTOs
CreatePersonDto
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
export class CreatePersonDto {
@IsString()
@IsNotEmpty()
name: string;
@IsEmail()
email: string;
}
CreateResponseInterface
export interface CreateResponseInterface<T> {
ok: boolean;
data: T;
constraints: string[];
message: string;
}
Ejemplo de Implementación
Controlador
import {
Controller,
Post,
Body,
} from '@nestjs/common';
import { CreatePersonDto, PeopleService, Person } from '../.';
import {
CreateResponseInterface,
HttpStatusEnum,
} from '../../common';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
@ApiTags('people')
@Controller('people')
export class PeopleController {
constructor(private readonly peopleService: PeopleService) {}
@Post()
@ApiResponse({
status: HttpStatusEnum.Created,
description: 'The record has been successfully created.',
})
async create(
@Body() createPersonDto: CreatePersonDto,
): Promise<CreateResponseInterface<Person>> {
return await this.peopleService.create(createPersonDto);
}
}
Servicio
import { Injectable, Logger } from '@nestjs/common';
import { Person } from '../entities';
import { CreatePersonDto } from '../dtos';
import { PersonChecker } from '../checkers';
@Injectable()
export class PeopleService {
private readonly logger = new Logger(PeopleService.name);
constructor(private readonly personChecker: PersonChecker) {}
async create(createPersonDto: CreatePersonDto): Promise<CreateResponseInterface<Person>> {
// Conversión del DTO a entidad
const newPerson: Person = CreatePersonDtoToPersonAdjust(createPersonDto);
// Validación de reglas de negocio
await this.personChecker.validateCreate(newPerson);
// Lógica adicional y retorno de respuesta
return { ok: true, data: newPerson, constraints: [], message: 'Person created successfully' };
}
}
Validador de Reglas
import { Injectable } from '@nestjs/common';
import { Person } from '../entities';
import { SingleEmailPerPersonRule } from '../rules';
@Injectable()
export class PersonChecker {
async validateCreate(person: Person): Promise<void> {
const rules = [
new SingleEmailPerPersonRule(),
];
for (const rule of rules) {
await rule.validate(person);
}
}
}
Regla de Negocio
import { Person } from '../entities';
export class SingleEmailPerPersonRule {
async validate(person: Person): Promise<void> {
if (!person.email.includes('@example.com')) {
throw new Error('Email domain must be @example.com');
}
}
}
Test Unitario
Ejemplo de Prueba para el Servicio
import { Test, TestingModule } from '@nestjs/testing';
import { PeopleService } from '../services/people.service';
import { PersonChecker } from '../checkers';
import { CreatePersonDto } from '../dtos';
import { Person } from '../entities';
describe('PeopleService', () => {
let service: PeopleService;
let checker: PersonChecker;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
PeopleService,
{
provide: PersonChecker,
useValue: {
validateCreate: jest.fn(),
},
},
],
}).compile();
service = module.get<PeopleService>(PeopleService);
checker = module.get<PersonChecker>(PersonChecker);
});
it('should create a person successfully', async () => {
const dto: CreatePersonDto = { name: 'John Doe', email: 'john.doe@example.com' };
const expectedPerson: Person = { id: 1, ...dto };
jest.spyOn(service, 'create').mockResolvedValue({
ok: true,
data: expectedPerson,
constraints: [],
message: 'Person created successfully',
});
const result = await service.create(dto);
expect(result.ok).toBe(true);
expect(result.data).toEqual(expectedPerson);
});
});
Ventajas de la Verificación en "EleganFlow"
- Modularidad: Las validaciones se agrupan en reglas independientes, lo que facilita su reutilización y mantenimiento.
- Claridad: La separación entre validación de sintaxis y semántica mejora la comprensión del flujo.
- Retroalimentación: Los errores se identifican rápidamente y se comunican de manera clara al usuario.
Conclusión
El módulo de verificación en la arquitectura "EleganFlow" asegura que solo los datos válidos ingresen a las etapas posteriores del flujo, mejorando la calidad del sistema y reduciendo la probabilidad de errores. Este enfoque estructurado facilita la extensibilidad y el mantenimiento a largo plazo.
Top comments (0)