En el mundo del desarrollo de software, es evidente que la innovación tecnológica ha sido un pilar fundamental para facilitar y mejorar el proceso de creación de aplicaciones y sistemas. En esta era digital, la IA (Inteligencia Artificial) ha adquirido un papel protagonista y ha demostrado ser un aliado excepcional para los desarrolladores. Uno de los exponentes más destacados de la IA aplicada al lenguaje natural es ChatGPT, un modelo de lenguaje desarrollado por OpenAI, cuya versatilidad y potencia han generado un gran impacto en el ámbito del software.

Hace algunos posts os hablábamos de la IA generativa o la explicabilidad de la IA, pues hoy veremos cómo ChatGPT puede ayudar al mundo del desarrollo de software, analizando sus ventajas y desventajas.

Además, proporcionaremos ejemplos de instrucciones a ChatGPT para tareas específicas en Java, Spring Boot, arquitectura hexagonal, Domain-Driven Design (DDD), Docker y pruebas (testing). Estos ejemplos ilustrarán cómo esta IA puede agilizar y mejorar diversas etapas del proceso de desarrollo, optimizando la eficiencia y liberando a los/as desarrolladores/as de tareas rutinarias, sin olvidarnos del lado humano, puesto que esta herramienta no es infalible y necesita de un rigor y supervisión para evitar resultados inesperados.

Automatización de tareas rutinarias

Una de las formas más valiosas en las que ChatGPT puede ayudar a los desarrolladores es automatizando tareas repetitivas y rutinarias. Por ejemplo, al crear una aplicación Java utilizando el framework Spring Boot, es común tener que configurar varias dependencias, anotaciones y propiedades. En lugar de escribir estas configuraciones manualmente, se puede instruir a ChatGPT para que genere un proyecto básico de Spring Boot con las dependencias y la configuración inicial.

Vamos a ver algunos ejemplos que van más allá de enseñar un algoritmo al usuario.

Ejemplo 1: algoritmo simple

Usuario: “Enséñame un algoritmo java para poder calcular la trayectoria de un vuelo”

Respuesta de ChatGPT: “Aquí tienes un ejemplo de un algoritmo en Java que puede calcular la trayectoria de un vuelo basado en la distancia y el ángulo de despegue:”

import java.util.Scanner;

public class CalculadoraTrayectoriaVuelo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Ingrese la distancia del vuelo en kilómetros: ");
        double distancia = scanner.nextDouble();

        System.out.print("Ingrese el ángulo de despegue en grados: ");
        double angulo = scanner.nextDouble();

        // Convertir el ángulo de grados a radianes
        double anguloRadianes = Math.toRadians(angulo);

        // Calcular la trayectoria vertical y horizontal
        double trayectoriaVertical = distancia * Math.sin(anguloRadianes);
        double trayectoriaHorizontal = distancia * Math.cos(anguloRadianes);

        System.out.println("La trayectoria vertical del vuelo es: " + trayectoriaVertical + " kilómetros");
        System.out.println("La trayectoria horizontal del vuelo es: " + trayectoriaHorizontal + " kilómetros");

        scanner.close();
    }
}

Este algoritmo solicita al usuario ingresar la distancia del vuelo en kilómetros y el ángulo de despegue en grados. Luego, calcula la trayectoria vertical y horizontal del vuelo utilizando las fórmulas trigonométricas. Finalmente, muestra los resultados en la consola.

Recuerda que este es solo un ejemplo básico y no tiene en cuenta otros factores como la velocidad del viento, la altitud, la curvatura de la Tierra, entre otros, que pueden influir en la trayectoria real de un vuelo.

Vamos a ir un paso más y le pedimos algo más elaborado:

Ejemplo 2: proyecto base

Usuario: “Necesito crear un proyecto de Spring Boot para una aplicación web. ¿Puedes ayudarme a generar un proyecto base con las dependencias necesarias y una clase de controlador simple?"

Respuesta de ChatGPT: "¡Claro! Aquí tienes los pasos para generar un proyecto base de Spring Boot:”

1. Abre el IDE de tu preferencia y crea un nuevo proyecto de Spring Boot.

