<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eduardo Fuentes</title>
    <description>The latest articles on DEV Community by Eduardo Fuentes (@eduuu_dev).</description>
    <link>https://dev.to/eduuu_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1365498%2Ff28861e4-d2d7-4dba-b4c7-184cd247c62e.jpeg</url>
      <title>DEV Community: Eduardo Fuentes</title>
      <link>https://dev.to/eduuu_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eduuu_dev"/>
    <language>en</language>
    <item>
      <title>Arquitectura Cloud Moderna para Aplicaciones Web en AWS</title>
      <dc:creator>Eduardo Fuentes</dc:creator>
      <pubDate>Sun, 01 Mar 2026 22:21:28 +0000</pubDate>
      <link>https://dev.to/eduuu_dev/arquitectura-cloud-moderna-para-aplicaciones-web-en-aws-koi</link>
      <guid>https://dev.to/eduuu_dev/arquitectura-cloud-moderna-para-aplicaciones-web-en-aws-koi</guid>
      <description>&lt;p&gt;Cuando aprendemos AWS, solemos estudiar los servicios por separado:&lt;br&gt;
EC2, RDS, S3, VPC…&lt;/p&gt;

&lt;p&gt;Pero la verdadera ingeniería comienza cuando entendemos cómo se conectan entre sí para formar una arquitectura escalable, segura y lista para producción.&lt;/p&gt;

&lt;p&gt;En este artículo explico una arquitectura moderna para aplicaciones web basada en buenas prácticas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Objetivo de la arquitectura
&lt;/h2&gt;

&lt;p&gt;Diseñar una infraestructura que sea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Altamente disponible&lt;/li&gt;
&lt;li&gt;Escalable&lt;/li&gt;
&lt;li&gt;Segura&lt;/li&gt;
&lt;li&gt;Optimizada en costos&lt;/li&gt;
&lt;li&gt;Preparada para producción&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Punto de Entrada: Route 53 + CloudFront
&lt;/h2&gt;

&lt;p&gt;Cuando un usuario escribe el dominio en su navegador, el flujo correcto es:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Route 53&lt;/strong&gt; resuelve el dominio.&lt;/li&gt;
&lt;li&gt;El dominio apunta a &lt;strong&gt;CloudFront&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;CloudFront verifica si el contenido está cacheado en una Edge Location cercana.&lt;/li&gt;
&lt;li&gt;Si está cacheado, lo entrega inmediatamente.&lt;/li&gt;
&lt;li&gt;Si no está cacheado, consulta al origin.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; No todo el tráfico entra a la VPC. CloudFront actúa como primera capa de optimización y protección.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contenido Estático: S3 como Origin
&lt;/h2&gt;

&lt;p&gt;Para contenido estático como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Imágenes&lt;/li&gt;
&lt;li&gt;Assets del frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CloudFront usa &lt;strong&gt;Amazon S3&lt;/strong&gt; como origin.&lt;/p&gt;

&lt;p&gt;Esto permite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Baja latencia global&lt;/li&gt;
&lt;li&gt;Reducción de carga en backend&lt;/li&gt;
&lt;li&gt;Menor costo operativo&lt;/li&gt;
&lt;li&gt;Mejor experiencia de usuario&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; En muchos casos, el frontend completo puede servirse desde S3 + CloudFront sin tocar la VPC.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contenido Dinámico: ALB como Origin
&lt;/h2&gt;

&lt;p&gt;Cuando la petición requiere lógica de negocio (API, autenticación, base de datos):&lt;/p&gt;

&lt;p&gt;CloudFront redirige la solicitud hacia el &lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Flujo dinámico:&lt;/p&gt;

&lt;p&gt;Usuario → Route 53 → CloudFront → ALB → EC2 → RDS&lt;/p&gt;

&lt;p&gt;Aquí recién entramos a la VPC.&lt;/p&gt;




&lt;h2&gt;
  
  
  VPC: Nuestra Red Privada
&lt;/h2&gt;

&lt;p&gt;La VPC define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rango de IPs&lt;/li&gt;
&lt;li&gt;Subnets públicas&lt;/li&gt;
&lt;li&gt;Subnets privadas&lt;/li&gt;
&lt;li&gt;Tablas de ruteo&lt;/li&gt;
&lt;li&gt;Gateways&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Es el entorno aislado donde vive nuestra aplicación.&lt;/p&gt;




&lt;h2&gt;
  
  
  Subnets Públicas
&lt;/h2&gt;

&lt;p&gt;En las subnets públicas normalmente encontramos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Load Balancer&lt;/li&gt;
&lt;li&gt;NAT Gateway&lt;/li&gt;
&lt;li&gt;Internet Gateway (a nivel VPC)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; El ALB recibe tráfico desde CloudFront. No desde usuarios directamente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Subnets Privadas (Capa de Aplicación)
&lt;/h2&gt;

&lt;p&gt;Aquí viven las instancias:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 con nuestro backend&lt;/li&gt;
&lt;li&gt;Auto Scaling Group (recomendado)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Características:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No tienen IP pública.&lt;/li&gt;
&lt;li&gt;Solo reciben tráfico desde el ALB.&lt;/li&gt;
&lt;li&gt;Pueden salir a Internet mediante NAT Gateway.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Esto reduce significativamente la superficie de ataque.&lt;/p&gt;




&lt;h2&gt;
  
  
  Subnets Privadas (Capa de Datos)
&lt;/h2&gt;

&lt;p&gt;La base de datos (Amazon RDS) se ubica en subnets privadas separadas.&lt;/p&gt;

&lt;p&gt;Buenas prácticas aplicadas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-AZ para alta disponibilidad&lt;/li&gt;
&lt;li&gt;Sin acceso público&lt;/li&gt;
&lt;li&gt;Security Groups restringidos&lt;/li&gt;
&lt;li&gt;Backups automáticos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Separar aplicación y datos mejora seguridad y organización.&lt;/p&gt;




&lt;h2&gt;
  
  
  NAT Gateway
&lt;/h2&gt;

&lt;p&gt;Las instancias en subnets privadas pueden necesitar acceso externo para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Descargar dependencias&lt;/li&gt;
&lt;li&gt;Consumir APIs externas&lt;/li&gt;
&lt;li&gt;Actualizaciones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; El NAT Gateway permite salida controlada a Internet sin exponer las instancias.&lt;/p&gt;




&lt;h2&gt;
  
  
  Seguridad por Capas
&lt;/h2&gt;

&lt;p&gt;Esta arquitectura aplica principios clave:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CDN como primera barrera&lt;/li&gt;
&lt;li&gt;Separación por capas&lt;/li&gt;
&lt;li&gt;Principio de mínimo privilegio&lt;/li&gt;
&lt;li&gt;Base de datos no expuesta&lt;/li&gt;
&lt;li&gt;Instancias privadas&lt;/li&gt;
&lt;li&gt;Balanceo multi-AZ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; La seguridad no es un componente. Es un diseño.&lt;/p&gt;




&lt;h2&gt;
  
  
  Escalabilidad
&lt;/h2&gt;

&lt;p&gt;La arquitectura permite crecer fácilmente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto Scaling en EC2&lt;/li&gt;
&lt;li&gt;Read replicas en RDS&lt;/li&gt;
&lt;li&gt;Cacheo en CloudFront&lt;/li&gt;
&lt;li&gt;Separación frontend/backend&lt;/li&gt;
&lt;li&gt;Migración futura a contenedores (ECS/EKS)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Optimización de Costos
&lt;/h2&gt;

&lt;p&gt;CloudFront reduce tráfico al backend.&lt;/p&gt;

&lt;p&gt;S3 es más barato que servir estáticos desde EC2.&lt;/p&gt;

&lt;p&gt;Auto Scaling evita sobreaprovisionamiento.&lt;/p&gt;

&lt;p&gt;Arquitectura moderna no es solo técnica. También es financiera.&lt;/p&gt;




&lt;h2&gt;
  
  
  ¿Por qué esta es una buena base?
&lt;/h2&gt;

&lt;p&gt;Porque:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desacopla estático de dinámico&lt;/li&gt;
&lt;li&gt;Reduce latencia global&lt;/li&gt;
&lt;li&gt;Aumenta seguridad&lt;/li&gt;
&lt;li&gt;Aplica buenas prácticas reales&lt;/li&gt;
&lt;li&gt;Te obliga a entender networking, disponibilidad y diseño&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Entender cómo diseñar un sistema completo, pensando en rendimiento, seguridad y escalabilidad desde el inicio.&lt;/p&gt;

&lt;p&gt;La diferencia entre saber usar servicios y saber diseñar arquitectura es lo que realmente eleva tu carrera como ingeniero.&lt;/p&gt;




&lt;p&gt;Feliz codeo gente!&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/eduuu"&gt;@eduuu&lt;/a&gt;.dev&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplvexazxw0y47zvlzxs6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplvexazxw0y47zvlzxs6.jpg" alt=" " width="800" height="945"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Implementación segura de CORS y validación de peticiones en arquitecturas de microservicios</title>
      <dc:creator>Eduardo Fuentes</dc:creator>
      <pubDate>Fri, 24 Oct 2025 15:17:28 +0000</pubDate>
      <link>https://dev.to/eduuu_dev/implementacion-segura-de-cors-y-validacion-de-peticiones-en-arquitecturas-de-microservicios-2f5e</link>
      <guid>https://dev.to/eduuu_dev/implementacion-segura-de-cors-y-validacion-de-peticiones-en-arquitecturas-de-microservicios-2f5e</guid>
      <description>&lt;h2&gt;
  
  
  1. Introducción
&lt;/h2&gt;

&lt;p&gt;Cuando diseñamos una API que será consumida por diferentes clientes como aplicaciones web, móviles o microservicios internos, es esencial controlar quién puede acceder a ella y bajo qué condiciones.&lt;br&gt;
Uno de los mecanismos más importantes para proteger los endpoints expuestos en la web es CORS (Cross-Origin Resource Sharing).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué es CORS?&lt;/strong&gt;&lt;br&gt;
CORS es una política de seguridad implementada por los navegadores que impide que un sitio web en un dominio (&lt;a href="https://app.com" rel="noopener noreferrer"&gt;https://app.com&lt;/a&gt;) realice solicitudes a otro dominio (&lt;a href="https://api.com" rel="noopener noreferrer"&gt;https://api.com&lt;/a&gt;) a menos que el servidor lo autorice explícitamente.&lt;/p&gt;

&lt;p&gt;Esto evita ataques como el Cross-Site Request Forgery (CSRF) o el data leakage entre orígenes no relacionados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Por qué es importante&lt;/strong&gt;&lt;br&gt;
Una configuración incorrecta de CORS puede dejar una API abierta a solicitudes desde cualquier origen, exponiendo datos sensibles.&lt;br&gt;
Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Allow-Origin: *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta cabecera, usada sin control, permite que cualquier sitio del mundo interactúe con tu API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diferencia entre peticiones desde navegador y server-to-server&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipo&lt;/th&gt;
&lt;th&gt;¿Incluye Origin?&lt;/th&gt;
&lt;th&gt;¿Requiere CORS?&lt;/th&gt;
&lt;th&gt;Ejemplo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Navegador (frontend)&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Sí&lt;/td&gt;
&lt;td&gt;Petición desde React, Angular, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microservicio interno&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Comunicación entre APIs internas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cliente CLI&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;curl, Postman, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  2. El problema
&lt;/h2&gt;

&lt;p&gt;Muchas configuraciones por defecto o ejemplos en internet aplican soluciones genéricas, como permitir todos los orígenes o usar comodines.&lt;br&gt;
Aunque simplifican las pruebas, en producción pueden generar vulnerabilidades serias.&lt;/p&gt;

&lt;p&gt;Riesgos comunes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Permitir todos los orígenes (*): Ideal para desarrollo, peligroso en producción.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validar con endsWith() o expresiones débiles: Permite subdominios falsos: evil.miapp.com.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No diferenciar entre navegadores y servicios: Se aplican políticas de CORS incluso a peticiones internas que no las requieren.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Omitir la validación de tokens: APIs que aceptan cualquier Origin pero no exigen autenticación válida.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. Estrategia de seguridad dual
&lt;/h2&gt;

&lt;p&gt;La forma más segura de abordar el problema es combinar dos niveles de validación complementarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validación de origen (CORS) para peticiones que provienen de navegadores.&lt;/li&gt;
&lt;li&gt;Validación de autorización (token o clave API) para peticiones que provienen de otros servidores o servicios internos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;En otras palabras:&lt;/strong&gt;&lt;br&gt;
Los navegadores se validan por quiénes son (su dominio).&lt;br&gt;
Los servicios se validan por lo que saben (sus credenciales).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Lógica de validación recomendada
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Validar el origen (CORS)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solo permitir dominios conocidos (no comodines).&lt;/li&gt;
&lt;li&gt;Verificar que el esquema sea HTTPS.&lt;/li&gt;
&lt;li&gt;Evitar comparaciones simples como endsWith(), usar validaciones exactas o listas blancas.&lt;/li&gt;
&lt;li&gt;Incluir una lista explícita de orígenes confiables: &lt;a href="https://app.miempresa.com" rel="noopener noreferrer"&gt;https://app.miempresa.com&lt;/a&gt;, &lt;a href="https://admin.miempresa.com" rel="noopener noreferrer"&gt;https://admin.miempresa.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Validar autorización&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aceptar tokens JWT o API Keys solo en canales seguros (HTTPS).&lt;/li&gt;
&lt;li&gt;Rechazar peticiones sin credenciales válidas.&lt;/li&gt;
&lt;li&gt;Permitir excepciones únicamente para endpoints públicos documentados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Lógica de decisión (resumen)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipo de petición&lt;/th&gt;
&lt;th&gt;Cabecera &lt;code&gt;Origin&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;Token/API Key&lt;/th&gt;
&lt;th&gt;Resultado&lt;/th&gt;
&lt;th&gt;Uso típico&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Navegador confiable&lt;/td&gt;
&lt;td&gt;Válido&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Permitir + CORS&lt;/td&gt;
&lt;td&gt;Frontend web&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Navegador no permitido&lt;/td&gt;
&lt;td&gt;Inválido&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Rechazar 403&lt;/td&gt;
&lt;td&gt;Sitio externo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microservicio interno&lt;/td&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;Válido&lt;/td&gt;
&lt;td&gt;Permitir&lt;/td&gt;
&lt;td&gt;Comunicación interna&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Petición anónima&lt;/td&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;Rechazar 403&lt;/td&gt;
&lt;td&gt;Postman/curl sin token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preflight OPTIONS&lt;/td&gt;
&lt;td&gt;Válido&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Permitir 200&lt;/td&gt;
&lt;td&gt;Verificación previa de navegador&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  5. Conclusión
&lt;/h2&gt;

&lt;p&gt;La seguridad en APIs modernas no depende solo de la autenticación, sino también del control del contexto desde donde se realizan las peticiones.&lt;br&gt;
Implementar una política de CORS estricta y validación de tokens sólida garantiza que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solo los clientes autorizados puedan interactuar con los endpoints.&lt;/li&gt;
&lt;li&gt;Las comunicaciones internas permanezcan seguras y verificadas.&lt;/li&gt;
&lt;li&gt;Se evite el acceso indebido desde sitios externos o maliciosos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En cualquier lenguaje o framework, la clave es aplicar una estrategia dual coherente y auditable, en lugar de confiar en configuraciones genéricas o atajos.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>security</category>
      <category>backend</category>
      <category>programming</category>
    </item>
    <item>
      <title>El principio de menor sorpresa y cómo el vibe coding puede romperlo</title>
      <dc:creator>Eduardo Fuentes</dc:creator>
      <pubDate>Sat, 19 Jul 2025 22:56:29 +0000</pubDate>
      <link>https://dev.to/eduuu_dev/el-principio-de-menor-sorpresa-y-como-el-vibe-coding-puede-romperlo-3nlj</link>
      <guid>https://dev.to/eduuu_dev/el-principio-de-menor-sorpresa-y-como-el-vibe-coding-puede-romperlo-3nlj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;El mejor código es el que no te sorprende.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Cuando hablamos de buenas prácticas en desarrollo de software, uno de los principios más importantes y a veces ignorado, es el &lt;strong&gt;Principio de Menor Sorpresa&lt;/strong&gt;. Este principio establece que el comportamiento del código debería ser el que cualquier desarrollador razonable esperaría.&lt;/p&gt;

&lt;p&gt;Es decir: &lt;em&gt;tu código debería comportarse de forma predecible.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué significa esto en la práctica?&lt;/strong&gt;&lt;br&gt;
Veamos un ejemplo sencillo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// ¿Qué hace esta función?
function getUser(id: string): any {
  return fetch(`/api/users/${id}`);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si lees este código por primera vez, podrías pensar que getUser devuelve un usuario. Pero en realidad devuelve una promesa, no un objeto User.&lt;/p&gt;

&lt;p&gt;Un enfoque más alineado con el principio de menor sorpresa sería:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function getUser(id: string): Promise&amp;lt;User&amp;gt; {
  const response = await fetch(`/api/users/${id}`);
  return await response.json();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O incluso nombrar la función como fetchUser o getUserAsync, si se desea enfatizar aún más el comportamiento asíncrono.&lt;/p&gt;




&lt;p&gt;Romper este principio genera fricción entre el desarrollador y el sistema. Cuando te topas con código que no hace lo que esperas, te obliga a perder tiempo leyendo la implementación en lugar de enfocarte en resolver el problema de negocio.&lt;/p&gt;

&lt;p&gt;Esto se puede convertir en un efecto dominó: pérdida de tiempo, bugs difíciles de encontrar, o peor aún… errores en producción.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;¿Qué tiene que ver el vibe coding?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Con el interés de herramientas de inteligencia artificial que pueden generar código de forma automática a partir de prompts o ideas generales, muchos desarrolladores están adoptando una nueva forma de programar: escribir por impulso, sin pensar demasiado en la intención o el diseño, dejando que la IA tome decisiones por ellos.&lt;/p&gt;

&lt;p&gt;Esta forma de trabajar puede resultar productiva en el corto plazo, pero también puede romper completamente el Principio de Menor Sorpresa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Por qué el código generado impulsivamente por IA puede sorprender?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Inconsistencia de estilo o paradigmas:&lt;br&gt;
A veces la IA genera código funcional, otras veces imperativo, otras veces reactivo... todo en el mismo proyecto. Esto confunde a quien lee o mantiene el código después.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decisiones mágicas que no se documentan:&lt;br&gt;
El desarrollador que usa IA puede no entender del todo lo que se generó. El código funciona, pero su intención y contexto quedan ocultos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Abstracciones que no se alinean con el dominio del problema:&lt;br&gt;
Es común ver clases, funciones o estructuras que no tienen un nombre claro o una responsabilidad definida, simplemente porque la IA respondió a un prompt mal planteado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pérdida de convenciones del equipo o del lenguaje:&lt;br&gt;
Lo que antes era una convención interna del equipo, ahora puede romperse con un simple "copiar y pegar" desde la IA.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo respetar el Principio de Menor Sorpresa usando IA?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No se trata de no usar IA. Al contrario, es una herramienta poderosa. Pero debemos usarla con intención, con criterio y con responsabilidad:&lt;/li&gt;
&lt;li&gt;Sé el diseñador, no solo el consumidor: guía a la IA con prompts claros y evalúa críticamente lo que produce.&lt;/li&gt;
&lt;li&gt;Refactoriza lo generado: dale tu toque, adáptalo al estilo de tu equipo y asegúrate de que no sorprenda a quien lo lea.&lt;/li&gt;
&lt;li&gt;Prefiere estructuras familiares: nombres de variables, funciones y clases que reflejen el dominio del problema.&lt;/li&gt;
&lt;li&gt;Evita la magia: si algo parece funcionar "porque sí", probablemente merezca una revisión.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El código que sorprende es difícil de mantener, probar y escalar. Y eso es lo que queremos evitar.&lt;/p&gt;

&lt;p&gt;Por muy avanzado que sea el código generado por inteligencia artificial, sigue siendo nuestra responsabilidad garantizar su claridad, coherencia y previsibilidad.&lt;/p&gt;

&lt;p&gt;Así que la próxima vez que generes código con ayuda de una IA, recuerda:&lt;br&gt;
El mejor código no es el más creativo… es el que menos sorprende.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>coding</category>
      <category>vibecoding</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Código Limpio: Fechas (TimeZone)</title>
      <dc:creator>Eduardo Fuentes</dc:creator>
      <pubDate>Tue, 15 Jul 2025 02:24:54 +0000</pubDate>
      <link>https://dev.to/eduuu_dev/codigo-limpio-fechas-timezone-1nlp</link>
      <guid>https://dev.to/eduuu_dev/codigo-limpio-fechas-timezone-1nlp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Porque sí, las fechas son más complejas de lo que parece…&lt;/strong&gt;&lt;br&gt;
Como desarrolladores, tarde o temprano nos encontramos con el dilema de manejar fechas correctamente. Lo que comienza como un simple new Date() puede escalar a problemas de zonas horarias, inconsistencias entre frontend y backend, y bugs que aparecen en el camino.&lt;/p&gt;

&lt;p&gt;Por eso, en este artículo te muestro cómo estructurar el manejo de fechas de forma profesional, limpia y reutilizable.&lt;/p&gt;


&lt;h2&gt;
  
  
  Regla de oro: encapsula las operaciones de fecha
&lt;/h2&gt;

&lt;p&gt;Uno de los mejores consejos que puedo darte es que no trabajes con fechas directamente en cada parte de tu código. En lugar de eso, crea una clase o módulo que se encargue exclusivamente del manejo de fechas.&lt;/p&gt;

&lt;p&gt;Esto te dará:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Código más limpio&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Operaciones reutilizables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Menos bugs en producción&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mejor manejo de zonas horarias&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Más facilidad para testear&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Además, si en algún momento decides cambiar la librería que usas (Date, Luxon, Day.js, etc.), solo tienes que cambiarlo en un solo lugar.&lt;/p&gt;


&lt;h2&gt;
  
  
  Guardar en UTC, mostrar en zona local
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;br&gt;
MongoDB guarda fechas en formato UTC si usas new Date() desde Node.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
await db.collection('users').insertOne({
  createdAt: new Date()
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;br&gt;
Usa el tipo de columna timestamp with time zone. Aunque el nombre suene confuso, guarda la fecha en UTC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En ambos casos, el dato se guarda en UTC, y la conversión a la zona del usuario debe hacerse solo cuando se va a mostrar.&lt;/p&gt;




&lt;h2&gt;
  
  
  Clase TypeScript para encapsular fechas
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { DateTime } from "luxon";

export class DateHelper {
  private date: DateTime;

  constructor(input?: Date | string) {
    this.date = input
      ? DateTime.fromJSDate(new Date(input)).toUTC()
      : DateTime.utc();
  }

  static now(): DateHelper {
    return new DateHelper();
  }

  toUTC(): string {
    return this.date.toUTC().toISO();
  }

  toLocal(zone: string): string {
    return this.date.setZone(zone).toFormat("dd/MM/yyyy HH:mm");
  }

  isAfter(other: DateHelper): boolean {
    return this.date.toMillis() &amp;gt; other.date.toMillis();
  }

  isBefore(other: DateHelper): boolean {
    return this.date.toMillis() &amp;lt; other.date.toMillis();
  }

  isSameDay(other: DateHelper): boolean {
    return this.date.hasSame(other.date, 'day');
  }

  static compare(a: DateHelper, b: DateHelper): number {
    return a.date.toMillis() - b.date.toMillis();
  }

  static fromLocal(dateString: string, zone: string): DateHelper {
    return new DateHelper(DateTime.fromFormat(dateString, "dd/MM/yyyy HH:mm", { zone }).toJSDate());
  }

  toJSDate(): Date {
    return this.date.toJSDate();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Este módulo te permitirá:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comparar fechas&lt;/li&gt;
&lt;li&gt;Convertir a zona local&lt;/li&gt;
&lt;li&gt;Convertir a UTC&lt;/li&gt;
&lt;li&gt;Crear fechas desde strings localizados&lt;/li&gt;
&lt;li&gt;Exportarlas como Date para persistirlas&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Controla los formatos
&lt;/h2&gt;

&lt;p&gt;Es una buena práctica definir formatos únicos para mostrar las fechas en toda la aplicación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export enum TimeFormats {
  HH_MM = "HH:mm",
  HH_MM_SS = "HH:mm:ss",
}

export enum DateFormats {
  DD_MM_YYYY = "dd/MM/yyyy",
  YYYY_MM_DD = "yyyy-MM-dd",
  FULL_DATE = "dddd dd MMMM yyyy",
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Así evitas inconsistencias visuales y puedes modificar todos los formatos desde un solo lugar.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Encapsular tu lógica de fechas y trabajar siempre en UTC es una de las mejores inversiones que puedes hacer, te ahorarás dolores de cabeza.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>🧠 Caso real: cuando .populate() no es suficiente (y lo que aprendí integrando MongoDB con Oracle)</title>
      <dc:creator>Eduardo Fuentes</dc:creator>
      <pubDate>Thu, 29 May 2025 00:42:18 +0000</pubDate>
      <link>https://dev.to/eduuu_dev/caso-real-cuando-populate-no-es-suficiente-y-lo-que-aprendi-integrando-mongodb-con-oracle-1lbo</link>
      <guid>https://dev.to/eduuu_dev/caso-real-cuando-populate-no-es-suficiente-y-lo-que-aprendi-integrando-mongodb-con-oracle-1lbo</guid>
      <description>&lt;p&gt;Hace un tiempo me tocó un desafío interesante como backend developer.&lt;/p&gt;

&lt;p&gt;Un cliente necesitaba extender su sistema. Era una especie de migración evolutiva: querían crear un nuevo módulo clave para el negocio, pero conservando algunos datos críticos en su base de datos legacy (Oracle).&lt;/p&gt;

&lt;p&gt;El stack&lt;br&gt;
Para el nuevo módulo se decidió trabajar con MongoDB, lo cual nos forzaba a diseñar una lógica de integración para que ambas bases pudieran coexistir mientras se realizaba la transición. El problema vino cuando uno de los requerimientos fue:&lt;/p&gt;

&lt;p&gt;"Para los datos que vengan de Oracle, queremos mantener el mismo id como identificador en Mongo."&lt;/p&gt;

&lt;p&gt;Parece simple, ¿no? Pero aquí es donde entra Mongoose.&lt;/p&gt;


&lt;h2&gt;
  
  
  ¿Qué es Mongoose?
&lt;/h2&gt;

&lt;p&gt;Para quienes no lo conocen, Mongoose es un ODM (Object Document Mapper) para MongoDB en el ecosistema de Node.js. Sirve para estructurar tus colecciones como si fueran modelos en un ORM, con schemas, validaciones, middlewares, y sí, relaciones entre documentos.&lt;/p&gt;

&lt;p&gt;Es justamente ahí donde aparece .populate(), una función que simula los joins del mundo SQL, permitiéndote relacionar documentos entre colecciones.&lt;/p&gt;

&lt;p&gt;El problema real&lt;br&gt;
Cuando quisimos relacionar documentos por un campo que no era el _id de Mongo, comenzaron los problemas.&lt;/p&gt;

&lt;p&gt;Mongoose por defecto hace .populate() usando el campo _id. Pero en este caso, queríamos hacer .populate() usando un campo llamado id que venía desde Oracle y que debíamos conservar.&lt;/p&gt;

&lt;p&gt;Intentamos cosas como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;js
Copy
Edit
ref: 'User',
localField: 'userId',
foreignField: 'id',
justOne: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y aunque eso nos llevó a una solución parcial usando populate virtuales, se empezó a complicar la lectura del código y la mantenibilidad.&lt;/p&gt;

&lt;p&gt;La solución (de compromiso)&lt;br&gt;
Optamos por construir los documentos en Mongo usando ambos campos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;json
Copy
Edit
{
  "_id": "valor-id-legacy",
  "id": "valor-id-legacy",
  "otrosCampos": "..."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto nos permitió mantener compatibilidad con Mongoose sin modificar demasiadas partes del sistema, y respetar el requerimiento de mantener el mismo identificador del sistema legacy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;💡 Este tipo de casos son un buen ejemplo de cuando se habla de que MongoDB no está hecho para relaciones complejas. A veces es fácil subestimar estos detalles hasta que necesitas hacer cosas como .populate() con condiciones especiales.&lt;/p&gt;

&lt;p&gt;👀 Mongoose ofrece herramientas potentes, pero también tiene sus limitaciones cuando queremos salirnos de lo estándar.&lt;/p&gt;

&lt;p&gt;⚠️ Es importante pensar bien la estructura de los datos antes de migrar o integrar con sistemas existentes. Mongo te da flexibilidad, pero esa flexibilidad puede jugarte en contra cuando empiezas a crecer o te toca convivir con sistemas relacionales.&lt;/p&gt;




&lt;h2&gt;
  
  
  Solución
&lt;/h2&gt;

&lt;p&gt;¿Y entonces?&lt;br&gt;
En nuestro caso, mantener ambos campos (_id e id) fue un compromiso aceptable. ¿Ideal? No. ¿Pragmático? Totalmente.&lt;/p&gt;

&lt;p&gt;🔧 Si te encuentras en una situación parecida:&lt;/p&gt;

&lt;p&gt;Evalúa si puedes mapear los datos antes de guardarlos.&lt;/p&gt;

&lt;p&gt;Considera los límites de .populate() con campos no convencionales.&lt;/p&gt;

&lt;p&gt;Usa virtuales con cuidado, y documenta bien su propósito.&lt;/p&gt;

&lt;p&gt;Y si empiezas a escribir muchos .aggregate() para solucionar estos problemas… quizá Mongo no es el lugar.&lt;/p&gt;




&lt;p&gt;¿Te ha pasado algo similar? ¿Has tenido que hacer convivir Mongo con sistemas legacy?&lt;/p&gt;

&lt;p&gt;Déjamelo saber en los comentarios o comparte tu experiencia. 🙌&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>mongoose</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Puede la IA reemplazar los trabajos de desarrollo? Vamos a hablar de ello!</title>
      <dc:creator>Eduardo Fuentes</dc:creator>
      <pubDate>Mon, 30 Dec 2024 13:50:44 +0000</pubDate>
      <link>https://dev.to/eduuu_dev/puede-la-ia-reemplazar-los-trabajos-de-desarrollo-vamos-a-hablar-de-ello-23fn</link>
      <guid>https://dev.to/eduuu_dev/puede-la-ia-reemplazar-los-trabajos-de-desarrollo-vamos-a-hablar-de-ello-23fn</guid>
      <description>&lt;p&gt;El pánico por la IA es real. Adondequiera que vayas, alguien grita: "¡La IA nos va a quitar el trabajo!". Y si trabajas en el sector tecnológico (sobre todo si eres desarrollador), probablemente lo hayas oído más veces de las que has tenido que depurar esa molesta línea de código. (No mientas: todos tenemos ese error que nos persigue).&lt;/p&gt;

&lt;p&gt;Pero dejemos de lado el ruido por un segundo. ¿Realmente corres el riesgo de ser reemplazado por una IA? Alerta de spoiler: no, a menos que estés flojeando. Analicemos esto en detalle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Si te preocupa que te reemplacen, tal vez deberías hacer algo al respecto
&lt;/h2&gt;

&lt;p&gt;Este es el asunto: solo te reemplazan en un trabajo, en cualquier trabajo, si no eres lo suficientemente bueno en él. Piénsalo. Si estás escribiendo código de espagueti que haría que un plato de tallarines se vea organizado, sí, tal vez sea hora de subir de nivel. Con IA o sin IA, el lugar de trabajo nunca ha sido amable con la mediocridad.&lt;/p&gt;

&lt;p&gt;En lugar de sudar la gota gorda porque la IA te quite el trabajo, ¿qué tal si haces las cosas que te hacen irreemplazable?&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué puedes hacer?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Aprende nuevos lenguajes: explora ese marco del que todos hablan maravillas.&lt;/li&gt;
&lt;li&gt;Contribuye al código abierto: es como un gimnasio para tus habilidades de codificación.&lt;/li&gt;
&lt;li&gt;Crea proyectos secundarios: porque nada grita "contrátame" como un repositorio genial de GitHub.&lt;/li&gt;
&lt;li&gt;ePiénsalo como un videojuego: no pierdes en la pelea con el jefe si superas el nivel. (¿Y si no lo eres? Bueno, tienes mucho trabajo por hacer, amigo mío.)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Las herramientas de IA son geniales, pero no son varitas mágicas
&lt;/h2&gt;

&lt;p&gt;He trabajado con muchas herramientas de IA. Estoy usando algunas de ellas ahora mismo. Y déjame decirte que son geniales. Agilizan tu flujo de trabajo, te ayudan a solucionar problemas de sintaxis que normalmente pasarías horas buscando en Google e incluso generan código repetitivo para que no tengas que hacer las cosas aburridas. (Más sobre eso más adelante).&lt;/p&gt;

&lt;p&gt;Pero aquí está la cuestión: son solo herramientas.&lt;/p&gt;

&lt;p&gt;¿Recuerdas cuando los IDE comenzaron a agregar autocompletar y la gente pensó que eso reemplazaría a los desarrolladores? Sí, no sucedió. La misma historia aquí.&lt;/p&gt;

&lt;p&gt;Entonces, ¿qué no puede hacer la IA?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Entiende el contexto de tu proyecto: no sabes por qué elegiste esa extraña lógica de caso extremo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Establece objetivos: la IA no conoce las necesidades comerciales de tu cliente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Piensa de manera creativa: claro, puede generar una función, pero ¿puede diseñar una arquitectura completa? En realidad, no.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Piénsalo de esta manera: un taladro eléctrico hace que construir una casa sea más fácil, pero eso no significa que de repente puedas convertirte en arquitecto o contratista sin ninguna habilidad.&lt;/p&gt;




&lt;h2&gt;
  
  
  La IA solo hace que las cosas aburridas sean más fáciles
&lt;/h2&gt;

&lt;p&gt;Seamos honestos: a nadie le gusta escribir código repetitivo.&lt;/p&gt;

&lt;p&gt;Es como pelar papas antes de hacer un plato gourmet. ¿Necesario? Seguro. ¿Divertido? Absolutamente no. Y ahí es donde la IA realmente brilla.&lt;/p&gt;

&lt;p&gt;En el pasado (hace como dos años), comenzar un proyecto significaba construir todo desde cero o al menos a partir de un código repetitivo viejo y cansado que encontrabas en GitHub. Ahora, con la IA, escribes algunas indicaciones y ¡boom! Te genera una base bonita, brillante y personalizada para tu proyecto. No es perfecta, pero te ahorra tiempo y te permite concentrarte en las cosas divertidas: la resolución de problemas y la creación de funciones.&lt;/p&gt;




&lt;h2&gt;
  
  
  ¿Qué hay que aprender?
&lt;/h2&gt;

&lt;p&gt;La IA es como ese pasante que hace las partes tediosas de tu trabajo para que puedas concentrarte en las cosas interesantes.&lt;/p&gt;

&lt;p&gt;Tú sigues siendo el que está a cargo.&lt;br&gt;
Sigues siendo el cerebro creativo detrás del proyecto.&lt;br&gt;
Y sigues siendo… bueno, un programador. Solo que ahora eres más rápido. (Lo siento, autónomos por horas. Parece que los contratos con ofertas fijas te están llamando).&lt;br&gt;
La ​​IA no depurará ese código de pesadilla que escribiste a las 3 a. m.&lt;br&gt;
Aquí hay otra cosa que debes tener en cuenta: la IA es excelente para seguir patrones y reglas, pero ¿depurar? Eso sigue siendo cosa tuya, amigo.&lt;/p&gt;

&lt;p&gt;La IA puede decirte qué está mal en tu código, pero ¿averiguar por qué está mal y cómo solucionarlo de una manera que no arruine todo el proyecto? Eso requiere la capacidad intelectual de un desarrollador.&lt;/p&gt;




&lt;h2&gt;
  
  
  El elemento humano
&lt;/h2&gt;

&lt;p&gt;El código no consiste solo en escribir líneas que funcionen.&lt;/p&gt;

&lt;p&gt;Se trata de colaborar con tu equipo.&lt;br&gt;
Entender las necesidades del cliente.&lt;br&gt;
Crear algo que no solo sea funcional, sino también elegante y escalable.&lt;br&gt;
La IA no hace eso. Al menos, no todavía.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lo que deberías hacer en lugar de entrar en pánico
&lt;/h2&gt;

&lt;p&gt;Si aún te preocupa la IA, te damos un consejo: deja de preocuparte y empieza a aprender.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepárate para el futuro
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aprenda a trabajar con IA: estas herramientas no desaparecerán, así que más vale que se familiarice con ellas. Trátelas como las extensiones de sus habilidades que son.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concéntrese en la resolución de problemas: la IA puede escribir código, pero no puede descifrar lógicas empresariales complejas ni diseñar arquitecturas escalables. Ese es su trabajo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manténgase actualizado: la tecnología cambia rápidamente. Si todavía está escribiendo aplicaciones jQuery en 2024, eso es culpa suya, no de la IA. Manténgase al día con las tendencias, aprenda nuevas herramientas y manténgase adaptable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Crea cosas: proyectos paralelos, contribuciones de código abierto, trabajos independientes, lo que sea que mantenga sus habilidades en forma y su cartera en crecimiento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Colabora: el trabajo en equipo es una parte importante de ser un desarrollador. La IA no está reemplazando su capacidad para comunicarse con su equipo o comprender la visión de un cliente.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  En conclusión: relájate, no te reemplazarán (a menos que tú lo permitas)
&lt;/h2&gt;

&lt;p&gt;La IA no vendrá a ocupar su trabajo.&lt;/p&gt;

&lt;p&gt;Al menos no si eres bueno en eso. Es una herramienta, no una amenaza. Úsala a tu favor, sigue mejorando y deja de permitir que los titulares te asusten.&lt;/p&gt;

&lt;p&gt;La única forma en que la IA te va a reemplazar es si te quedas estancado en el pasado, negándote a adaptarte o crecer.&lt;/p&gt;

&lt;p&gt;Pero si estás ahí afuera aprendiendo, experimentando y manteniendo la curiosidad, estás bien.&lt;/p&gt;

&lt;p&gt;Ahora, vuelve a codificar. Y tal vez deja que la IA se encargue del código estándar por ti mientras lo haces. ¡Saludos!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Servidor NodeJs + Typescript + ExpressJs</title>
      <dc:creator>Eduardo Fuentes</dc:creator>
      <pubDate>Mon, 07 Oct 2024 20:07:01 +0000</pubDate>
      <link>https://dev.to/eduuu_dev/servidor-nodejs-typescript-expressjs-59jk</link>
      <guid>https://dev.to/eduuu_dev/servidor-nodejs-typescript-expressjs-59jk</guid>
      <description>&lt;p&gt;Express es un framework web minimalista popular para Node.js. Permite crear aplicaciones web de manera sencilla y rápida, tiene una documentación bastante completa que puedes revisar &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;En este tutorial, te explico cómo puedes crear tú primer servidor Express en TypeScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  Paso 1: Configuración del entorno de desarrollo
&lt;/h2&gt;

&lt;p&gt;Asegúrate de tener Node.js y npm instalados en tú máquina. Para instalar estas tecnologías, puedes seguir los pasos de sus sitios oficiales.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;NodeJs &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Luego, debes dirigirte a la ubicación donde quieres guardar tú proyecto, y crear una carpeta con el nombre que prefieras. En mi caso utilizaré ts-server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ts-server
cd ts-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para iniciar el proyecto node con configuraciones por defecto, debes utilizar el siguiente comando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para iniciar un repositorio git, debes utilizar el siguiente comando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego, debes crear un archivo .gitignore en la raíz del directorio, este archivo sirve, para ignorar ciertos directorios o archivos, que no son necesarios subir al repositorio remoto.&lt;/p&gt;

&lt;p&gt;Al crear .gitignore, puedes entrar al siguiente &lt;a href="https://www.toptal.com/developers/gitignore" rel="noopener noreferrer"&gt;link&lt;/a&gt;, donde para este caso, puedes sumar las siguientes restricciones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2snzd0wywpzflmzja1mu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2snzd0wywpzflmzja1mu.png" alt="Generador gitignore" width="716" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto generará el contenido necesario para el .gitignore, por lo que lo debes copiar y pegar en el archivo que creaste.&lt;/p&gt;

&lt;p&gt;A continuación, debes agregar un archivo .editorconfig en la raíz del directorio, que su objetivo, es tener un estandar en el editor que utilices, así si otros desarrolladores quieren aportar en el proyecto, estará esta configuración centralizada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.js]
quote_type = single

[*.md]
max_line_length = off
trim_trailing_whitespace = false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;También es necesario configurar un linter, para seguir un estándar de código, por lo que debes crear un .eslintrc.json en la raíz del directorio con una configuración similar a esta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ],
  "env": {
    "es6": true,
    "node": true,
    "jest": true
  },
  "plugins": ["@typescript-eslint"],
  "rules": {
    "no-console": "warn"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esto, tienes la configuración principal de tú proyecto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 2: Instalación de dependencias
&lt;/h2&gt;

&lt;p&gt;Para continuar con el proyecto, es necesario que instalemos las dependencias que necesitamos en nuestro proyecto.&lt;/p&gt;

&lt;p&gt;Estas serían las dependencias que se necesitan en un entorno de desarrollo, esto quiere decir que no son necesarias cuando el servidor esté en producción.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;@types/express --&amp;gt; Proporciona definiciones de tipo para el framework Express.&lt;/li&gt;
&lt;li&gt;@typescript-eslint/eslint-plugin --&amp;gt; Un plugin de ESLint que contiene un conjunto de reglas específicas para TypeScript.&lt;/li&gt;
&lt;li&gt;@typescript-eslint/parser --&amp;gt; Un parser que permite a ESLint entender TypeScript. Es necesario para que ESLint pueda analizar y aplicar reglas a los archivos TypeScript.&lt;/li&gt;
&lt;li&gt;eslint --&amp;gt;  Es una herramienta de análisis de código estático para identificar patrones problemáticos en el código JavaScript.&lt;/li&gt;
&lt;li&gt;eslint-config-prettier --&amp;gt; Desactiva las reglas EsLint que son innevesarias.&lt;/li&gt;
&lt;li&gt;eslint-plugin-prettier --&amp;gt; Integra Prettier con ESLint, permitiendo que Prettier formatee el código como parte del proceso de linting.&lt;/li&gt;
&lt;li&gt;nodemon --&amp;gt; Es una herramienta que ayuda a desarrollar aplicaciones basadas en Node.js al reiniciar automáticamente la aplicación cuando se detectan cambios en los archivos del directorio.&lt;/li&gt;
&lt;li&gt;prettier --&amp;gt; Es un formateador de código que asegura que todo el código tenga un estilo consistente.&lt;/li&gt;
&lt;li&gt;ts-node --&amp;gt;  Permite ejecutar archivos TypeScript directamente en Node.js sin necesidad de compilarlos previamente a JavaScript.&lt;/li&gt;
&lt;li&gt;typescript --&amp;gt; Es un superconjunto de JavaScript que añade tipos estáticos opcionales&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La dependencia necesaria para producción, para este caso.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;express --&amp;gt; Framework web minimalista&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para instalar estas dependencias, ocuparemos los siguientes comandos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i express
npm i @types/express @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-prettier nodemon prettier ts-node typescript -D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Paso 3: Archivos de configuración
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Para crear el archivo de configuración de typescript puedes utilizar el siguiente comando.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx tsc --init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y debe contener algo así.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "src/tests/**/*"]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;El package.json hay que modificarlo, para que utilice nodemon y cosas por el estilo, por lo que quedaría algo como esto.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "curso-platzi",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "nodemonConfig": {
    "watch": [
      "src"
    ],
    "ext": "ts",
    "ignore": [
      "*.test.ts"
    ],
    "execMap": {
      "ts": "ts-node"
    }
  },
  "scripts": {
    "dev": "nodemon src/index.ts",
    "start": "node dist/index.js",
    "lint": "eslint src --ext .ts"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/express": "^5.0.0",
    "@typescript-eslint/eslint-plugin": "^8.8.0",
    "@typescript-eslint/parser": "^8.8.0",
    "eslint": "^9.12.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.2.1",
    "nodemon": "^3.1.7",
    "prettier": "^3.3.3",
    "ts-node": "^10.9.2",
    "typescript": "^5.6.2"
  },
  "dependencies": {
    "express": "^4.21.0"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Paso 4: Levantar servidor
&lt;/h2&gt;

&lt;p&gt;Finalmente en el directorio src/ agregamos el archivo index.ts, donde podremos levantar el servidor que necesitamos de la siguiente manera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import express, { NextFunction, Request, Response } from "express";
// Se define lo necesario para el servidor
const app = express();
const port = 3000;
// Se define un middleware, para que se puedan manejar peticiones y respuestas en formato json
app.use(express.json());
// Se define el endpoint raiz, para obtener un recurso
app.get("/", (req: Request, res: Response) =&amp;gt; {
  res.send({ message: "Hello World" });
});

//Manejo de errores
app.use((err: Error, req: Request, res: Response, next: NextFunction) =&amp;gt; {
  res.status(500).send("Algo salió mal");
});

// Se levanta el servidor y escucha en el puerto 3000
app.listen(port, () =&amp;gt; {
  console.log(`Server is running on port ${port}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La estructura del código queda de esta forma.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8nz72fc8vrxixh7jiv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8nz72fc8vrxixh7jiv3.png" alt="Estructura código" width="332" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Y eso es gente, espero que haya sido un buen punto de partida para aprender a crear servidores web con Express, TypeScript y Node.&lt;/p&gt;

&lt;p&gt;Chau!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>typescript</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
