Integracion de nuevos developers

= Introducción = El objetivo de esta guía es servir como referencias para developers actuales y nuevos, acerca de dónde empezar a escribir funcionalidades nuevas dentro de cada proyecto y las guías de escritura de código que son recomendables seguir. Se explica la filosofía de orden del producto y luego se exponen las reglas que se alinean con esta filosofía.

= Filosofía del código = Se hace hincapié en el orden y la separación de responsabilidades antes que en la eficiencia. En un momento en que el orden compite con la eficiencia, el primero debe de ser favorecido. La justificación de esto es que estamos construyendo un sistema modular, que seguirá evolucionando durante el tiempo. Garantizar el orden es clave para mejorar los tiempos de respuesta y la expansibilidad del sistema.

= Los mandamientos =

Los módulos se comunican a nivel de servicio
Un módulo pueden llamar a un servicio de otro Módulo para construir valor encima del mismo. Sin embargo, un módulo no puede llamar directamente a un repository. Se recomienda que la comunicación entre los módulos sea por medio de los DTOs para mejorar el desacople entre los mismos. Excepciones a la regla pueden ser aquellos módulos que poseen referencia a nivel de base de datos.

Un paquete por módulo
Cada módulo debe tener su propio paquete java debajo del paquete principal, que por lo general lleva el nombre del proyecto. Los módulos a su vez están divididos en paquetes de acuerdo a la responsabilidad de los distintos objetos.

Log level
1. Se escriben en ingles. 2. Si al entrar a un método, siempre será impreso, entonces es TRACE. Ejemplo:

3. Debug puede usarse si hay alguna condición que haga que el texto se imprima. 4. Info puede usarse en cambios de estado del sistema. Ejemplo: Se recargaron las reglas. Un endpoint del que dependemos se recuperó, Se recalcularon los balances mensuales. 5. Error. Esto debe usarse solamente si es un fallo del sistema.

Las excepciones se lanzan
Las excepciones son como su nombre lo dicen, excepciones a la regla. Una vez que aparecen debemos salir lo antes posible del contexto actual y simplemente tirar del método. Los únicos dos lugares autorizados para agarrar excepciones son:
 * ErrorController: Para traducir el mensaje a un http code adecuado.
 * Workers/JMS handlers: Los métodos asíncronos, en los cuales queremos manejar el error inesperado y realizar alguna acción.

= Entities = Estas clases suelen ubicarse en los siguientes paquetes, utilizando la nomenclatura mencionada abajo.

Nomenclatura y ubicación
Nombre de sustantivo en singular equivalente a la tabla que se mapea con sufijo Entity

Ejemplo:

Bueno

Malo

= Repositorios de Spring Data =

Nomenclatura y ubicación
Interfaces Java con el nombre del Entity que maneja más el sufijo Repository

Ejemplo:

= Services =

Nomenclatura y ubicación
Interfaces Java con el nombre del entity que maneja más el sufijo Service

Ejemplo:

Nomenclatura y ubicación
Clases que implementan las interfaces Java de los Services, con el nombre del Entity que maneja más el sufijo ServiceImpl.

Ejemplo:

Recomendaciones
Así como se muestra arriba se recomienda poner el @Autowired en el constructor con las dependencias a otros Repository o Service como parámetros de dicho constructor.

Además se recomienda no tener más de 4 dependencias en un Service (parámetros en el constructor).

Estos puntos hace que la clase sea más fácilmente testeable de forma unitaria y también extensible para modificaciones.

Si un Service en particular necesita más de 4 dependencias ya puede ser un síntoma de que dicho Service está teniendo muchas responsabilidades y que hay una nueva clase escondida esperando para salir.

= Capa web: Controllers = Posee los endpoints y los objetos particulares que se necesitan de respuesta. Como la Web está organizada en base a los endpoints, los controllers no forman parte directa de los módulos sino una manera de comunicarse con los mismos. El motivo principal de esto es que los endpoints respeten la nomenclatura establecida por Roy Fielding

Web resource
Cuando decimos recurso no nos referimos necesariamente a algo que exista como entity, o tabla, aunque puede darse el caso. Un recurso nos referimos a la definición de un objeto mapeable por medio de un URI y que expone ciertas propiedades. Ejemplo:
 * 1) Mapea el recurso cliente: api/clients/{referenceNumber}
 * 2) Mapea todas las transacciones de un cliente: api/clients/{referenceNumber}/transactions
 * 3) Mapea el balance de un cliente en particular, en un mes dado: /api/clients/{referenceNumber}/balance/{year}/{month}

