Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Debemos revisar si se requiere documentar todo el código para documentación, en caso de que no se requiera debemos evitar cualquier comentario.

Declaraciones

Imports. Cuando declaramos imports debemos de evitar usar el comodín o wildcard para evitar cargar dependencias que no se usan. 

...

En cualquier de estos tipos de variables, no debemos declarar más de una variable por línea. Así también, siempre debemos inicializar las variables de instancia y de clase evitando que las variables no primitivas tengan un valor null.

Al tener la versión de java 17 es importante considerar la inferencia de tipos usando var en las variables locales (incluyendo ciclos y lambdas) así como si se asigna valor una sola vez, declararla final.

Sentencias

Debemos recordar que es importante que solo se tenga una sentencia por línea de código. En las sentencias como if o for es importante colocar las llaves del bloque de código que le corresponde aunque solo tenga una línea de código en el bloque.

...

Debemos usar constantes en lugar de tener cadenas de texto o números por todas partes, si esos textos o números se pueden representar en un conjunto que compartan un contexto se puede crear una enumeración. 

Encapsulación

Todos Todas nuestras variables de instancia de  un Bean debería ser encapsulas para evitar el acceso directo a sus valores, dado esto se deben crear sus métodos getter y setter. De ser posible todos nuestros beans deberían ser no mutables quitando los métodos setter. En este ultimo caso se recomienda usas el tipo record.

Duplicidad de código

Uno de los problemas más frecuentes identificados al realizar un code review es el código repetido duplicado y aunque es difícil de eliminarlo cuando ya se ha concluido, es importante no crearlo. Para esto nos podemos apoyar en patrones de diseño o en los principios solid para evitarlo. ¡No copiemos código! O si lo hacemos asegurémonos que es imposible implementar una solución alterna. 

...

Si bien es cierto que la herencia es unos de los elementos más importantes de la programación orientada a objetos al reutilizar los atributos y métodos comunes, también puede tener sus problemas si la profundidad de herencia es muy grande. Ya que cada subclase hereda los atributos y métodos del padre haciendo difícil la lectura del código y su mantenimiento, así también el diseño se vuelve más complejo. Por lo que es recomendable una herencia con una profundidad no mayor a 3 o 4.

Principios SOLID

Acrónimo propuesto por Robert Martin:

  • Single Responsibility Principle

  • Open-Close Principle

  • Liskov Substitution Principle

  • Interface Segregation Principle

  • Dependency Inversion Principle

Estos principios nos ayudan a crear software escalable, código fácil de leer y entender, tener alta cohesión y un bajo acoplamiento, y con esto el mantenimiento es más sencillo.

SRP 

Al abstraer un objeto que tenga su funcionalidad bien definida logramos incrementar la cohesión y disminuir el acoplamiento. Esto se logra al delegar por herencia ciertas responsabilidades, esto es que una clase no debe contener atributos o métodos que no le correspondan. 

...

OCP

Todo el software es propenso a crecimiento en funcionalidad pero, al realizarse no debería de modificar la funcionalidad existente y ya probada. Este principio indica justo eso: abierto para la extensión pero cerrado para la modificación. Es complicado realizar esto sin un buen análisis y un conocimiento adecuado del proyecto para prever futuros cambios, pero es deseable que siempre consideremos una extensión futura.

Conseguimos esto con componentes con alta cohesión (SRP) y con una buena dirección de las dependencias (DIP).

...

LSP

El principio de sustitución de Liskov nos dice: un subtipo S de T puede ser asignado a T sin alterar el comportamiento esperado. Esto puede verse como herencia y polimorfismo, pero va más allá y eso se ve en el "sin alterar el comportamiento esperado". Lo que se debe considerar es que al usar el polimorfismo, una clase no debe contener atributos/métodos que no le correspondan. Para lograr esto debemos crear clases que implementen esa funcionalidad y que hereden de la clase padre de donde se quitaron los atributos/métodos.

...

ISP

El principio de segregación de interfaces nos dice que una cliente no puede depender de métodos que no use, en caso de que pase debemos crear una o más interfaces y repartir los métodos evitando que algún cliente que usaba la interface quede con un método que no use como dependencia, al realizar esto podemos tener que un cliente use métodos de diferentes interfaces lo que sería correcto.

...

DIP

