domingo, 17 de agosto de 2025

Programando en C# no. 9 (usando Nuget)

En un anterior post hablamos sobre Nuget. El cual es el administrador de paquetes para .NET.

Con Nuget podemos:

  1. Consumir paquetes de terceros. 
  2. Crear nuestros paquetes. 
  3.  Publicar nuestros paquetes.

Nuget está incluido en el .Net Core. Abriremos una consola y teclearemos lo siguiente:

$ mkdir codemonkey 
$ cd codemonkey
$ dotnet new console

Nos ubicaremos en el proyecto creado y listaremos los paquetes:

$ dotnet list package

Mostrará un mensaje indicando que no hay paquetes asociados al proyecto.

Si queremos instalar un paquete podemos hacerlo con Nuget.

El sitio https://www.nuget.org/ tiene un buscador de paquetes. Si queremos, por ejemplo, instalar un conector de BD de MySQL podemos buscarlo. Si lo encuentra, damos clic al enlace y nos mostrará la forma de instalarlo desde dotnet.

Instalando el paquete de MySQL:

$ dotnet add package MySqlConnector --version 2.4.0

Ahora listamos el paquete:

$ dotnet list package

El sitio también provee de ejemplos de cómo usarlo (en algunos paquetes):

// set these values correctly for your database server
var builder = new MySqlConnectionStringBuilder
{
	Server = "your-server",
	UserID = "database-user",
	Password = "P@ssw0rd!",
	Database = "database-name",
};

// open a connection asynchronously
using var connection = new MySqlConnection(builder.ConnectionString);
await connection.OpenAsync();

// create a DB command and set the SQL statement with parameters
using var command = connection.CreateCommand();
command.CommandText = @"SELECT * FROM orders WHERE order_id = @OrderId;";
command.Parameters.AddWithValue("@OrderId", orderId);

// execute the command and read the results
using var reader = await command.ExecuteReaderAsync();
while (reader.Read())
{
	var id = reader.GetInt32("order_id");
	var date = reader.GetDateTime("order_date");
	// ...
}

Para ASP .Net tendríamos:

var builder = WebApplication.CreateBuilder(args);

// use AddMySqlDataSource to configure MySqlConnector
builder.Services.AddMySqlDataSource(builder.Configuration.GetConnectionString("Default"));

var app = builder.Build();

// use dependency injection to get a MySqlConnection in minimal APIs or in controllers
app.MapGet("/", async (MySqlConnection connection) =>
{
    // open and use the connection here
    await connection.OpenAsync();
    await using var command = connection.CreateCommand();
    command.CommandText = "SELECT name FROM users LIMIT 1";
    return "Hello World: " + await command.ExecuteScalarAsync();
});

app.Run();

Nuget nos permite encontrar, agregar y compartir paquetes para nuestras aplicaciones. Como desarrolladores sabemos que muchas veces un paquete puede ahorrarnos horas o días (e incluso más tiempo) de desarrollo.

Ejemplo. Queremos hacer una sencilla gráfica, pero nos llevaría bastante tiempo crear un paquete que nos permita hacerlo. La solución sería buscarlo e instalarlo.

La opción ideal sería ScottPlot, ya que es una biblioteca de gráficos similar a Matplotlib. La cual ofrece un equilibrio ideal entre facilidad de uso, rendimiento, integración nativa y documentación extensa. Eso es lo que buscamos.

La instalaremos:

$ dotnet add package ScottPlot --version 5.0.55

Si la instalación fue correcta, saldrá un mensaje indicando que ya lo tenemos integrado a nuestro proyecto. Usaremos el código de ejemplo:

Program.cs

double[] dataX = { 1, 2, 3, 4, 5 };
double[] dataY = { 1, 4, 9, 16, 25 };

ScottPlot.Plot myPlot = new();
myPlot.Add.Scatter(dataX, dataY);
myPlot.SavePng("quickstart.png", 400, 300);

Código completo:

Program.cs

using System;
using ScottPlot;


class Program
{

    public static void Main(string[] args)
    {
        Test();
    }


   private static void Test()
   {
       double[] dataX = { 1, 2, 3, 4, 5 };
       double[] dataY = { 1, 4, 9, 16, 25 };

       ScottPlot.Plot myPlot = new();
       myPlot.Add.Scatter(dataX, dataY);
       myPlot.SavePng("quickstart.png", 400, 300);
       Console.WriteLine("Gráfico creado.");
   }

}

Compilamos y ejecutamos:

$ dotnet build
$ dotnet run

