Skip to content
Rubby Casallas edited this page Feb 14, 2023 · 34 revisions

La capa de lógica

Introducción

En la arquitectura de capas que estamos utilizando en nuestros proyectos, la capa de lógica de la aplicación o negocio se encarga de coordinar los llamados del API REST y el acceso a la capa de persistencia. Es una capa intermedia entre la implementación de los recursos y la base de datos.

Una de sus responsabilidades es ocuparse de validar reglas de negocio o de invocar servicios de otras aplicaciones. Algunas reglas de negocío, podrían ser, por ejemplo:

  1. Que el ISBN de un libro exista en el servicio internacional de ISBN.
  2. Que la fecha de publicación del libro sea mayor que la fecha de nacimiento del autor.

En el contexto de Spring, la lógica de la aplicación está implementada mediante beans, es decir, clases Java cuyo ciclo de vida es manejado por el contenedor de aplicaciones. En los proyectos del curso, las clases de la lógica estarán anotadas por @Service y como convención de nombramiento tendrań el sufijo Service, por ejemplo CompanyService.

La capa de lógica en nuestros proyectos

La Figura 1 presenta los elementos de la arquitectura de las aplicaciones que estamos desarrollando. La capa de lógica contiene las clases anotadas por @Service y son la fachada para el uso de los servicios que ofrece el Backend de la aplicación. En los proyectos que estamos desarrollando el cliente del Backend es un API REST (o las pruebas junit). Los objetos que maneja el Backend y que transfiere entre las capas son entidades de persistencia, es decir, clase Java anotadas con @Entity.

El Backend no conoce DTOs ni Json ni ninguna otra representación de los recursos.

Figura 1
Figura 1

El diagrama de clases de la Figura 2 presenta para dos módulos su fachada AuthorService y EditorialService, y su relación con la capa de persistencia. El diagrama no lo muestra pero, cuando la lógica invoca métodos en la persistencia, lo que viajan son entidades. En este caso AuthorEntity y EditorialEntity.

Figura 2
Figura 2

Veamos ahora cómo la lógica se comunica con la persistencia a través de la inyección de dependencias.

Inyección de Dependencias

La mayoría de las aplicaciones en Java utilizan recursos y servicios, tales como fuentes de datos o servicios web externos. El uso de estos recursos se convierte en algo simple en Spring mediante la inyección de dependencias.

La inyección de dependencias permite que un recurso A declare una dependencia a un recurso B y delega la resolución de la misma al contenedor. El contenedor se ocupa de resolver y entregar una instancia del recurso B y se lo "inyecta" al recurso A.

Veamos dos ejemplos: i) el controlador inyectando la lógica y ii) la lógica inyectando la persistencia.

La clase de la lógica de company define una variable para acceder a la persistencia de tipo CompanyRepository. Utilizamos la anotación @Autowired para indicarle al contenedor que en ejecución "inyecte", es decir, haga que la variable apunte a un objeto de una clase que CompanyRepository.

@Service
public class CompanyService {

    @Autowired
    private CompanyRepository repository;
  ... 
}

En el contexto de nuestro ejemplo tenemos que el API Rest implementado en los controladores, para el ejemplo, CompanyController, define una variable cuyo tipo es una interface de la lógica. Utilizamos la anotación @Autowired para indicarle al contenedor que en ejecución "inyecte", es decir, haga que la variable apunte a un objeto de una clase que implementa esa interfaz.

@RestController
@RequestMapping("/authors")
public class CompanyController {

    @Autowired
    private CompanyService companyService;
    ... 
}

Validación de las reglas de negocio

La lógica de la aplicación es responsable de comunicar la capa de controladores (o recursos) con la persistencia. Esta capa manipula objetos Entity. Esta capa es responsable de verificar las reglas de negocio y de comunicarse con la persistencia para recuperar o modificar los datos.

Para ilustrar verificaciones de reglas de negocio en nuestro ejemplo hemos definido las siguientes:

  1. No puede haber dos compañías con el mismo nombre
  2. No puede haber dos departamentos de la misma compañía con el mismo nombre
  3. Un empleado no puede tener un salario superior a 50 millones.

Vamos a explicar la primera regla de negocio. Esta se debe validar en dos ocasiones: cuando se crea una nueva compañía y cuando se modifica una compañía que ya existe. El siguiente fragmento de código presenta el método en la lógica para crear una compañía.

La lógica recibe el objeto CompanyEntity que se quiere crear. Este es un objeto enviado por el API. Lo primero que debe hacer es llamar a la persistencia para que consulte en la base de datos si ya existe una compañía con el nombre de la que se quiere crear (método findByName). Si ya existe, significa que la regla de negocio no se está validando y en ese caso se dispara una excepción. Si no existe se procede con la creación de la nueva compañía a través de la persistencia.

@Service
public class CompanyService {

  @Autowired
  private CompanyRepository repository;
  
  ...
  @Transactional
  public CompanyEntity createCompany(CompanyEntity entity) throws IllegalOperationException {
    List<CompanyEntity> alreadyExist = repository.findByName(entity.getName());
    if(!alreadyExist.isEmpty()) {
        throw new IllegalOperationException("Ya existe una compañía con ese nombre");
    } else {
        return repository.save(entity);
    }
  } 
...
}

Este libro fue creado para el curso ISIS2603 Desarrollo de Software en Equipos en la Universidad de los Andes. Desarrollado por Rubby Casallas con la colaboración de César Forero, Kelly Garcés, Jaime Chavarriaga y José Bocanegra. Universidad de los Andes, Bogotá, Colombia. 2021.

Clone this wiki locally