Los primeros dos poseen recursos que se pueden encontrar dentro del modelo de datos. Sin embargo, el último es un cómputo para obtener el recurso.

Nomenclatura y ubicación
Clases con el nombre del entity o recurso que maneja más el sufijo Controller

Ejemplo:

Recomendaciones
Usar @RestController siempre que se recibe y responde JSON, usar @Controller en otros casos.

Los controladores deben solamente servir de pasa mano entre los clientes del recurso o endpoint y las clases Service. Deberían a lo sumo realizar validaciones sobre los parámetros de un request, transformar datos para pasar a los Services y tomar los resultados y devolverlos. Estas clases no deben tener nada de lógica en sus métodos (if/else, loops, etc.), esta lógica debe ir destinada de manera exclusiva a los Services.

= Clases DTOS = DTO (Data Transfer Objects) son POJOs que se usan para comunicación comunicación entre módulos, o entre Controllers y el exterior. Son una representación de datos contenidos en Entities pero resumidos y cada campo con formato apropiado para que la clase DTO pueda ser utilizada como respuesta directa de un Controlador (clase que se serializa a un JSON en el response de la petición).

Recomendaciones
Estas clases generalmente suelen ser transformadas desde un Entity a un DTO o viceversa. Para que este mapeo de un tipo de clase a otra sea sencillo y legible, se recomienda usar el patrón Builder para no tener tantos setters uno debajo de otro. Queda más limpia la construcción de DTOS si tenemos llamadas anidadas a métodos

Lectura adicional: https://github.com/HugoMatilla/Effective-JAVA-Summary#2-use-builders-when-faced-with-many-constructors

= Otras clases utilizadas como dependencias =

@Component
Si se necesita otra clase como dependencia inyectada en un Service o Controller (en el constructor con @Autowired) y ésta clase es un POJO que no tiene mucha lógica o acceso a otros recursos como Base de datos o servicios REST externos, se puede anotar dicha clase con @Component. Esta anotación es funcionalmente idéntica a una clase anotada con @Service pero su semántica indica que es una clase más genérica, sin ninguna responsabilidad tan específica como la de los Service o Controllers.

Clases que por ejemplo se anotan con @Components son clases que almacenan parámetros de instalación de una aplicación (propiedades de un application.properties).

Recomendaciones
Por defecto se recomienda que toda clase POJO sea con mínima mutabilidad, propiedades privadas final y sin setters.

Lectura adicional: https://github.com/HugoMatilla/Effective-JAVA-Summary#15-minimize-mutability

= Constantes y enums =

Nomenclatura y ubicación
Los enums deben ir como inner class de la clase donde son utilizadas o bien deben estar en un archivo ".java" separado y tener como prefijo la clase a la cual está asociada.

O bien en archivos separados con el nombre de la clase asociada como prefijo

Recomendaciones
No se deben usar constantes numéricas, siempre se deben usar enums en su lugar. Los enums casi nunca van sueltos y siempre deben estar asociado a un Component, Entity, Controller o Service o clase utilitaria.

De igual forma, las constantes de String deben ir en la clase donde va a ser utilizada. No se recomienda usar Strings en duro, se debe siempre tener una propiedad de clase static final que almacene a esa constante. Tampoco se recomienda meter todas las constantes en una sola clase, sino dividirlas de acuerdo a su cercanía de la clase donde serán utilizadas.

Lectura recomendada: https://github.com/HugoMatilla/Effective-JAVA-Summary#6-enums-and-annotations

= Clases utilitarias con métodos estáticos =

Nomenclatura y ubicación
Si es una clase genérica podría ir en un paquete genérico como sys o commons

Recomendaciones
Estas clases deben ser escritas explícitamente para no ser heredadas (final) o instanciadas (constructor privado).

Lectura recomendada: https://github.com/HugoMatilla/Effective-JAVA-Summary#17-design-and-document-for-inheritance-or-else-prohibit-it

= Parámetros de aplicación "application.properties" =

Nomenclatura y ubicación
Son pares clave y valor escritos dentro de un archivo con nombre application.properties. Tienen como prefijo el nombre del proyecto

Ejemplo:

Cada propiedad definida dentro de este archivo debe tener un mapeo en una clase Java destinada a contener estos valores. En el proyecto por ejemplo se puede tener una clase destinada a este propósito:

En el caso de que se quiera usar parámetros de aplicación en un Service/Controller se debe poner en el constructor anotado con @Autowired.

Recomendaciones
Siempre que se pueda se debe poner un valor por defecto. El criterio a usar es, si la aplicación puede funcionar con un valor por defecto, hay que poner uno.

Esto se hace usando la notación de dos puntos ":" mostrada arriba.