Si ejecutó correctamente la aplicación, entonces se creará un gráfico llamado ``quickstart.png``.

En conclusión, si eres desarrollador .NET, entonces con Nuget encontrarás los paquetes necesarios para tus aplicaciones.

Enlaces:

https://www.nuget.org/
https://learn.microsoft.com/es-es/nuget/what-is-nuget
https://codemonkeyjunior.blogspot.com/2019/06/instalar-paquetes-nuget-con-dotnet.html



sábado, 16 de agosto de 2025

Helm, una herramienta para administrar paquetes Kubernetes

Helm es una herramienta software que nos ayuda a encontrar, compartir y usar software construido para Kubernetes.

Salvando las distancias es como un CPAN o cualquier otro gestor de paquetes.

Como hemos hablado en otros posts, Kubernetes es un gestor de contenedores que se encarga del mantenimiento, organización y la escalabilidad de nuestros contenedores (que pueden estar hechos o no con Docker). Helm vendría siendo su propio CPAN. Si se requiere un paquete para Kubernetes, esta herramienta la podrá buscar e instalar en nuestro ambiente. También podrá permitirnos agregar repositorios donde podremos descargar paquetes o compartir los nuestros.

Helm se une a las decenas (¿o centenas o quizás miles?) de herramientas DevOps que son populares hoy en día.

Esta herramienta requiere cierto conocimiento sobre herramientas como Docker y, por supuesto, Kubernetes.

La documentación oficial provee guías sobre su uso. Comandos de lo básico a lo avanzado y hasta ejemplos de cómo se debería usar.

Un concepto dentro de Helm son los Charts. Según la documentación oficial, los Charts de Helm te ayudan a definir, instalar y actualizar incluso la aplicación de Kubernetes más compleja. Originalmente, el objetivo de Helm era proporcionar a los usuarios una forma mejor de gestionar todos los archivos YAML de Kubernetes que creamos en los proyectos de Kubernetes.

¿Qué es un Chart Helm?

En pocas plabras, es un paquete que contiene toda la información necesaria para implementar una aplicación en Kubernetes.

Los Charts son fáciles de crear, versionar, compartir y publicar - así que puedes comienzar a utilizar Helm y deja de copiar y pegar.

Helm instala todo el árbol de dependencias de un proyecto si ejecuta el comando install para el gráfico de nivel superior. Sólo tiene que ejecutar un único comando para instalar toda su aplicación, en lugar de listar los ficheros a instalar mediante ``kubectl``.

Tampoco olvidar el ``config``, el cual contiene información de configuración que puede fusionarse en un chart empaquetado para crear un objeto releaseable. Y el ``release``, que es una instancia en ejecución de un chart, combinado con un config específico.

Estos son los tres conceptos que debemos tener presentes al usar Helm.

Instalando Helm

Requisitos:

  • Un clúster de Kubernetes configurado y accesible. 
  • Tener la herramienta ``kubectl` instalada y configurada para interactuar con el clúster. 
  •  Un entorno local con acceso a la línea de comandos.

Para instalarlo, puedes ir a este sitio y descargarlo:

https://github.com/helm/helm/releases/tag/v3.18.5

También existe la opción de instalarlo mediante con un administrador de paquetes como Homebrew, chocolatey , scoop o snap:

Homebrew:

$ brew install helm

Chocolatey:

$ choco install kubernetes-helm

Scoop

$ scoop install helm

Snap:

$ sudo snap install helm --classic

Una vez instalado en tu equipo deberás agregarlo a tu PATH. Para validar la instalación, abre una consola y escribe:

$ helm version

Podemos agregar un repositorio:

$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

Buscar un paquete:

$ helm search repo ingress-nginx

Actualizar el repositorio:

$ helm repo update

Continuando con la documentación oficial de Helm, nos ayuda a:

  • Nos permite crear nuevos charts (paquetes) desde cero. 
  • Empaquetar charts en archivos de charts (tgz). 
  • Interactuar con repositorios de charts donde se almacenan charts. 
  • Instalar y desinstalar charts en un clúster Kubernetes existente. 
  • Gestionar el ciclo de lanzamiento de los charts instalados con Helm.

En conclusión, Helm nos ayuda con la gestión de las aplicaciones de Kubernetes y es una herramienta que se ha vuelto esencial en gestiones de DevOps. Es necesario tener nociones semi avanzadas o avanzadas sobre Docker y Kubernetes si le queremos sacar un buen provecho a la herramienta.

Enlaces:

https://helm.sh
https://codemonkeyjunior.blogspot.com/2025/01/kubernetes-como-si-le-explicaras-tu.html
https://www.freecodecamp.org/espanol/news/que-es-un-helm-chart-un-tutorial-para-principiantes-en-kubernetes/
https://learn.microsoft.com/es-es/azure/aks/kubernetes-helm?WT.mc_id=containers-19838-ludossan

domingo, 10 de agosto de 2025

Apache Camel: un framework para integración de sistemas y datos

 

Apache Camel es un framework de integración de código abierto basado en Java que facilita la conexión y comunicación entre diferentes sistemas, aplicaciones o servicios mediante patrones de integración empresarial (EIP). Permite definir rutas de procesamiento de mensajes de forma sencilla, soportando múltiples protocolos y formatos de datos. Además de integraciones más complejas, como conectar APIs o bases de datos.

Nos sirve para:

  • Integración de sistemas: Conecta aplicaciones heterogéneas (ej. bases de datos, APIs, colas de mensajes). 
  • Transformación de datos: Convierte formatos (XML, JSON, etc.). 
  • Enrutamiento de mensajes: Dirige datos entre sistemas según reglas definidas. 
  • Soporte de protocolos: Integra con HTTP, FTP, JMS, Kafka, y más.
  • Automatización: Simplifica flujos de trabajo complejos.

Aunque está diseñado principalmente para entornos Java y se integra bien con aplicaciones basadas en JVM, también soporta otros lenguajes y entornos gracias a su flexibilidad y componentes.

Hagamos un sencillo ejemplo. Un simple "Hola, mundo". Primero debemos tener instalado:

  1. JDK 8 o una versión mayor. 
  2. Maven en su última versión.

Crear un proyecto Maven y agregar esta dependencia al pom.xml:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-core</artifactId>
    <version>4.8.0</version>
</dependency>

Podemos crear el proyecto con estos comandos:

$ mvn archetype:generate -DgroupId=com.codemonkey -DartifactId=HolaMundo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Creamos una clase Java:

HolaMundoCamel.java

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.main.Main;

public class HolaMundoCamel {
    public static void main(String[] args) throws Exception {
        Main camel = new Main();
        camel.configure().addRoutesBuilder(new RouteBuilder() {
            @Override
            public void configure() {
                from("timer:hello?period=2000")
                    .setBody(constant("Hola, Mundo"))
                    .to("log:output");
            }
        });
        camel.run();
    }
}

Construimos el proyecto:

$ mvn clean install

Ejecutamos:

$ mvn exec:java -Dexec.mainClass="HolaMundoCamel"

Cada 2 segundos se mostrará este mensaje:

[main] output INFO  Exchange[ExchangePattern: InOnly, Body: Hola, Mundo]

Apache Camel también se puede usar con Spring Boot y Quarkus.

Enlaces:

https://camel.apache.org/

lunes, 4 de agosto de 2025

OWASP: el Top Ten de las vulnerabilidades de tu aplicación web

OWASP(Open Web Application Security Project) es un proyecto de código abierto dedicado a determinar y combatir las causas que hacen que el software sea inseguro.

Su misión es mejorar la seguridad de las aplicaciones web mediante la concienciación, la educación y la promoción de las mejores prácticas de seguridad.

Este proyecto hace hincapié en un top ten de concientización para desarrolladores y seguridad de aplicaciones web. Básicamente, se trata de un documento que representa un amplio consenso sobre los riesgos de seguridad más críticos para las aplicaciones web.

El top ten de OWASP

El Top Ten de OWASP es una lista de las 10 vulnerabilidades de seguridad más críticas en aplicaciones web.

Aunque son en 10 se presenta un onceavo, ya que la lista no se limita y hay muchos aspectos de seguridad a tomar en cuenta.

  Tema   Significado
A01:2021 – Broken Access Control Control de Acceso Roto: Fallos en la gestión de permisos que permiten a usuarios no autorizados acceder a datos o funciones restringidas.
A02:2021 – Cryptographic Failures Fallos Criptográficos: Uso inadecuado de cifrado, exponiendo datos sensibles como contraseñas o información personal.
A03:2021 – Injection Inyección: Código malicioso (como SQL o comandos) insertado en entradas de usuario, comprometiendo sistemas o bases de datos.
A04:2021 – Insecure Design Diseño Inseguro: Falta de principios de diseño seguro, lo que introduce vulnerabilidades desde la concepción de la aplicación.
A05:2021 – Security Misconfiguration Configuración Incorrecta de Seguridad: Configuraciones débiles o predeterminadas en servidores, frameworks o aplicaciones.
A06:2021 – Vulnerable and Outdated Components Componentes Vulnerables y Desactualizados: Uso de software obsoleto o con vulnerabilidades conocidas, como bibliotecas o frameworks.
A07:2021 – Identification and Authentication Failures Fallas de Autenticación e Identificación: Errores que permiten a atacantes suplantar identidades o eludir autenticaciones.
A08:2021 – Software and Data Integrity Failures Fallas en la Integridad de Datos y Software: Falta de validación de datos o software, permitiendo manipulaciones no autorizadas.
A09:2021 – Security Logging and Monitoring Failures Fallas en el Registro y Monitoreo de Seguridad: Ausencia de logs adecuados o monitoreo, dificultando la detección de ataques.
A10:2021 – Server-Side Request Forgery (SSRF) Falsificación de Peticiones del Lado del Servidor (SSRF): Ataques que inducen al servidor a realizar peticiones no autorizadas a sistemas internos o externos.
A11:2021 – Next Steps Denegación de servicio entre otros.

Como programador, conocer el Top Ten de OWASP te sirve para:

  • Prevenir vulnerabilidades: Identificar y corregir fallos comunes en el código (como inyecciones SQL o autenticación débil) antes de que se conviertan en problemas de seguridad. 
  • Mejorar la seguridad de tus aplicaciones: Aplicar prácticas de desarrollo seguro, como validar entradas, usar cifrado adecuado y gestionar permisos correctamente. 
  • Proteger datos sensibles: Evitar exposición de información de usuarios (contraseñas, datos personales) al mitigar riesgos como fallos criptográficos o SSRF. 
  • Cumplir con estándares: Alinear tus proyectos con normativas de seguridad (como GDPR o PCI-DSS) y demostrar diligencia en auditorías. 
  • Reducir riesgos de ataques: Disminuir la probabilidad de que tu aplicación sea explotada por atacantes, protegiendo la reputación y los recursos de tu organización. 
  • Priorizar esfuerzos: Enfocarte en las vulnerabilidades más críticas y comunes, optimizando tiempo y recursos en el desarrollo. 
  • Educarte y capacitarte: Mantenerte actualizado sobre amenazas emergentes y aprender mejores prácticas de codificación segura.

Enlaces:

https://owasp.org/
https://cheatsheetseries.owasp.org/index.html
https://es.securecodewarrior.com/

sábado, 26 de julio de 2025

Kubernetes en un vistazo

Continuamos con esta serie de entregas sobre Docker y Kubernetes

Según la documentación oficial Kubernetes (k8s) es una plataforma de código abierto para automatizar la implementación, el escalado y la administración de aplicaciones en contenedores.

Básicamente es una plataforma de código abierto que orquesta contenedores (como los de Docker) en grupos distribuidos de servidores.

¿Para qué sirve?

  • Escalar aplicaciones fácilmente (de 1 a 1,000 contenedores sin perder el control).
  • Distribuir carga entre servidores. 
  • Recuperarse automáticamente si algo falla.
  • Declarar el estado ideal (Kubernetes se encarga de mantenerlo).

Es como tener un director de orquesta que sabe cuándo y dónde deben sonar los instrumentos (contenedores) para que la sinfonía (tu app) no se detenga.

Comandos básicos

Observemos ahora algunos de los comandos más usados en Kubernetes.

Crear un Deployment que maneje un Pod:

$ kubectl create deployment hello-node --image=registry.k8s.io/echoserver:1.4

Ver el Deployment:

$ kubectl get deployments

Mostrar los contenedores que están corriendo en un clúster:

$ kubectl get pods

Mostrar los eventos del clúster:

$ kubectl get events

Mostrar la configuración:

$ kubectl config view

Crear o actualizar recursos desde un archivo YAML:

$ kubectl apply -f application.yaml

Mostrar información detallada del Pod:

$ kubectl describe pod mypod

Mostrar los logs del contenedor:

$ kubectl logs mypod

Mostrar todos los recursos:

$ kubectl get all

Eliminar recursos definidos en el archivo YAML:

$ kubectl delete -f application.yaml

Interacción con Docker

En una entrega anterior vimos el flujo de trabajo con Docker.

Ahora imaginemos que tienes una aplicación en un contenedor Docker. Para que Kubernetes la administre, se crea un archivo de configuración (deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mi-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mi-app
  template:
    metadata:
      labels:
        app: mi-app
    spec:
      containers:
      - name: mi-app
        image: usuario/mi-imagen:latest
        ports:
        - containerPort: 80

Ahora desplegamos con Kubernetes:

$ kubectl apply -f deployment.yaml

Se podría usar Docker Swarm en lugar de Kubernetes por simplicidad y rapidez. Sin embargo, si tu proyecto es algo más complejo es mejor usar Kubernetes. Ya que es ideal para arquitecturas complejas, microservicios y entornos empresariales.

Este solo es un pequeño vistazo a lo que es Kubernetes. Continuaremos con este tema en próximas entregas.

Enlaces:

https://kubernetes.io/
https://codemonkeyjunior.blogspot.com/2025/07/docker-conociendo-el-flujo-de-trabajo.html
https://codemonkeyjunior.blogspot.com/2025/01/docker-en-palabras-sencillas.html
https://alquimistadecodigo.blogspot.com/2020/07/docker-imagenes-y-contenedores.html
https://hub.docker.com/
https://alquimistadecodigo.blogspot.com/2020/03/docker-instalacion.html
https://alquimistadecodigo.blogspot.com/2020/08/docker-instalando-una-imagen-de-nimrod.html

domingo, 20 de julio de 2025

Docker: conociendo el flujo de trabajo

 


En esta entrega veremos el flujo de trabajo en Docker.

Tomemos como referencia la siguiente imagen:

Todo inicia con nuestra aplicación (MyApp). Que es la que queremos subir a un contenedor Docker.

Para ello debemos crear un archivo llamado Dockerfile. El cual contendrá todas las dependencias, rutas y configuraciones necesarias para hacer funcionar nuestra aplicación.

Una vez teniendo este archivo, docker se encargará de crear la imagen, la cual es un paquete autocontenido con todo lo necesario para ejecutar la aplicación.

Posteriormente tendremos un contenedor, que es la instancia activa y aislada de la aplicación corriendo en el sistema.

Todo gracias al motor de Docker (Docker Engine), el componente que interpreta el Dockerfile, construye la imagen, lanza el contenedor y gestiona todo ese flujo. Es el corazón del ecosistema Docker.

El SO anfitrión donde reside Docker puede ser un SO Linux, Mac OS o Windows.

Básicamente este es flujo de trabajo de Docker. Omitiendo su interracción con Kubernetes.

Enlaces:

https://codemonkeyjunior.blogspot.com/2025/01/docker-en-palabras-sencillas.html
https://alquimistadecodigo.blogspot.com/2020/07/docker-imagenes-y-contenedores.html
https://hub.docker.com/

Las leyes (no escritas) de la programación (4ta parte)

En un mundo donde la I.A. ha dejado de ser un sueño o fantasía y es usada por la mayoría de las empresas de tecnología e IT el programador deberá saber adaptarse o morir.

Sin embargo, ¿La I.A. supone la muerte de la programación? No, ¡claro que no!

Quien quiera programar deberá saber programar. Así como quien quiera ser escritor deberá saber escribir.

Muchos creen que usar ChatGPT, Copilot, DeepSeek o cualquier otra inteligencia artificial automáticamente los convertirá en programadores. Se equivocan. Quien crea eso terminará dándose de topes en la pared cuando se enfrente a problemas de programación reales. No sabrá como resolverlos cuando la I.A. arroje resultados erróneos o inútiles.

He visto personas que creen que ChatGPT les resolverá todos sus bugs o creará de la nada sus proyectos. Y es por qué no conocen cómo funciona la I.A.

La I.A. no piensa, imita la forma de pensar. Carece de conciencia aunque nos quieran decir lo contrario. No es un Skynet, pero sus creadores lo harán parecer que sí.

Y tampoco es "gratis", ya que el producto final es quien la usa: nosotros.

Y nosotros somos quien la alimentamos, quien le damos retroalimentación, la "entrenamos" de acuerdo a lo que le pedimos, a lo que se le solicita.

ChatGPT, DeepSeek, Grok, etc. accede a sitios web, repositorios de código, base de datos propias para "crear" las respuestas a las solicitudes del usuario.

Lo cual es muy sospechoso. Es como si se hubiesen puesto de acuerdo para que funcionara así. Pues es capaz de recolectar datos de casi cualquier lado en la Internet.

Y también es sospechoso que antes del auge de las I.A. la malévola empresa Microsoft compró Github.😱

Pero, ¿Qué significa adaptarse? Significa que:

  • Recordar que los fundamentos nunca deben dejarse en saco roto. 
  • Mantener el código lo más simple y claro posible.
  • Actualizarse constantemente.  
  • No dejar de practicar y conocer nuevos temas. 
  • Usar la I.A. a favor y no en contra.
  • Saber qué solicitar y saber qué no es útil.

Esperemos que pasa en el futuro.

Enlaces:

https://codemonkeyjunior.blogspot.com/2025/01/las-leyes-no-escritas-de-la.html
https://codemonkeyjunior.blogspot.com/2025/06/vibe-coding-la-programacion-via-ia-el.html

sábado, 19 de julio de 2025

Programando en C++ no. 5 (manejo de excepciones)

El manejo de excepciones nos ayuda a que el flujo normal de nuestros programas no se vea interrumpido. C++ tiene mecanismos similares a lenguajes como Java y/o C# para realizar esta tarea.

Una excepción ocurre cuando hay un problema en alguna instrucción de nuestro programa, ya sea por que accedemos a una variable sin asignación de valor y que de por resultado un null. Un acceso a un método en un momento inoportuno. Una conversión numérica que no cumple las condiciones adecuadas. Acceder a un elemento que no existe en un arreglo o matriz.

Nosotros podríamos provocar una excepción con toda intencionalidad. Veamos un ejemplo:

excepcion.cpp

#include <iostream>

int main() {
  try {
    throw 0.0;
  }
  catch(double ex){
    std::cout << "Excepcion de tipo double: " << ex << std::endl;
  }
}

Compilamos y ejecutamos:

$ g++ excepcion.cpp -o excepcion.exe
$ excepcion.exe

¿Qué queremos decir en este programa?

El bloque ``try-catch`` se encargará de lanzar (throw) una excepción para luego cacharla (catch). En este caso provocamos la excepción que es un valor 0.0 (tipo double) y la excepción deberá ser del mismo tipo.

En otras palabras:

  • try: define el código a probar, es decir, es el cuerpo del código donde puede ocurrir una excepción.
  • throw: activa o lanza una excepción. 
  • catch: maneja o atrapa el error.

Veamos las siguientes excepciones hechas en Java:

try{
    int divide = 2/0;
}catch(ArithmeticException ex){
    ex.printStackTrace();
}


int[] arreglo = {1,2,3};
try{
    int numero = arreglo[3];
}
catch(ArrayIndexOutOfBoundsException ex){
    ex.printStackTrace();
}
catch(Exception ex){
    ex.printStackTrace();
}


try{
    int entero = Integer.parseInt("23f");
}catch(NumberFormatException ex){
    ex.printStackTrace();
}


String cadena = null;
try{
    boolean vacio = cadena.isEmpty();
}catch(NullPointerException ex){
    ex.printStackTrace();
}

Tipos de excepciones que vemos:

  • ArithmeticException: cuando tratamos de hacer una operación aritmética inválida. En este caso una división por cero. 
  • ArrayIndexOutOfBoundsException: al tratar de acceder a un índice inexistente de un arreglo. 
  • NumberFormatException: intentar convertir una cadena a número, pero la cadena no cumple el formato numérico. 
  • NullPointerException: acceder a un elemento null.

El código equivalente en C++ sería algo como esto:

excepciones.cpp

#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>

int main() {
    // División por cero simulada
    try {
        int divisor = 0;
        if (divisor == 0) throw std::runtime_error("División por cero detectada.");
        int divide = 2 / divisor;
        std::cout << "Resultado: " << divide << std::endl;
    } catch (const std::exception& ex) {
        std::cerr << "[División] Excepción: " << ex.what() << std::endl;
    }

    // Acceso fuera de los límites del arreglo
    try {
        std::vector<int> arreglo = {1, 2, 3};
        int numero = arreglo.at(3); // índice fuera de rango
        std::cout << "Número: " << numero << std::endl;
    } catch (const std::out_of_range& ex) {
        std::cerr << "[Arreglo] Excepción: " << ex.what() << std::endl;
    } catch (...) {
        std::cerr << "[Arreglo] Otra excepción inesperada." << std::endl;
    }

    // Conversión inválida de cadena a entero
    try {
        std::string texto = "f23f";
        int numero = std::stoi(texto);
        std::cout << "Número convertido: " << numero << std::endl;
    } catch (const std::invalid_argument& ex) {
        std::cerr << "[Conversión] Excepción: " << ex.what() << std::endl;
    }

    // Puntero nulo accediendo a método
    try {
        std::string* cadena = nullptr;
        if (!cadena) throw std::runtime_error("Cadena nula.");
        bool vacio = cadena->empty();
        std::cout << "¿Está vacía?: " << std::boolalpha << vacio << std::endl;
    } catch (const std::exception& ex) {
        std::cerr << "[Cadena nula] Excepción: " << ex.what() << std::endl;
    }

    return 0;
}

Compilamos y ejecutamos:

$ g++ excepciones.cpp -o excepciones.exe
$ excepciones.exe

Salida:

[Divisi├│n] Excepci├│n: Divisi├│n por cero detectada.
[Arreglo] Excepci├│n: vector::_M_range_check: __n (which is 3) >= this->size() (which is 3)
[Conversi├│n] Excepci├│n: stoi
[Cadena nula] Excepci├│n: Cadena nula.

¡Hemos visto como crear excepciones en C++!

Continuaremos con este tema en próximas entregas sobre este lenguaje.

Enlaces:

https://codemonkeyjunior.blogspot.com/2024/06/hace-tiempo-vimos-como-crear-un.html
https://hektorprofe.github.io/cpp/13-manejo-excepciones/
https://isocpp.org/wiki/faq/exceptions
https://www.w3schools.com/cpp/cpp_exceptions.asp

domingo, 13 de julio de 2025

Programando en C# no. 8 (manejo de excepciones)

En el mundo de la programación hay que saber diferenciar entre una excepción y un error.

Una excepción es una falla en el flujo normal de un programa. Si el programa tiene manejo de excepciones, el programa continuará su ejecución o flujo aunque hayan excepciones. Un ejemplo sería que en una parte del prograam se quiera acceder a un índice inexistente de un vector.

Un error es una falla que romperá el flujo del programa. No hay forma de evitarlo. Por ejemplo, que la máquina en la que se está ejecutando un programa se quede sin memoria o que no tenga energía (eléctrica) para funcionar.

Al igual que Java, C# tiene la capacidad de manejar excepciones. Casi de manera idéntica.

Supongamos que queremos acceder a un índice de una cadena "ABC" que no existe. La forma de manejar esa excepción, de tipo ArgumentOutOfRangeException, sería la siguiente:

 try
 {
   string nuevoString = "ABC".Substring(2, 4);
   Console.WriteLine("{0}", nuevoString);
 } catch (ArgumentOutOfRangeException aoex)
  {
    Console.WriteLine("Ha ocurrido una Excepcion: {0}", aoex.Message);
  }

Al compilar no ocurrirá ningún error. La excepción se lanzará a la hora de la ejecución:

Ha ocurrido una Excepcion: Index and length must refer to a location within the string. (Parameter 'length')

Con esto el programa continuará su flujo a pesar de la excepción.

Para operaciones aritméticas haríamos algo como esto (ArithmeticException): 

var x = 1;
var y = 0;
try
{
  int divide = x / y;
}
catch (ArithmeticException ex)
{ 
  Console.WriteLine("Ha ocurrido una Excepcion: {0}", ex.Message);
}

De igual manera, no ocurrirá nada a la hora de la compilación. Ocurrirá a la hora de ejecución:

Ha ocurrido una Excepcion: Attempted to divide by zero.

Ya que se trata de una división entre cero.

Supongamos que queremos acceder a un elemento inexistente de un arreglo (o vector):

int[] arreglo = { 1, 2, 3 };
try
{
   int numero = arreglo[3];
}
catch (IndexOutOfRangeException ex)
{
  Console.WriteLine("Ha ocurrido una Excepcion: {0}", ex.Message);
}

El compilador no adivinará que queremos acceder a un índice que no existe. Sin embargo, el manejo de la excepción, de tipo IndexOutOfRangeException, se encargará de gestionar esa acción.

Ha ocurrido una Excepcion: Index was outside the bounds of the array.

Nota: Existen excepciones marcadas y no marcadas. Las marcadas son las que el compilador obliga a escribir. Las no marcadas no requieren manejo explícito, pero pueden causar la terminación del programa.

Continuaremos con esta serie de entregas sobre C#.

Enlaces:

https://codemonkeyjunior.blogspot.com/2025/07/programando-en-c-no-7-uso-de-genericos.html


GCP Pub/Sub: un servicio de mensajería asíncrona y escalable

Según la documentación oficial, Pub/Sub es:

Un servicio de mensajería asíncrona y escalable que separa los servicios que producen mensajes de aquellos que procesan esos mensajes.

Lo que nos permite hacer es:

Permitir que los servicios se comuniquen de forma asíncrona, con latencias de alrededor de 100 milisegundos.

Se usa para:

Las canalizaciones de integración de datos y estadísticas de transmisión a fin de cargar y distribuir datos. Es igual de efectivo que el middleware orientado a la mensajería para la integración de servicios o como una cola con el fin de paralelizar las tareas.

Pub/Sub te permite crear sistemas de productores y consumidores de eventos, llamados publicadores y suscriptores. Los publicadores se comunican con los suscriptores de forma asíncrona mediante la transmisión de eventos, en lugar de llamadas de procedimiento remoto (RPC) síncronas.

Los publicadores envían eventos al servicio de Pub/Sub, sin importar cómo o cuándo se procesarán estos eventos. Luego, Pub/Sub entrega eventos a todos los servicios que reaccionan a ellos. En los sistemas que se comunican a través de RPC, los publicadores deben esperar a que los suscriptores reciban los datos.

Sin embargo, la integración asíncrona en Pub/Sub aumenta la flexibilidad y solidez del sistema general.

En pocas palabras, es una tecnología similar a RabbitMQ, Apache Kafka y/o ActiveMQ por mencionar solo algunas.

Casos habituales

  • Transferir la interacción del usuario y los eventos del servidor. 
  • Distribución de eventos en tiempo real. 
  • Replicar datos entre bases de datos. 
  • Procesamiento y flujos de trabajo paralelos. 
  • Bus de eventos empresariales. 
  • Transmisión de datos desde aplicaciones, servicios o dispositivos de la IoT. 
  • Actualización de cachés distribuidas. 
  • Balanceo de cargas para la confiabilidad.

Un ejemplo sencillo de esta tecnología sería crear una aplicación que:

  • Publique mensajes a un tópico de Pub/Sub y 
  • Reciba mensajes desde ese tópico.

Para ello es necesario tener una cuenta de GCP. Tener el JDK más actual.

Creamos una aplicación de Spring Boot y en nuestro pom.xml agregamos la siguiente dependencia:

<dependency>
  <groupId>com.google.cloud</groupId>
  <artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
</dependency>

La configuración del archivo YAML sería algo como esto:

# En application.yml
spring:
  cloud:
    gcp:
      pubsub:
        project-id: tu-id-de-proyecto
        credentials:
          location: classpath:tu-archivo-de-credenciales.json

Crearemos una clase tipo Service que servirá como el "publicador":

@Service
public class PublisherService {
    private final PubSubTemplate pubSubTemplate;

    public PublisherService(PubSubTemplate pubSubTemplate) {
        this.pubSubTemplate = pubSubTemplate;
    }

    public void enviarMensaje(String mensaje) {
        pubSubTemplate.publish("mi-topico", mensaje);
    }
}

Crearemos una clase tipo Component que servirá para escuchar los mensajes:

@Component
public class Subscriber {
    @PubSubSubscriber(subscription = "mi-suscripcion")
    public void recibirMensaje(String mensaje) {
        System.out.println("Mensaje recibido: " + mensaje);
    }
}

Ahora crearemos una clase tipo Controller para invocar el método de envío de mensajes:

@RestController
@RequestMapping("/pubsub")
public class PubSubController {

    private final PublisherService publisherService;

    public PubSubController(PublisherService publisherService) {
        this.publisherService = publisherService;
    }

    @PostMapping("/enviar")
    public ResponseEntity<String> enviar(@RequestBody String mensaje) {
        publisherService.enviarMensaje(mensaje);
        return ResponseEntity.ok("Mensaje publicado: " + mensaje);
    }
}

Usando curl para probar el mensaje:

curl -X POST http://localhost:8080/pubsub/enviar \
     -H "Content-Type: text/plain" \
     -d "Hola desde el controlador!"

También agregando un nuevo método en el controller:

@PostMapping("/enviar-json")
public ResponseEntity<String> enviarJson(@RequestBody Map<String, String> payload) {
    String mensaje = payload.get("mensaje");
    publisherService.enviarMensaje(mensaje);
    return ResponseEntity.ok("Mensaje JSON publicado: " + mensaje);
}

Y usando curl:

curl -X POST http://localhost:8080/pubsub/enviar-json \
     -H "Content-Type: application/json" \
     -d '{"mensaje": "¡Hola JSON!"}'

Continuaremos sobre temas de GCP en próximas entregas.

Enlaces:

https://cloud.google.com/pubsub/docs/overview
https://www.rabbitmq.com/
https://kafka.apache.org/
https://activemq-apache-org.translate.goog/

Programando en C# no. 9 (usando Nuget)

En un anterior post hablamos sobre Nuget . El cual es el administrador de paquetes para .NET. Con Nuget podemos: Consumir paquetes de ...

Etiquetas

Archivo del blog