2. Agrega las dependencias necesarias en tu archivo pom.xml o build.gradle, como 'spring-boot-starter-web' para habilitar el soporte web y 'spring-boot-starter-test' para las pruebas.

3. Crea una clase de controlador anotada con '@RestController' y define un método que maneje una solicitud HTTP GET.

4. Ejecuta la aplicación y accede a la URL http://localhost:8080 para verificar que el controlador responda correctamente.

Con estos pasos, tendrás un proyecto de Spring Boot con una clase de controlador básica lista para comenzar. Eso sí, tenemos un esqueleto que no hace nada y quizá sea mejor tener arquetipos especializados de compañía. Además, Spring te da starters que compilan y arrancan sin problemas.

Ejemplo 3: recibir instrucciones de conceptos de arquitectura

La arquitectura hexagonal y DDD son enfoques que promueven un diseño de software claro, flexible y centrado en el dominio del problema. Al emplear estos conceptos, es posible lograr una separación clara entre la lógica de negocio y la infraestructura técnica. ChatGPT puede brindar orientación sobre cómo estructurar un proyecto siguiendo estos principios.

¿Qué pasa si lo intentamos?

Usuario: "Estoy interesado en implementar la arquitectura hexagonal y DDD en mi proyecto Java. ¿Puedes proporcionarme algunos consejos para organizar las capas y definir los dominios?"

Respuesta de ChatGPT: "¡Por supuesto! Aquí tienes algunos pasos para implementar la arquitectura hexagonal y DDD:”

1. Divide tu proyecto en tres capas principales: dominio, aplicación y adaptadores.

2. En la capa de dominio, define las entidades principales y los agregados que representan los conceptos clave de tu dominio. También puedes incluir interfaces de repositorio y servicios de dominio.

3. En la capa de aplicación, implementa los casos de uso específicos de tu aplicación utilizando los servicios de dominio. Estos casos de uso pueden ser expresados como comandos o consultas.

4. En la capa de adaptadores, implementa las clases que interactúan con la infraestructura técnica, como adaptadores de base de datos, adaptadores de servicios externos y controladores web.

5. Utiliza interfaces y contratos claros para definir las interacciones entre las capas y mantener una separación adecuada.

Siguiendo estos pasos, te ayudará a crear algo con arquitectura hexagonal y DDD en tu proyecto, lo que facilitará la evolución y mantenimiento del software en el tiempo. Eso sí, no te evita que tengas que tener conocimientos para poder implementar la lógica.

Ejemplo 4: contenerización con Docker facilísima

La contenerización con Docker ha revolucionado la forma en que se desarrollan, implementan y escalan las aplicaciones. ChatGPT puede brindar instrucciones sobre cómo configurar y trabajar con contenedores Docker para facilitar el despliegue de aplicaciones en diferentes entornos.

Qué nos diría ChatGPT…

Usuario: "¡Hey, ChatGPT! Estoy interesado en contenerizar mi aplicación Spring Boot con Docker. ¿Puedes ayudarme con los pasos para crear una imagen de Docker y ejecutar mi aplicación en un contenedor?"

Respuesta de ChatGPT: "¡Por supuesto! Aquí tienes los pasos para contenerizar tu aplicación Spring Boot con Docker:"

1. Asegúrate de tener Docker instalado en tu máquina.

2. Crea un archivo llazado Dockerfile en la raíz de tu proyecto. Este archivo contendrá las instrucciones para construir la imagen de Docker.

3. En el Dockerfile, especifica una imagen base de Java que sea compatible con la versión de Java utilizada en tu aplicación.

4. Copia los archivos necesarios de tu proyecto al contenedor utilizando la instrucción COPY.

5. Configura los comandos necesarios para compilar y ejecutar tu aplicación dentro del contenedor, utilizando las herramientas de construcción de tu proyecto, como Maven o Gradle.

6. Ejecuta el comando 'docker build' en el directorio que contiene el Dockerfile para construir la imagen de Docker.

7. Una vez que la imagen se haya construido, ejecuta el comando 'docker run' para iniciar un contenedor basado en esa imagen.

Siguiendo estos pasos, tendrás tu aplicación Spring Boot contenerizada con Docker, lo que te permitirá desplegarla de manera más eficiente y consistente en diferentes entornos.

