DEV Community

Cover image for 👮🏻‍♂️ Enfoque en la Verificación de la Arquitectura 'EleganFlow'

👮🏻‍♂️ Enfoque en la Verificación de la Arquitectura 'EleganFlow'

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:

  1. 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.
  2. 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;
}
Enter fullscreen mode Exit fullscreen mode

CreateResponseInterface

export interface CreateResponseInterface<T> {
  ok: boolean;
  data: T;
  constraints: string[];
  message: string;
}
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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' };
  }
}
Enter fullscreen mode Exit fullscreen mode

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);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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);
  });
});
Enter fullscreen mode Exit fullscreen mode

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.

Image of AssemblyAI tool

Transforming Interviews into Publishable Stories with AssemblyAI

Insightview is a modern web application that streamlines the interview workflow for journalists. By leveraging AssemblyAI's LeMUR and Universal-2 technology, it transforms raw interview recordings into structured, actionable content, dramatically reducing the time from recording to publication.

Key Features:
🎥 Audio/video file upload with real-time preview
🗣️ Advanced transcription with speaker identification
⭐ Automatic highlight extraction of key moments
✍️ AI-powered article draft generation
📤 Export interview's subtitles in VTT format

Read full post

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay