Original article: https://www.freecodecamp.org/news/developer-productivity-with-github-copilot/

Hay una gran cantidad de herramientas de inteligencia artificial (IA) para desarrolladores en el mercado, pero para mi GitHub Copilot se diferencia del resto por su usabilidad, integración limpia al IDE y la palpable diferencia en la productividad al utilizarlo.

Copilot ofrece una variedad de herramientas de Inteligencia Artificial que han simplificado radicalmente mi experiencia como desarrollador. Lo usé para generar código, pruebas e incluso aplicaciones simples. También es genial para depurar, refactorizar y documentar código existente.

Curiosamente, usar Copilot causo que desarrolle funciones más rápido de lo que las partes interesadas del negocio pueden revisarlas.

Es importante remarcar que, las herramientas de Inteligencia Artificial, incluido Copilot pueden estar superequivocadas, disculparse (o no) cuando las corregimos y, luego con total confianza, producir el mismo error.

Pero, siempre que estés atento a los puntos débiles de las herramientas de Inteligencia Artificial, y, tengas suficientes conocimientos para reconocer cuando se equivocan, vas a poder mitigarlos en el camino hacia una productividad sustancialmente mejorada.

Como configurar GitHub Copilot

Para configurar y ver el uso básico de Copilot, te recomiendo que consultes la documentación oficial (en español). Puedes agregar Copilot a una cuenta personal o comercial, hay una prueba gratuita y, tiene un precio razonable luego del periodo de prueba.

Después de agregar Copilot a tu cuenta de GitHub, querrás instalar los plugins a tu IDE y logguearte para empezar a utilizarlo.

En este artículo, vamos a utilizar estas extensiones de Visual Studio Code:

EXTENSIONDESCRIPCION
CopilotProgramador de pares potenciado por Inteligencia Artificial con sugerencias de codigo dentro del IDE
Copilot ChatChat interactivo embebido en el IDE
Copilot VoiceAsistente de voz (permite programar utilizando tu voz)

Notas:

  1. Esta información está actualizada al momento de escribir este artículo, pero probablemente cambie a medida que GitHub avance en el desarrollo de sus productos.
  2. Todavía no recibí acceso a Copilot Voice, por lo que mi perspectiva está limitada y basada en la documentación ofrecida por GitHub.

Privacidad

Antes de sumergirnos en algunos casos de uso de Copilot, una aclaración rápida en cuanto a la privacidad: Básicamente, si confías en GitHub para alojar tu código fuente, puedes confiar en lo que harán con los prompts que envíes a Copilot y tus fragmentos de código. [Por favor, revisa las preguntas frecuentes (en inglés) y la declaración de privacidad]

Casos de uso para GitHub Copilot

Los casos de uso de GitHub Copilot son numerosos, y pueden realmente agilizar el proceso de desarrollo.

A continuación, te dejo una lista de lo que puedes hacer con las extensiones de Copilot:

CATEGORIAEXTENSION(ES)
Generacion de codigoCopilot, Copilot Voice
Explicacion del codigoCopilot Chat, Copilot Voice
Traduccion de lenguajeCopilot Chat
DepurarCopilot Chat
RefactorizarCopilot Chat
Creacion de pruebasCopilot, Copilot Chat
Revision de codigoCopilot Chat
Desarrollo guiado por vozCopilot Voice

Generación de código

Copilot es conocido por su capacidad para finalizar el código. Si escribís un comentario o si escribís el principio de una línea de código, Copilot te sugerirá una solución que puedes aceptar, ignorar o, incluso explorar alternativas. Esta característica es conocida como "texto fantasma".

Una vez que instalada la extensión de Copilot e iniciada la sesión, utilizarlo es tan sencillo como tipear instrucciones y pulsar la tecla Tabulador a medida que van surgiendo las sugerencias.

copilot_completar2
Un comentario en Ruby que Copilot uso para crear un método.

Llevando un poco más allá la función de completar, Copilot puede tomar un prompt y usarlo para construir toda una aplicación.

Le pedí que creara una API REST en Node con funciones ABM para "productos", y género código funcional. Esto es impresionante;  inclusive le di el mismo prompt a ChatGPT, que también me dio instrucciones de como realizar el proyecto, lo cuan es también impresionante.

Copilot Voice puede tanto escribir como editar código basado en comandos de voz, la mayoría de las veces es más rápido utilizar Copilot con el teclado que dictando una a una las líneas de código usando Voice, pero es totalmente factible utilizar Voice para crear y ejecutar código sin necesidad de utilizar el teclado, algo mucho más que útil para personas que posean alguna dificultad para usar el teclado.

Explicación de código

A menudo debí sentarme frente a la PC para intentar deducir que es lo que un boque de código está haciendo. Algunas veces es código heredado (Legacy Code) del cual no entiendo el contexto del negocio, o a veces está usando una librería particular que nunca use, a veces también debo reconocer que maldije a la persona que lo escribió, incluso si esa persona fui yo.

A continuación te muestro el código generado por Copilot con el prompt que utilice antes "Un API REST en Node...":

app.get('/products/:id', (req, res) => {
  const id = req.params.id;
  const product = products.find((p) => p.id === id);
  if (product) {
    res.json(product);
  } else {
    res.status(404).json({ error: 'El producto no fue encontrado' });
  }
});

Tome el código y se lo di como entrada a Copilot para que me explicara el código, esta fue su respuesta:

Aquí está la explicación del código:

  1. Definimos la ruta con la ruta /productos/:id. Los dos puntos : en la ruta indica que es un parámetro de la ruta. El valor del parámetro de la ruta estará disponible en req.params, por ejemplo, si la ruta es /products/:id y hacemos una solicitud a /products/5, entonces el valor de req.params será { id: 5}.
  2. Obtenemos el id de req.params y buscamos el producto con el id que obtuvimos del arreglo de productos. Si existe el producto lo mostramos, si no existe devolvemos un código de error 404 con el mensaje "El producto no fue encontrado".

Este es un segmento de código sencillo, y la respuesta brindada por Copilot es clara y directa, sería bastante útil agregar esto como un comentario sobre el código de la función.

Otro buen ejemplo de uso son las expresiones regulares, entiendo como funcionan, pero a veces no tengo la paciencia para entender que es lo que la expresión regular esta haciendo. Le di como entrada a Copilot esté gigantesca expresión regular para la validación de un correo electrónico:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Explico la expresión regular a un alto nivel, indicando que está dividido en la parte local y el dominio, representado antes y después del símbolo "@" en una dirección de correo electrónico. Luego, describió los caracteres permitidos en cada parte, bastante útil.

Traducir código (entre lenguajes)

A menudo se requiere que los desarrolladores aprendamos rápidamente nuevos lenguajes y frameworks, Copilot Chat hace esta tarea bastante sencilla, aquí te muestro un arreglo de productos en JavaScript que fue convertido a Ruby por Copilot:

let productos = [
  { id: '1', descripcion: 'Producto 1', precio: 10.99 },
  { id: '2', descripcion: 'Producto 2', precio: 19.99 },
  { id: '3', descripcion: 'Producto 3', precio: 7.99 }
];
productos = [
  { id: '1', descripcion: 'Producto 1', precio: 10.99 },
  { id: '2', descripcion: 'Producto 2', precio: 19.99 },
  { id: '3', descripcion: 'Producto 3', precio: 7.99 }
]

Este es un ejemplo muy sencillo, así que transformemos esto en una clase y vallamos en sentido contrario (de Ruby a JavaScript):

class Producto
  attr_reader :nombre, :precio

  def initialize(nombre, precio)
    @nombre = nombre
    @precio = precio
  end
end
class Producto {
  constructor(nombre, precio) {
    this.nombre = nombre;
    this.precio = precio;
  }
}

Esto funciono de maravilla, inclusive le pedí que lo transformara en TypeScript y funciono perfecto:

class Producto {
  nombre: string;
  precio: number;

  constructor(nombre: string, precio: number) {
    this.nombre = nombre;
    this.precio = precio;
  }
}

Depurando código

Esta es una de las funciones más útiles que posee Copilot Chat, puedes darle un fragmento de código problemático o el mensaje de error que tienes y el programa te indicara cuál "piensa" que es el error

No recuerdo la cantidad de veces que me arranque los pelos tratando de encontrar un error de sintaxis, la habilidad de Copilot para arreglar errores me hacen más feliz (y me permite conservar mi cabello).

También puedes darle como entrada a Copilot Chat un mensaje de error sin ningún otro prompt y te devolverá el problema que lo ocasiona, en este caso intencionalmente removí un punto del código de la API  REST en Node:

products[productIndex] = { id, ..req.body };

He copiado/pegado el mensaje de error en el Chat, y me ha respondido con...

req.body

Esto es correcto (la linea y la fuente del error) e incorrecto (ya que debería ser solo un punto). Luego, me dio un fragmento de código con tres puntos, el cual es también correcto.

Como te mencione al principio, siempre debes chequear el trabajo de las herramientas de IA, aun así estoy impresionado con la habilidad de Copilot de tomar un error, describir lo que "piensa" que está mal y, luego sugerir la corrección.

Refactorización

Otro gran caso de uso es la refactorización, consideremos el siguiente código:

req.body

Esto es correcto (la linea y la fuente del error) e incorrecto (ya que debería ser solo un punto). Luego, me dio un fragmento de código con tres puntos, el cual es también correcto.

Como te mencione al principio, siempre debes chequear el trabajo de las herramientas de IA, aun así estoy impresionado con la habilidad de Copilot de tomar un error, describir lo que "piensa" que está mal y, luego sugerir la corrección.

Refactorización

Otro gran caso de uso es la refactorización, consideremos el siguiente código:

def precio_con_descuento
  precio - (precio * tasa_de_descuento)
end

Este codigo para calcular descuentos no realiza verificaciones para validar que no le demos valores nulos, cadenas de texto que deberían ser números o valores razonables para  "precio" o "tasa_de_descuento", necesitamos que el código haga lo siguiente:  

  1. Asegurarse que "precio" sea un Integer o Float (no nulo)
  2. Asegurarse que "precio" no sea negativo
  3. Asegurarse que "tasa_de_descuento" sea un Float (no nulo)
  4. Asegurarse que "tasa_de_descuento" no sea negativo y menor o igual que 1

Copilot Chat puede manejar esto fácilmente...

def precio_con_descuento
  raise ArgumentError, "El precio debe ser un número positivo" unless precio.is_a?(Numeric) && precio >= 0
  raise ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1" unless tasa_de_descuento.is_a?(Numeric) && tasa_de_descuento >= 0 && tasa_de_descuento <= 1

  precio - (precio * tasa_de_descuento)
end

Generación de pruebas

Estrictamente hablando, la generación de pruebas es una subsección de la "Generación de código", pero es tan útil, que sentí que merecía su propia sección.

Generar pruebas unitarias para el código puede ser tedioso si estás tratando de cubrir caminos felices y tristes, casos principales de uso y casos extremos. Nuestra función de "precio_con_descuento" necesita casos de prueba para asegurarnos que se genere un aviso de error si "precio" o "tasa_de_descuento" no cumplen con los requisitos. Además, queremos probar lo siguiente:

  1. Un "precio" sin una "tasa_de_descuento"
  2. Un "precio" con una "tasa_de_descuento" razonable (por ejemplo, un 10% de descuento)
  3. Un "precio" con un 100% de "tasa_de_descuento" (por ejemplo, si queremos regalar el producto)

Con estos y nuestros casos de error anteriores, esto es lo que Copilot Chat genero, despues de alguno pequeños ajustes (re-prompting) y cambiando de Minitest a Rspec:

RSpec.describe Producto do
  describe "#precio_con_descuento" do
    context "cuando se proporciona un precio válido y una tasa de descuento" do
      it "retorna el precio con el descuento aplicado" do
        producto = Producto.new("Producto de Prueba", 100, 0.2)
        expect(producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento)).to eq(80)
      end
    end

    context "cuando se proporciona un precio nulo" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", nil, 0.2)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "El precio debe ser un número positivo")
      end
    end

    context "cuando se proporciona un precio menor que 0" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", -100, 0.2)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "El precio debe ser un número positivo")
      end
    end

    context "cuando se proporciona una tasa de descuento nula" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", 100, nil)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1")
      end
    end

    context "cuando se proporciona una tasa de descuento menor que 0" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", 100, -0.2)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1")
      end
    end

    context "cuando se proporciona una tasa de descuento mayor que 1" do
      it "lanza un ArgumentError con un mensaje apropiado" do
        producto = Producto.new("Producto de Prueba", 100, 1.5)
        expect { producto.precio_con_descuento(producto.precio, producto.tasa_de_descuento) }.to raise_error(ArgumentError, "La tasa de descuento debe ser un número positivo entre 0 y 1")
      end
    end
  end
end

Una prueba para entradas válidas, cinco para entradas incorrectas, los seis funcionan, ¡y yo no tuve que escribirlos!

Revisión de código

Una de las características destacables de Github Copilot es la elaboración de los resúmenes de solicitudes de incorporación de cambios de Copilot. cabe destacar que esta función está solo disponible para quienes posean una suscripción de Github Copilot Enterprise, aquí te presento algunos puntos clave:

  • Generación automática – Deje que Copilot complete la plantilla de Pull Request o explique el código.
  • Generación de pruebas – Genera pruebas para el código basado en el análisis de Copilot
  • Texto fantasma – Reciba sugerencias mientras escribe el Pull Request

Desarrollo guiada por voz

¡Antes conocida como "Hey, Github!", Copilot Voice te permite utilizar la voz para generar los prompts para interactuar con el código, Voice cuenta con estas impresionantes capacidades:

  • Escribir/Editar código – Usa comandos de voz para disparar sugerencias de código de Copilot
  • Explora el código – Recorre un archivo sin utilizar el mouse o el teclado
  • Controla el IDE – Dispare cualquier comando de Visual Studio Code utilizando su voz
  • Resumen del código – Obtenga resúmenes de bloques de código

Resumen

GitHub rápidamente está generando una explosión de productividad con toda la familia de addons Copilot. Está incrementando el tiempo que disfruto programando y reduciendo el que antes gastaba en tareas triviales. Lo animo, querido lector, a seguir de cerca los avances de Copilot, porque se producen rápidamente.

Ignora los artículos sensacionalistas que prometen "un aumento de productividad de 10 veces la que tiene ahora", pero no ignores esta investigación acerca del impacto que Copilot tiene en la productividad y felicidad de los programadores.

Dedique un poco de su tiempo a utilizar las herramientas que Copilot le brinda, póngalo a prueba en su día a día, y, le garantizo que quedará encantado por el efecto que genera en su productividad y felicidad.