Evidentemente, no es todo tan sencillo, pero es muy potente, y todo depende de cómo de concisos seamos.

Ejemplo 5: guía en pruebas automatizadas

Las pruebas automatizadas son cruciales para garantizar la calidad y el correcto funcionamiento de las aplicaciones. ChatGPT puede ayudar a generar instrucciones para configurar y ejecutar pruebas automatizadas utilizando frameworks populares como JUnit y Mockito.

Veamos qué sucede:

Usuario: "Me gustaría saber cómo puedo configurar y ejecutar pruebas unitarias en mi proyecto Java utilizando JUnit y Mockito. ¿Puedes proporcionarme algunos pasos básicos?"

Respuesta de ChatGPT: "¡Por supuesto! Aquí tienes los pasos para configurar y ejecutar pruebas unitarias con JUnit y Mockito:”

1. Asegúrate de que tu proyecto esté configurado con las dependencias de JUnit y Mockito en tu archivo pom.xml o build.gradle.

2. Crea una clase de prueba para cada clase que desees probar. Estas clases de prueba deben estar en el mismo paquete que las clases que estás probando.

3. Anota tus métodos de prueba con la anotación '@Test' para indicar que son casos de prueba.

4. Utiliza las anotaciones '@Before' y '@After' para configurar el estado inicial y realizar limpieza después de cada prueba, respectivamente.

5. Utiliza las anotaciones '@Mock' y '@InjectMocks' para simular objetos dependientes y para inyectar mocks en la clase bajo prueba.

6. Utiliza los métodos de aserción proporcionados por JUnit, como 'assertEquals', 'assertTrue' y 'assertNotNull', para verificar el comportamiento esperado de tu código.

Siguiendo estos pasos, podrás configurar y ejecutar pruebas unitarias utilizando JUnit y Mockito, lo que te ayudará a garantizar la calidad y la integridad de tu código."

No está mal, ¿verdad?

Ejemplo 6: documentación de API con Swagger

La documentación de la API es esencial para facilitar la comprensión y el uso de los servicios que ofrece una aplicación. ChatGPT puede brindar instrucciones sobre cómo integrar y configurar Swagger, una herramienta popular para generar documentación de API interactiva y amigable.

Ejemplo de instrucción a ChatGPT:

Usuario: "Me gustaría documentar mi API de Spring Boot utilizando Swagger. ¿Puedes darme una guía básica sobre cómo configurarlo?"

Respuesta de ChatGPT: "¡Claro! Aquí tienes los pasos básicos para configurar Swagger en tu proyecto Spring Boot:”

1. Asegúrate de tener las dependencias necesarias de Swagger en tu archivo pom.xml o build.gradle.

2. Agrega la anotación '@EnableSwagger2' a tu clase de configuración principal, que suele ser la clase que contiene el método 'main' de tu aplicación.

3. Configura un bean de tipo 'Docket' en tu clase de configuración, donde puedes personalizar la información de tu API, como el título, la descripción y la versión.

4. Utiliza las anotaciones '@Api' y '@ApiOperation' en tus controladores y métodos de controlador respectivamente, para describir la funcionalidad de tu API.

5. Ejecuta tu aplicación y accede a la URL http://localhost:8080/swagger-ui.html para ver la documentación generada automáticamente por Swagger.

Siguiendo estos pasos, prácticamente podrás configurar Swagger en tu proyecto Spring Boot y generar una documentación interactiva y fácil de usar para tu API.

Ejemplo 7: proyecto y funcionalidad básica

Muy, muy potente…

Usuario: “Ayúdame a crear un microservicio con springboot, dockerizado, que tenga un endpoint que le pase 2 números y me retorne la suma de ambos, además debe persistir la entrada, la respuesta y la hora de la solicitud. Utiliza H2 en memoria, genera la documentación con swagger 2 y elabora tests básicos. Todo con arquitectura hexagonal”

Respuesta de ChatpGPT: ¡Claro! Aquí tienes un ejemplo de cómo puedes crear un microservicio con Spring Boot en Java, siguiendo la arquitectura hexagonal, dockerizado, con un endpoint para sumar dos números, persistiendo la entrada, la respuesta y la hora de la solicitud. Utilizaremos H2 en memoria, generaremos la documentación con Swagger 2 y elaboraremos tests básicos.”