El principio de inversión de dependencias nos dice que el objeto contenido en otro no debe depender del principal y viceversa. Esto es que cuando modelamos una solución debemos abstraer el objeto de más bajo nivel con su funcionalidad básica y por medio de una interface definir la funcionalidad genérica del objeto de bajo nivel que será implementado por el de alto nivel. Con esto logramos que ninguno de los objetos dependa uno del otro y la dependencia entre ambos esta dado por una interface.

...

Usar este principio de forma correcta nos permite tener código desacoplado, código reutilizable y escalable.

Nomenclatura para el nombrado de los servicios

El estándar de nombramiento de microservicios es el siguiente:

<canal>-<tipo>-<dominio o funcionalidad>-service

Canal. únicamente se usa si el servicio estará en la capa OSL (canal), de ser el caso, se debe usar el nombre del canal como prefijo, por ejemplo, un servicio que será consumido por el app Spin estará en la capa de canal mobile y su nombre deberá comenzar con “mobile”. Si es un servicio de capa DSL core, no debe llevar ningún valor en este campo.

Ejemplos de canales y servicios:

...

Canal

...

Ejemplos

...

mobile

...

mobile-transaction-service, mobile-profile-service

...

fraud-support

...

fraud-support-service

...

customer-support

...

customer-support-service

Dominio o funcionalidad. únicamente se usa si el servicio es de capa DSL, el valor será el dominio o funcionalidad que abstraiga el servicio. Por ejemplo: account-service, user-service, transaction-inquiry-service, pricing-service.

...

Consideraciones para el desarrollo de Token Digital

Anotaciones de lombok

Todos los beans deben tener la anotación de lombok:

@Getter

@Setter

@Builder

@NoArgsConstructor

@AllArgsConstructor

@ToString

Archivos YML o properties

Se deben crear archivos de tipo yml o properties en caso de que se deba parametrizar alguna propiedad que pueda cambiar con el tiempo. De preferencia solo agregar parámetros de una lectura.

Logs

Se debe usar la anotación:

@slf4j

para los logs. Los scopes usados serán:

error. Para los logs de las excepciones

debug. Para imprimir datos que ayuden a resolver issues

info. Para dar información adicional

 

·        Se deben crear los logs necesarios en cada clase.

·        Es obligatorio crear un log en cada excepción.

 

Se agregará el siguiente formato para la escritura de los logs:

:: clase :: metodo >> mensage

Validaciones

Con librerías. Usar librerías ya existentes de spring, hibernate, etc.

Con anotaciones. Se deben crear anotaciones para validaciones no existentes en las librerías, que deberían de ser todas las correspondientes al negocio.

Principios SOLID

Acrónimo propuesto por Robert Martin:

  • Single Responsibility Principle

  • Open-Close Principle

  • Liskov Substitution Principle

  • Interface Segregation Principle

  • Dependency Inversion Principle

Estos principios nos ayudan a crear software escalable, código fácil de leer y entender, tener alta cohesión y un bajo acoplamiento, y con esto el mantenimiento es más sencillo.

SRP 

Al abstraer un objeto que tenga su funcionalidad bien definida logramos incrementar la cohesión y disminuir el acoplamiento. Esto se logra al delegar por herencia ciertas responsabilidades, esto es que una clase no debe contener atributos o métodos que no le correspondan. 

...

OCP

Todo el software es propenso a crecimiento en funcionalidad pero, al realizarse no debería de modificar la funcionalidad existente y ya probada. Este principio indica justo eso: abierto para la extensión pero cerrado para la modificación. Es complicado realizar esto sin un buen análisis y un conocimiento adecuado del proyecto para prever futuros cambios, pero es deseable que siempre consideremos una extensión futura.

Conseguimos esto con componentes con alta cohesión (SRP) y con una buena dirección de las dependencias (DIP).

...

LSP

El principio de sustitución de Liskov nos dice: un subtipo S de T puede ser asignado a T sin alterar el comportamiento esperado. Esto puede verse como herencia y polimorfismo, pero va más allá y eso se ve en el "sin alterar el comportamiento esperado". Lo que se debe considerar es que al usar el polimorfismo, una clase no debe contener atributos/métodos que no le correspondan. Para lograr esto debemos crear clases que implementen esa funcionalidad y que hereden de la clase padre de donde se quitaron los atributos/métodos.

...

ISP

El principio de segregación de interfaces nos dice que una cliente no puede depender de métodos que no use, en caso de que pase debemos crear una o más interfaces y repartir los métodos evitando que algún cliente que usaba la interface quede con un método que no use como dependencia, al realizar esto podemos tener que un cliente use métodos de diferentes interfaces lo que sería correcto.

...

DIP

El principio de inversión de dependencias nos dice que el objeto contenido en otro no debe depender del principal y viceversa. Esto es que cuando modelamos una solución debemos abstraer el objeto de más bajo nivel con su funcionalidad básica y por medio de una interface definir la funcionalidad genérica del objeto de bajo nivel que será implementado por el de alto nivel. Con esto logramos que ninguno de los objetos dependa uno del otro y la dependencia entre ambos esta dado por una interface.

...

Usar este principio de forma correcta nos permite tener código desacoplado, código reutilizable y escalable.

Nomenclatura para el nombrado de los servicios

El estándar de nombramiento de microservicios es el siguiente:

<canal>-<tipo>-<dominio o funcionalidad>-service

Canal. únicamente se usa si el servicio estará en la capa OSL (canal), de ser el caso, se debe usar el nombre del canal como prefijo, por ejemplo, un servicio que será consumido por el app Spin estará en la capa de canal mobile y su nombre deberá comenzar con “mobile”. Si es un servicio de capa DSL core, no debe llevar ningún valor en este campo.

Ejemplos de canales y servicios:

Canal

Ejemplos

mobile

mobile-transaction-service, mobile-profile-service

fraud-support

fraud-support-service

customer-support

customer-support-service

Dominio o funcionalidad. únicamente se usa si el servicio es de capa DSL, el valor será el dominio o funcionalidad que abstraiga el servicio. Por ejemplo: account-service, user-service, transaction-inquiry-service, pricing-service.

Otra consideración para el nombrado de servicios es el agrupado en capas en donde tenemos las siguientes:

...

Data Layer. En esta capa se concentran las bases de datos.

...

Contrato para servicios REST

...

Lo ideal es usar las tecnologías más usadas ya que estas han sido probadas y validadas por muchísimos otros proyectos. Por lo que de esto y de acuerdo a lo que usan en Spin, las tecnologías que usaremos serán: 

Framework: Spring con Spring Boot 2 y Spring Cloud 

Servidore de aplicaciones: Se usaran Saas en la nube usando AWS (S3, Cognito, EC2, CloudWatch, RDS, Lamdas, SQS) y Google Cloud 

Kinesis 

Base de datos: MongoDB, Redis 3

Spring Cloud 

gRPC

REST

MongoDB

Kubernetes 

Docker 

Dynatrace 

React Native 

Configcat 

Repositorio: Bitbucket usando git 

Versión de Java: 8 

Otros: OTP, retrofit 

Spock Testing Framework

Dynatrace  

Java 17

AWS

Adicional a esto se usara como IDE IntelliJ Community al tener una de las comunidades más activas y contar con plugins fáciles de instalar y usar.

...

Integración continua. Para esto podemos usar herramientas de control de versiones como SVN o GIT. En nuestro caso usaremos git, con github y bitbucket. La forma como iremos integrando nuestros cambios será la siguiente:

...

Distribución continua. Nos ayuda a realizar una liberación de forma constante y sencilla en uno o más ambientes, una de las herramientas más usadas es Jenkins con la ayuda de pipelines. Adicional a esto nos ayuda Docker y Kubernetes para poder gestionar instancias de forma dinámica de acuerdo a la demanda de los servicios quitándole un trabajo que antes era muy complejo a DevOps.En nuestro caso DevOps se encargara de esta actividad. es Jenkins con la ayuda de pipelines. Adicional a esto nos ayuda Docker y Kubernetes para poder gestionar instancias de forma dinámica de acuerdo a la demanda de los servicios quitándole un trabajo que antes era muy complejo a DevOps.

En nuestro caso DevOps se encargara de esta actividad. 

Asignación de nombres de branches

Considerar la HU de Jira para nombrar los branches en los que se subirá el código del sprint, por ejemplo:

  • feature/PALO-231

Jira Legacy
serverSystem Jira
serverId08c95066-e26d-357f-9c44-10e77235956c
keyPALO-168

Fecha

Autor

Descripción del cambio

Ivan Rodriguez (Unlicensed)

Se agrega la sección de: Consideraciones para el desarrollo de Token Digital