1. Crea un nuevo proyecto Spring Boot utilizando Maven. Puedes hacerlo desde la línea de comandos con el siguiente comando:

mvn archetype:generate -DgroupId=com.example -DartifactId=sum-service -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

2. Abre el archivo “pom.xml” y agrega las siguientes dependencias de Spring Boot, H2, Swagger 2 y JSON:

<dependencies>
    <!-- Dependencias de Spring Boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Dependencia de H2 -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Dependencia de Swagger 2 -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>

    <!-- Dependencia de Swagger UI -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>

    <!-- Dependencia de JSON -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
</dependencies>

3. Crea la estructura de carpetas para seguir la arquitectura hexagonal. Puedes organizarlo de la siguiente manera:

com.example
├── application
│   └── SumService.java
├── domain
│   ├── model
│   │   └── SumRequest.java
│   ├── repository
│   │   └── SumRequestRepository.java
│   └── service
│       └── SumServiceInterface.java
└── infrastructure
    ├── persistence
    │   └── SumRequestRepositoryImpl.java
    └── web
        └── controller
            └── SumController.java

4. Crea la clase SumRequest en el paquete com.example.domain.model para representar la entrada de la solicitud. Esta clase contendrá los dos números a sumar y se utilizará para la persistencia en la base de datos. Aquí tienes un ejemplo:

package com.example.domain.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class SumRequest {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private int num1;
    private int num2;

    // Getters y setters

    // Constructor vacío y constructor con parámetros
}

5. Crea la interfaz SumServiceInterface en el paquete com.example.domain.service para definir la lógica de negocio de la suma. Aquí tienes un ejemplo:

package com.example.domain.service;

public interface SumServiceInterface {
    int sum(int num1, int num2);
}

6. Implementa la interfaz SumServiceInterface en una clase concreta llamada SumService en el paquete com.example.application. Aquí tienes un ejemplo:

package com.example.application;

import com.example.domain.service.SumServiceInterface;
import org.springframework.stereotype.Service;

@Service
public class SumService implements SumServiceInterface {

    @Override
    public int sum(int num1, int num2) {
        return num1 + num2;
    }
}

7. Crea la interfaz SumRequestRepository en el paquete com.example.domain.repository para manejar las operaciones de persistencia de SumRequest en la base de datos. Aquí tienes un ejemplo:

package com.example.domain.repository;

import com.example.domain.model.SumRequest;

public interface SumRequestRepository {
    SumRequest save(SumRequest sumRequest);
}

8. Implementa la interfaz SumRequestRepository en una clase concreta llamada SumRequestRepositoryImpl en el paquete com.example.infrastructure.persistence. Esta implementación utilizará el repositorio de Spring Data JPA para interactuar con la base de datos H2. Aquí tienes un ejemplo:

package com.example.infrastructure.persistence;

import com.example.domain.model.SumRequest;
import com.example.domain.repository.SumRequestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class SumRequestRepositoryImpl implements SumRequestRepository {

    private final SumRequestJpaRepository sumRequestJpaRepository;

    @Autowired
    public SumRequestRepositoryImpl(SumRequestJpaRepository sumRequestJpaRepository) {
        this.sumRequestJpaRepository = sumRequestJpaRepository;
    }

    @Override
    public SumRequest save(SumRequest sumRequest) {
        return sumRequestJpaRepository.save(sumRequest);
    }
}

9. Crea la clase SumRequestJpaRepository que extienda JpaRepository para manejar las operaciones de persistencia de SumRequest en la base de datos. Aquí tienes un ejemplo:

package com.example.infrastructure.persistence;

import com.example.domain.model.SumRequest;
import org.springframework.data.jpa.repository.JpaRepository;

public interface SumRequestJpaRepository extends JpaRepository<SumRequest, Long> {
}

10. Crea la clase SumController en el paquete com.example.infrastructure.web.controller para manejar las solicitudes HTTP y exponer el endpoint de suma. Aquí tienes un ejemplo:

package com.example.infrastructure.web.controller;

import com.example.application.SumService;
import com.example.domain.model.SumRequest;
import com.example.domain.repository.SumRequestRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;

@RestController
public class SumController {

    private final SumService sumService;
    private final SumRequestRepository sumRequestRepository;

    @Autowired
    public SumController(SumService sumService, SumRequestRepository sumRequestRepository) {
        this.sumService = sumService;
        this.sumRequestRepository = sumRequestRepository;
    }

    @GetMapping("/sum")
    public ResponseEntity<Integer> sumNumbers(
            @RequestParam("num1") int num1,
            @RequestParam("num2") int num2
    ) {
        int sum = sumService.sum(num1, num2);

        SumRequest sumRequest = new SumRequest();
        sumRequest.setNum1(num1);
        sumRequest.setNum2(num2);
        sumRequest.setResult(sum);
        sumRequest.setRequestTime(LocalDateTime.now());

        sumRequestRepository.save(sumRequest);

        return ResponseEntity.ok(sum);
    }
}

11. Configura la base de datos H2 y Swagger 2 en la clase de configuración principal de Spring Boot. Agrega las siguientes anotaciones y métodos a la clase SumServiceApplication:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
public class SumServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SumServiceApplication.class, args);
    }

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {

        @Bean
        public Docket api() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.example.infrastructure.web.controller"))
                    .paths(PathSelectors.any())
                    .build()
                    .apiInfo(apiInfo());
        }

        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("Sum Service API")
                    .description("API para sumar dos números")
                    .version("1.0")
                    .build();
        }
    }
}

12. Por último, crea una configuración Docker para contenerizar la aplicación. Crea un archivo llamado Dockerfile en la raíz del proyecto con el siguiente contenido:

FROM openjdk:11-jdk

WORKDIR /app

COPY target/sum-service.jar /app

CMD ["java", "-jar", "sum-service.jar"]

13. Ahora puedes construir la imagen de Docker ejecutando el siguiente comando en el directorio del proyecto:

docker build -t sum-service .

!4. Una vez que la imagen de Docker se haya construido correctamente, puedes ejecutar el contenedor utilizando el siguiente comando:

docker run -p 8080:8080 sum-service

Ahora deberías tener el microservicio en ejecución y disponible en http://localhost:8080/sum. Puedes probar el endpoint pasando los parámetros num1 y num2 como query parameters en la URL y obtendrás la suma de ambos números.

Recuerda que este es solo un ejemplo básico para ilustrar cómo crear un microservicio con Spring Boot y dockerizado.

Puedes personalizar y ampliar el código según tus necesidades y requisitos específicos. No voy a negar que es algo muy potente, aunque hay que hacer algunas modificaciones para tener un microservicio que hacía lo que había solicitado, quizá habiendo sido más preciso.

Conclusión

En mi opinión, ChatGPT puede ser una herramienta muy útil en el mundo del desarrollo de software. A través de sus capacidades de generación de texto, puede ofrecer orientación, sugerencias y ejemplos en diversos aspectos, desde la generación de código hasta la arquitectura y la implementación de tecnologías emergentes.

Sin embargo, es importante tener en cuenta sus limitaciones y utilizarlo como una herramienta complementaria, no como un reemplazo de la experiencia y el juicio humano.

También es importante tener en cuenta la sensibilidad del código, no podemos dejar que todo lo haga ChatGPT ni facilitar cierta información, ya sean datos o código. Es decir, no podemos pedirle que nos resuelva un problema de X cliente porque se daría a conocer dicho problema o que nos resuelva cierto algoritmo que sea privado. En resumen, es una herramienta de apoyo que nos puede ayudar, centralizando y agilizando las búsquedas que haríamos en Google.

Al aprovechar las capacidades de ChatGPT de manera inteligente y crítica, los/as desarrolladores/as pueden mejorar la eficiencia, la calidad y la innovación en el desarrollo de software, manteniéndose a la vanguardia del paradigma digital en constante evolución.

Os recomiendo que echéis un vistazo y exploréis por vuestra cuenta. Tan solo hay que registrarse en la web de ChatGPT.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete

Estamos comprometidos.

Tecnología, personas e impacto positivo.