<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Codmind]]></title><description><![CDATA[Lleva tu carrera al siguiente nivel]]></description><link>https://blog.codmind.com/</link><image><url>https://blog.codmind.com/favicon.png</url><title>Codmind</title><link>https://blog.codmind.com/</link></image><generator>Ghost 3.1</generator><lastBuildDate>Tue, 30 Dec 2025 05:00:13 GMT</lastBuildDate><atom:link href="https://blog.codmind.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Aprende el patrón Facade mediante un ejemplo realista en C#]]></title><description><![CDATA[Simplifica la interacción con sistemas complejos utilizando el patrón de diseño Facade 🙌]]></description><link>https://blog.codmind.com/aprende-el-patron-facade-mediante-un-ejemplo-realista-csharp/</link><guid isPermaLink="false">66abb04ed6d7a519ba69bc22</guid><dc:creator><![CDATA[Gerson Azabache Martínez]]></dc:creator><pubDate>Thu, 01 Aug 2024 11:41:00 GMT</pubDate><media:content url="https://blog.codmind.com/content/images/2024/08/hugo-sousa-m7_lccaGaYA-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.codmind.com/content/images/2024/08/hugo-sousa-m7_lccaGaYA-unsplash.jpg" alt="Aprende el patrón Facade mediante un ejemplo realista en C#"><p>Facade o fachada es un patrón que simplifica la interacción con un sistema complejo.</p><h3 id="definici-n-formal">Definición formal</h3><p></p><p>Es un <strong>patrón de diseño estructural</strong> que proporciona una <strong>interfaz simplificada</strong> y unificada para un conjunto de interfaces de <strong>subsistemas complejos</strong>. Este patrón define una clase de alto nivel que hace que el subsistema sea más fácil de usar, ocultando su complejidad y ofreciendo una interfaz más conveniente para interactuar con él.</p><h3 id="ejemplo-pr-ctico">Ejemplo práctico</h3><p></p><p>Piensa en un control remoto para la TV. La televisión tiene muchas funciones y configuraciones complejas dentro de ella, pero el control remoto te permite encenderla, cambiar de canal y ajustar el volumen de una manera muy simple. El control remoto es como la fachada, ya que te proporciona una forma sencilla de usar las funciones de la televisión sin tener que lidiar con su complejidad interna.</p><p>Mira esta imagen, se notará aún más el ejemplo, tienes el control remoto de un dispositivo de entretenimiento multimedia como lo es el Xiaomi MiBox</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.codmind.com/content/images/2024/08/image.png" class="kg-image" alt="Aprende el patrón Facade mediante un ejemplo realista en C#"><figcaption>Xiaomi MiBox</figcaption></figure><p>Aquí el control remoto (<em><strong>facade</strong></em>) tiene botones que te facilitan la vida, nota el botón "<em>Netflix</em>" que mediante un sólo clic (<em><strong>interfaz simplificada</strong></em>) te permite realizar de forma sencilla una operación compleja que consta de varias operaciones (<em><strong>subsistemas complejos</strong></em>).</p><h3 id="ejemplo-del-patr-n-facade-con-c-">Ejemplo del patrón Facade con C#</h3><p>El escenario es el siguiente: Tienes un sistema complejo que maneja la compra de productos en una tienda en línea, y este sistema tiene múltiples subsistemas como <code>Inventario</code>, <code>Pedido</code>, y <code>Envio</code>.</p><p><u>Subsistemas complejos</u></p><pre><code class="language-C#">// Subsistema 1: Inventario
public class Inventario
{
    public bool VerificarStock(int productId)
    {
        // Verificar stock del producto por su Id
        return true; // Aquí iría tu lógica, yo asumiré que hay stock.
    }
}

// Subsistema 2: Ordenes de venta
public class Pedido
{
    public void RealizarPedido(int productId)
    {
        // Colocar el pedido
        Console.WriteLine($"Pedido realizado para el producto {productId}");
    }
}

// Subsistema 3: Envíos
public class Envio
{
    public void EnviarPedido(int productId)
    {
        // Enviar el pedido
        Console.WriteLine($"Pedido enviado para el producto {productId}");
    }
}
</code></pre><p><u>Clase Facade</u></p><pre><code class="language-C#">public class OnlineStoreFacade
{
    private Inventario inventario;
    private Pedido pedido;
    private Envio envio;

    public OnlineStoreFacade()
    {
        this.inventario = new Inventario();
        this.pedido = new Pedido();
        this.envio = new Envio();
    }

    public void ComprarProducto(int productId)
    {
    	//Aquí ocultas toda la complejidad de los subsistemas y expones ComprarProducto solamente
        if (inventario.VerificarStock(productId))
        {
            pedido.RealizarPedido(productId);
            envio.EnviarPedido(productId);
            Console.WriteLine("Compra completada con éxito");
        }
        else        
            Console.WriteLine("El producto no tiene stock");        
    }
}</code></pre><p><u>Aplicación del patrón Facade</u></p><pre><code class="language-c#">class Program
{
    static void Main(string[] args)
    {
        OnlineStoreFacade tienda = new OnlineStoreFacade();
        
        int productId = 1; // ID del producto a comprar
        tienda.ComprarProducto(productId); //Usas la interfaz simplificada

        Console.ReadLine();
    }
}</code></pre><h3 id="explicaci-n-del-c-digo">Explicación del código</h3><p></p><p><strong>Subsistemas</strong>: Tienes 3 subsistemas <code>Inventario</code>, <code>Pedido</code>, y <code>Envio</code>, cada uno con su propia lógica.</p><p><strong>Clase Facade</strong>: La clase <code>OnlineStoreFacade</code> simplifica la interacción con estos subsistemas al proporcionar un único método <code>ComprarProducto</code> que se encarga de todo el proceso de compra.</p><p><strong>Aplicación del patrón</strong>: En la clase <code>Program</code>, creas una instancia de <code>OnlineStoreFacade</code> y llamas al método <code>ComprarProducto</code> con el Id del producto. La fachada se encarga de verificar el stock, realizar el pedido y enviar el producto.</p><p>Este patrón de diseño, como has notado, es útil para ocultar la complejidad de un sistema y proporcionar una interfaz más amigable y fácil de usar.</p><h3 id="el-mismo-ejemplo-sin-facade">El mismo ejemplo sin Facade</h3><p></p><p>Los subsistemas complejos quedarían como están.</p><p>No existiría la clase <code>OnlineStoreFacade</code><em>.</em></p><p>Lo que cambiaría sería la clase <code>Program</code><em>.</em></p><pre><code class="language-c#">class Program
{
    static void Main(string[] args)
    {
        Inventario inventario = new Inventario();
        Pedido pedido = new Pedido();
        Envio envio = new Envio();

        int productId = 2; // Id del producto a comprar

        // La lógica de compra queda expuesta
        if (inventario.VerificarStock(productId))
        {
            pedido.RealizarPedido(productId);
            envio.EnviarPedido(productId);
            Console.WriteLine("Compra completada con éxito");
        }
        else        
            Console.WriteLine("El producto no tiene stock");  

        Console.ReadLine();
    }
}</code></pre><p>Espero que este ejemplo te haya ayudado a entender este patrón y recuerda que practicando es como te conviertes en un maestro. Puedes seguirme también en mi blog <a href="https://bravedeveloper.com">bravedeveloper.com</a> donde hago ejemplos como éste y más!</p><p>Éxitos mis cracks! 🐿️🥳</p><p>Créditos de imagen de portada: Foto de <a href="https://unsplash.com/es/@hmiguelsousa?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Hugo Sousa</a> en <a href="https://unsplash.com/es/fotos/casa-de-hormigon-blanco-y-rojo-m7_lccaGaYA?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></p>]]></content:encoded></item><item><title><![CDATA[Comprendiendo el estilo arquitectónico REST a profundidad]]></title><description><![CDATA[Comprender bien este estilo arquitectónico te hará un backend más profesional. Adelante.]]></description><link>https://blog.codmind.com/aprendiendo-el-estilo-arquitectonico-rest-a-profundidad/</link><guid isPermaLink="false">6535e73724c7f14b9ccaf6de</guid><category><![CDATA[rest]]></category><dc:creator><![CDATA[Gerson Azabache Martínez]]></dc:creator><pubDate>Tue, 24 Oct 2023 05:05:02 GMT</pubDate><media:content url="https://blog.codmind.com/content/images/2023/10/meggyn-pomerleau-hAYy2mFLjS8-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.codmind.com/content/images/2023/10/meggyn-pomerleau-hAYy2mFLjS8-unsplash.jpg" alt="Comprendiendo el estilo arquitectónico REST a profundidad"><p>Las siglas que dan nombre a este estilo arquitectónico vienen de <em>Representational State Transfer</em>, o en español, Transferencia de estado representacional y fue propuesto en un trabajo de tesis, me refiero a la tesis doctoral de Información y ciencias de la computación (PhD) desarrollada en el año 2000 por Roy Thomas Fielding titulada "<em>Architectural Styles and the Design of Network-based Software Architectures</em>" en la Universidad de California, Irvine. Dicha tesis está disponible <a href="https://ics.uci.edu/~fielding/pubs/dissertation/top.htm">aquí</a> por si quieras verla 😉.</p><p><strong>Definición</strong></p><p>REST es un estilo de arquitectura de software para realizar una comunicación cliente-servidor. Se apoya en el protocolo HTTP para la comunicación al servidor y los mensajes que se envían y reciben pueden estar en el formato de intercambio de datos JSON o también, aunque en menor medida, XML.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.codmind.com/content/images/2023/10/ante-hamersmit-IQE2vSrc_58-unsplash.jpg" class="kg-image" alt="Comprendiendo el estilo arquitectónico REST a profundidad"><figcaption>La uniformidad y el orden dan frutos. Foto de <a href="https://unsplash.com/es/@ante_kante?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Ante Hamersmit</a> en <a href="https://unsplash.com/es/fotos/abeja-amarilla-y-negra-en-una-valla-metalica-amarilla-durante-el-dia-IQE2vSrc_58?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p><strong>Principios de REST</strong></p><p>Para que la comunicación hacia un API utilizando el estilo REST funcione, debe seguir una serie de principios, los cuales son:</p><ul><li><em><em>Interfaz uniforme</em> o Uniform interface</em>: Este principio postula que REST está basado en recursos y estos deben ser sustantivos en plural por ejemplo: productos, estudiantes, peliculas.</li><li><em>Sin estado o <em>Stateless</em></em>: REST no tiene estados, esto quiere decir que una llamada al API es independiente de otra y no debe depender de ella, sin embargo sí se puede usar caché para reducir el tiempo de espera en consultas GET.</li><li><em><em>Cliente-Servidor</em> o Client-Server</em>: El servidor hace el procesamiento del API y expone los recursos a uno o muchos clientes, que pueden ser una aplicación de escritorio, una página web entre otros. El cliente debe ser independiente del servidor y toda comunicación a él se debe dar mediante el API.</li><li><em>Cacheable o Cacheability</em>: Siempre que sea posible los recursos deben de ser "cacheables" ya sea en el servidor o en el lado del cliente. La respuesta del serivdor debe contener esta información sobre cuando es posible o no el uso del caché. Esto se hace para incrementar el rendimiento en el cliente y la escalabilidad en el servidor.</li><li><em>Sistema de capas o Layered system</em>: El servicio web debe tener una arquitectura de capas, donde su evolución sea completamente transparente para el cliente</li></ul><p><strong>Características de un API REST</strong></p><p>Además de los principios arriba señalados, existen otros puntos a considerar los cuales vienen a ser características para todo API que implemente el estilo REST. Entre estos podemos considerar los siguientes:</p><ul><li><em><em>Operaciones específicas</em></em>: Cada acción u operacion sobre un recurso está bien definido y tiene un claro propósito, no existen los endpoints "multifuncionales". Por ejemplo si un endpoint por ejemplo es para insertar nuevos productos, no debería también insertar clientes.</li><li><em><em>Sintaxis estandarizada</em></em>: Cada recurso es accesible únicamente desde su URI.</li><li><em>HATEOAS</em>: Proviene del acrónimo de Hypermedia As The Engine Of Application State (Hipermedia como motor del estado de la aplicación). Es un principio o restricción de diseño que tiene REST el cual establece por ejemplo la información que nos da el web api debe incluir links, por poner un ejemplo.</li><li><em>Código bajo demanda</em> o <em>Code on demand</em> : Esta es una característica opcional. El servicio web comúnmente utiliza y envía recursos estáticos, sin embargo también tiene la opción de enviar código fuente el cual se va a ejecutar en el cliente, típicamente Javascript.</li></ul><p><strong>Más allá de REST...</strong></p><p>Y por si te lo hayas preguntado, ¿Existen acaso otras opciones aparte de REST? La respuesta es por supuesto, aquí te lo muestro mejor con una imagen:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.codmind.com/content/images/2023/10/image.png" class="kg-image" alt="Comprendiendo el estilo arquitectónico REST a profundidad"><figcaption>Estilos para crear APIs. Imagen tomada de <a href="https://bravedeveloper.com/2022/06/06/estilos-de-arquitectura-para-construir-apis/">bravedeveloper.com</a></figcaption></figure><p>Finalmente, y no menos importante, cabe aclarar un tema que es recurrente y sólo para que no te confundas como muchos. Escuchaste seguramente el término RESTful, ¿qué es?</p><p>Simple. Así como REST es el estilo de Arquitectura, RESTful es la implementación de dicha arquitectura.</p><p>Entonces por simple sentido común un API RESTful es un API que fue diseñada usando la arquitectura REST. Así de sencillo. En <a href="https://bravedeveloper.com/2021/09/01/que-es-rest-restful-api-restful-y-json/">esta entrada</a> que redacté también, puedes encontrar más información, espero te sirva!</p><p>Y ya sabes, si te ha gustado esta entrada considera compartirla con tu equipo de tecnología y tus amistades 🙌.</p><p>Créditos de imagen de portada: Foto de <a href="https://unsplash.com/es/@yungserif?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Meggyn Pomerleau</a> en <a href="https://unsplash.com/es/fotos/abeja-amarilla-y-negra-sobre-superficie-amarilla-y-negra-hAYy2mFLjS8?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a>.</p>]]></content:encoded></item><item><title><![CDATA[Establecer quotas o máximos de uso de CPU, RAM y disco de un contenedor Docker]]></title><description><![CDATA[Para establecer límites en el uso de CPU y memoria de un contenedor en Docker, puede usar el comando docker run con las opciones --cpus y --memory, respectivamente.]]></description><link>https://blog.codmind.com/establecer-quotas-o-maximos-de-uso-de-cpu-ram-y-disco-de-un-contenedor-docker/</link><guid isPermaLink="false">6391a4b424c7f14b9ccaf575</guid><category><![CDATA[docker]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Sat, 10 Dec 2022 20:42:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1605745341112-85968b19335b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGRvY2tlcnxlbnwwfHx8fDE2NzA0OTA0Mjc&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1605745341112-85968b19335b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGRvY2tlcnxlbnwwfHx8fDE2NzA0OTA0Mjc&ixlib=rb-4.0.3&q=80&w=2000" alt="Establecer quotas o máximos de uso de CPU, RAM y disco de un contenedor Docker"><p>Uno de los errores más comunes al ejecutar contenedores, es no establecer quotas o límites de uso de recursos a los contenedores, ocasionando que eventualmente tomen más recursos de los disponibles o desestabilicen el servidor.</p><h2 id="establecer-l-mites-de-uso-de-disco-duro">Establecer límites de uso de disco duro</h2><p>El comando <code>docker run</code> con la opción <code>--storage-opt</code> para establecer diferentes opciones de almacenamiento para el contenedor. Por ejemplo, para establecer un límite de almacenamiento de 10 GB para un contenedor, puede usar el siguiente comando:</p><pre><code class="language-bash">docker run --storage-opt size=10GB &lt;nombre-de-la-imagen&gt;</code></pre><p>También puede usar la opción <code>--storage-opt</code> para establecer límites en otros recursos de almacenamiento, como el número de archivos que se pueden almacenar en el contenedor o el tamaño máximo de un archivo individual. Para obtener más información sobre cómo establecer opciones de almacenamiento para un contenedor en Docker, consulte la documentación en el sitio web de Docker.</p><p></p><h2 id="establecer-l-mites-de-uso-de-cpu-y-memoria">Establecer límites de uso de CPU y Memoria</h2><p>Para establecer límites en el uso de CPU y memoria de un contenedor en Docker, puede usar el comando <code>docker run</code> con las opciones <code>--cpus</code> y <code>--memory</code>, respectivamente. Por ejemplo, para establecer un límite de uso de CPU de 0,5 y un límite de memoria de 512 MB para un contenedor, puede usar el siguiente comando:</p><pre><code class="language-bash">docker run --cpus 0.5 --memory 512MB &lt;nombre-de-la-imagen&gt;</code></pre><p>También puede usar las opciones <code>--cpu-shares</code> y <code>--memory-swap</code> para establecer límites adicionales en el uso de CPU y memoria. Para obtener más información sobre cómo establecer límites en el uso de recursos de un contenedor en Docker, consulte la documentación en el sitio web de Docker.</p><p><br>A continuación se presentan algunos ejemplos adicionales de cómo establecer límites en el uso de recursos de un contenedor en Docker:</p><ul><li>Para establecer un límite de uso de CPU de 1 y un límite de memoria de 2 GB para un contenedor, puede usar el siguiente comando:</li></ul><pre><code class="language-bash">docker run --cpus 1 --memory 2GB &lt;nombre-de-la-imagen&gt;</code></pre><ul><li>Para establecer un límite de uso de CPU de 0,25, un límite de memoria de 256 MB y un límite de almacenamiento de 5 GB para un contenedor, puede usar el siguiente comando:</li></ul><pre><code class="language-bash">docker run --cpus 0.25 --memory 256MB --storage-opt size=5GB &lt;nombre-de-la-imagen&gt;</code></pre><ul><li>Para establecer un límite de uso de CPU de 0,5, un límite de memoria de 1 GB, un límite de almacenamiento de 10 GB y un límite en el número de archivos almacenados en el contenedor (500 archivos), puede usar el siguiente comando:</li></ul><pre><code class="language-bash">docker run --cpus 0.5 --memory 1GB --storage-opt size=10GB --storage-opt max-files=500 &lt;nombre-de-la-imagen&gt;	</code></pre><p></p><h2 id="-qu-puede-pasar-si-no-fijo-l-mites">¿Qué puede pasar si no fijo límites?</h2><p>Si excede los límites establecidos para un contenedor en Docker, puede provocar que el contenedor se detenga o se bloquee. Esto puede ocurrir si el contenedor intenta utilizar más recursos de los permitidos, como CPU, memoria o almacenamiento. Cuando esto sucede, el contenedor deja de responder y ya no se puede acceder a su contenido o funcionalidades.</p><p>Para evitar que esto suceda, es importante establecer límites adecuados en el uso de recursos de un contenedor en Docker. De esta manera, se asegura de que el contenedor no consume más recursos de los necesarios, lo que puede mejorar su rendimiento y estabilidad. También es recomendable supervisar el uso de recursos del contenedor en tiempo real, para poder detectar y solucionar cualquier problema que pueda surgir antes de que afecte su funcionamiento.</p><p></p><h2 id="-c-mo-puedo-monitorear-el-uso-de-recursos">¿Cómo puedo monitorear el uso de recursos?</h2><p>Para monitorear el uso de recursos de un contenedor en Docker, puede usar el comando <code>docker stats</code>. Este comando muestra información en tiempo real sobre el uso de CPU, memoria, almacenamiento y otros recursos de uno o varios contenedores en ejecución. Para usar el comando <code>docker stats</code>, sólo tiene que ejecutarlo en una terminal y proporcionar el nombre o el identificador de los contenedores que desea monitorear.</p><p>Por ejemplo, para monitorear el uso de recursos de un contenedor llamado <code>my-container</code>, puede usar el siguiente comando:</p><pre><code class="language-bash">docker stats my-container</code></pre><p>Esto mostrará información en tiempo real sobre el uso de CPU, memoria, almacenamiento y otros recursos del contenedor <code>my-container</code>. Si desea monitorear el uso de recursos de varios contenedores, simplemente proporcione los nombres o identificadores de todos los contenedores que desea monitorear. Por ejemplo:</p><pre><code class="language-bash">docker stats my-container1 my-container2 my-container3</code></pre><p>También puede usar la opción <code>--no-stream</code> para mostrar la información del uso de recursos de manera estática, en lugar de actualizarse en tiempo real. </p><p>Cuando se ejecuta este comando, se muestra una tabla con información sobre el uso de CPU, memoria, almacenamiento y otros recursos de cada contenedor. La tabla incluye la siguiente información:</p><ul><li>El nombre o el identificador del contenedor.</li><li>El uso de CPU en porcentaje.</li><li>El uso de memoria en bytes.</li><li>El uso de almacenamiento en bytes.</li><li>El número de archivos en el contenedor.</li><li>El tamaño total de archivos en el contenedor.</li></ul><p>Por ejemplo, si se ejecuta el comando <code>docker stats</code> para supervisar el uso de recursos de un contenedor llamado <code>my-container</code>, se podría ver algo como lo siguiente:</p><pre><code class="language-bash">CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
69e3f12cddcd        my-container        0.12%               1.536MiB / 1.952GiB   0.08%               1.87kB / 0B         0B / 0B             1</code></pre><p>La tabla muestra información sobre el uso de CPU, memoria, almacenamiento y otros recursos del contenedor <code>my-container</code>. Si se supervisan varios contenedores, se mostrará una fila por cada contenedor.</p><p>Como dato adicional, también es posible sensar el uso de recursos de Docker en Prometheus y graficarlos en Grafana, pero esa es otra historia.</p><p>Si quieres aprender más sobre Docker, Docker Compose, Quotas y más cosas, te invito a nuestro curso de <a href="https://codmind.com/courses/docker">Docker para desarrolladores</a>, donde aprender a utilizar Docker como un pro montando un entorno de desarrollo completo conformado por varios Microservicios mediante Docker Compose.</p>]]></content:encoded></item><item><title><![CDATA[Explicando la función map de las colecciones Java]]></title><description><![CDATA[La función map de Java permite aplicar una función dada a cada elemento de una colección y devolver una nueva colección con los resultados.]]></description><link>https://blog.codmind.com/explicando-la-funcion-map-de-las-colecciones-java/</link><guid isPermaLink="false">6391a18e24c7f14b9ccaf549</guid><category><![CDATA[Java]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Sat, 10 Dec 2022 20:41:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1607081758728-78b82a34dc64?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE0fHxjb2xsZWN0aW9ufGVufDB8fHx8MTY3MDQ4ODczNQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1607081758728-78b82a34dc64?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDE0fHxjb2xsZWN0aW9ufGVufDB8fHx8MTY3MDQ4ODczNQ&ixlib=rb-4.0.3&q=80&w=2000" alt="Explicando la función map de las colecciones Java"><p>La función <code>map</code> de Java permite aplicar una función dada a cada elemento de una colección y devolver una nueva colección con los resultados. Esta función es muy útil para realizar operaciones como la transformación o filtrado de datos en una colección.</p><p>Por ejemplo, supongamos que queremos convertir una lista de cadenas en mayúsculas a minúsculas. Podríamos hacerlo de la siguiente manera:</p><pre><code class="language-java">List&lt;String&gt; words = Arrays.asList("the", "quick", "brown", "fox");

List&lt;String&gt; lowercaseWords = new ArrayList&lt;&gt;();
for (String word : words) {
  lowercaseWords.add(word.toLowerCase());
}</code></pre><p>Esta implementación funciona, pero puede resultar verbosa y poco elegante. Con la función <code>map</code>, podemos hacer lo mismo de manera más concisa y clara:</p><pre><code class="language-java">List&lt;String&gt; words = Arrays.asList("the", "quick", "brown", "fox");

List&lt;String&gt; lowercaseWords = words.stream()
  .map(word -&gt; word.toLowerCase())
  .collect(Collectors.toList());</code></pre><p>En este ejemplo, primero obtenemos un <code>Stream</code> de la lista <code>words</code>, luego usamos la función <code>map</code> para aplicar el método <code>toLowerCase</code> a cada elemento del <code>Stream</code>, y finalmente usamos el método <code>collect</code> para recolectar los resultados en una nueva lista.</p><p>La función <code>map</code> también se puede utilizar con expresiones lambda, lo que permite aún más concisión en el código:</p><pre><code class="language-java">List&lt;String&gt; words = Arrays.asList("the", "quick", "brown", "fox");

List&lt;String&gt; lowercaseWords = words.stream()
  .map(String::toLowerCase)
  .collect(Collectors.toList());
</code></pre><p>En este caso, estamos usando una referencia de método en lugar de una expresión lambda para aplicar el método <code>toLowerCase</code>. Esto es equivalente a la implementación anterior, pero es aún más conciso y legible.</p><p>En resumen, la función <code>map</code> es una herramienta muy útil en Java para aplicar una función dada a cada elemento de una colección y devolver una nueva colección con los resultados. Es una forma concisa y legible de realizar operaciones de transformación o filtrado en colecciones de datos.</p><p>Si quieres aprender más sobre Java, Colecciones y Lamdas, te invitamos a nuestro curso de <a href="https://codmind.com/courses/java">Java Core</a> y <a href="https://codmind.com/courses/java-collections">Mastering Java Collection</a> y nuestro curso <a href="https://codmind.com/courses/java-lambda">Java Lamdas</a>.</p>]]></content:encoded></item><item><title><![CDATA[Como cargar un archivo utilizando Spring Boot]]></title><description><![CDATA[Crearemos un servicio que nos permite cargar un archivo y guardarlo en disco o en AWS.]]></description><link>https://blog.codmind.com/como-cargar-un-archivo-utilizando-spring-boot/</link><guid isPermaLink="false">63919bd524c7f14b9ccaf50f</guid><category><![CDATA[spring-boot]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Sat, 10 Dec 2022 08:27:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1638847868668-a05a2f69622f?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDExfHxzdG9yYWdlfGVufDB8fHx8MTY3MDQ4NzYyMA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1638847868668-a05a2f69622f?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDExfHxzdG9yYWdlfGVufDB8fHx8MTY3MDQ4NzYyMA&ixlib=rb-4.0.3&q=80&w=2000" alt="Como cargar un archivo utilizando Spring Boot"><p>Para crear un servicio que te permita cargar un archivo usando Spring Boot, primero debes crear una interfaz de servicio que declare el método que se encargará de cargar el archivo. Por ejemplo:</p><pre><code class="language-java">public interface FileUploadService {
  void uploadFile(InputStream inputStream);
}</code></pre><p>Luego puedes implementar esta interfaz en tu clase de servicio y proporcionar la lógica para cargar el archivo en el método <code>uploadFile()</code>. Por ejemplo:</p><p></p><h2 id="guardar-el-archivo-en-un-disco-local">Guardar el archivo en un disco local</h2><pre><code class="language-java">@Service
public class FileUploadServiceImpl implements FileUploadService {

  private final String UPLOAD_DIR = "/path/to/upload/directory";

  @Override
  public void uploadFile(InputStream inputStream) {
    try {
      byte[] bytes = IOUtils.toByteArray(inputStream);
      Path path = Paths.get(UPLOAD_DIR + "/" + UUID.randomUUID().toString());
      Files.write(path, bytes);
    } catch (IOException e) {
      // manejar excepción
    }
  }

}</code></pre><p></p><h2 id="guardar-el-archivo-en-aws">Guardar el archivo en AWS</h2><p>Otra alternativa sería tomar ese mismo archivo y guardarlo directamente en un storage de AWS:</p><pre><code class="language-java">@Service
public class FileUploadServiceImpl implements FileUploadService {

  @Value("${aws.accessKey}")
  private String accessKey;

  @Value("${aws.secretKey}")
  private String secretKey;

  @Value("${aws.s3.bucketName}")
  private String bucketName;

  @Override
  public void uploadFile(InputStream inputStream) {
    try {
      BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
      AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
          .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
          .build();

      ObjectMetadata metadata = new ObjectMetadata();
      metadata.setContentType("application/octet-stream");
      metadata.setContentLength(inputStream.available());

      PutObjectRequest request = new PutObjectRequest(bucketName, UUID.randomUUID().toString(), inputStream, metadata);
      s3Client.putObject(request);
    } catch (IOException e) {
      // manejar excepción
    }
  }

}</code></pre><p>En este ejemplo, se crea un cliente <code>AmazonS3</code> utilizando las credenciales de AWS proporcionadas en el archivo de configuración de la aplicación. Luego se crea un objeto <code>ObjectMetadata</code> y se establece el tipo de contenido y el tamaño del archivo. Finalmente, se crea un objeto <code>PutObjectRequest</code> que contiene la información del archivo, incluyendo el nombre del bucket de S3 en el que se desea guardar el archivo, el <code>InputStream</code> del archivo y el objeto <code>ObjectMetadata</code> creado anteriormente. Luego se llama al método <code>putObject()</code> del cliente <code>AmazonS3</code> para guardar el archivo en el bucket de S3.</p><h2 id="implementar-el-controller">Implementar el Controller</h2><p>Luego puedes inyectar la implementación del servicio en cualquier componente de tu aplicación que necesite cargar un archivo, como un controlador de Spring MVC, y llamar al método <code>uploadFile()</code> proporcionando el <code>InputStream</code> del archivo que se desea cargar. Por ejemplo:</p><pre><code class="language-java">@Controller
public class MyController {

  @Autowired
  private FileUploadService fileUploadService;

  ...

  @PostMapping("/upload")
  public void handleFileUpload(@RequestParam("file") MultipartFile file) {
    fileUploadService.uploadFile(file.getInputStream());
  }

}</code></pre><p>En este ejemplo, se asume que el controlador está manejando una solicitud de carga de archivos enviada mediante un formulario HTML utilizando el enctype <code>multipart/form-data</code>. El archivo se recibe como un parámetro de la solicitud y se proporciona al método <code>uploadFile()</code> del servicio mediante el método <code>getInputStream()</code> del objeto <code>MultipartFile</code>.</p><p></p><h2 id="probar-el-servicio-mediante-curl">Probar el servicio mediante CURL</h2><p>Para cargar un archivo en un servicio de Spring Boot mediante una solicitud <code>curl</code>, debes enviar una solicitud <code>POST</code> al endpoint del servicio que maneja la carga de archivos y proporcionar el archivo en el cuerpo de la solicitud utilizando el enctype <code>multipart/form-data</code>. Por ejemplo, si el endpoint del servicio es <code>/upload</code> y el archivo se llama <code>file.txt</code>, puedes usar el siguiente comando <code>curl</code>:</p><pre><code class="language-bash">curl -X POST -F "file=@file.txt" http://localhost:8080/upload</code></pre><p>En este caso, se está enviando una solicitud <code>POST</code> al endpoint <code>/upload</code> en el host <code>localhost</code> en el puerto <code>8080</code>. El archivo se proporciona en el cuerpo de la solicitud utilizando el enctype <code>multipart/form-data</code> y se especifica mediante el parámetro <code>file</code> y el valor <code>@file.txt</code>, lo que indica que el archivo se llama <code>file.txt</code> y se encuentra en el directorio actual.</p><p>Tenga en cuenta que este comando <code>curl</code> es solo un ejemplo y debería ser adaptado según sea necesario para cumplir con las necesidades específicas de la aplicación. Por ejemplo, podrías necesitar proporcionar información de autenticación si el servicio está protegido por autenticación.</p><p></p><p>Si quieres aprender más sobre como crear API REST de forma profesional, te inviamos a nuestro curso <a href="https://codmind.com/courses/api-rest-con-spring-boot">Mastering API REST con Spring Boot</a>, donde aprenderás todo lo necesario para crear un API desde cero, con seguridad, validaciones, DTO y las mejores prácticas de la industria.</p>]]></content:encoded></item><item><title><![CDATA[Como validar un request con Spring boot]]></title><description><![CDATA[Spring boot proporciona diferentes formas de validar los request, que van desde mecanismos simples, hasta complejas estructuras de clases de validación]]></description><link>https://blog.codmind.com/como-validar-un-request-con-spring-boot/</link><guid isPermaLink="false">6391934c24c7f14b9ccaf494</guid><category><![CDATA[spring-boot]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Fri, 09 Dec 2022 16:00:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1554279652-51eee9372f32?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDEwfHxndWFyZHxlbnwwfHx8fDE2NzA0ODY1Mjg&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1554279652-51eee9372f32?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDEwfHxndWFyZHxlbnwwfHx8fDE2NzA0ODY1Mjg&ixlib=rb-4.0.3&q=80&w=2000" alt="Como validar un request con Spring boot"><p>A diferencia de lo que uno puedo llegar a pensar, Spring boot proporciona diferentes formas de validar los request, que van desde mecanismos simples, hasta complejas estructuras de clases de validación. En este artículo trataremos de explicar los más utilizados y como los puedes implementar en tus proyectos.</p><p></p><h2 id="validaci-n-de-p-rametros-mediante-bean-validator">Validación de párametros mediante Bean Validator</h2><p>La primera forma es usando anotaciones de validación en los parámetros del método del controlador. Por ejemplo, si quieres validar que un parámetro de tipo String no sea nulo ni vacío, puedes usar la anotación @NotNull y @Size:</p><pre><code class="language-java">@PostMapping("/api/example")
public ResponseEntity&lt;String&gt; example(@NotNull @Size(min = 1) String param) {
    // Tu código aquí
}</code></pre><p>Si hay varios parámetros que necesitan validación, puedes usar la anotación @Valid en el parámetro que contiene las anotaciones de validación. Por ejemplo:</p><pre><code class="language-java">public class ExampleForm {
    @NotNull
    @Size(min = 1)
    private String param1;

    @NotNull
    @Min(1)
    private Integer param2;

    // getters y setters
}

@PostMapping("/api/example")
public ResponseEntity&lt;String&gt; example(@Valid @RequestBody ExampleForm form) {
    // Tu código aquí
}</code></pre><p>La anotación @Valid ayuda a que Spring Boot valide el request antes de ejecutar el método, lo cual es de grán ayuda a evitar que incluse se ejecute el método, sin embargo, abrá ocasiones donde será mejor controlar nosotros mismo el momento exacto de la validación, es por ello que podemos implementar el método de esta otra forma:</p><pre><code class="language-java">@PostMapping("/api/example")
public ResponseEntity&lt;String&gt; example(@Valid @RequestBody ExampleForm form) {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
	Validator validator = factory.getValidator();


	Set&lt;ConstraintViolation&lt;ExampleForm&gt;&gt; violations = validator.validate(form);
	if (!violations.isEmpty()) {
    	// Se encontraron violaciones, procesa las violaciones aquí
	}
}</code></pre><p>Bean Validation proporciona un conjunto de anotaciones que puedes usar para validar los atributos de una clase. Algunas de las anotaciones más comunes son:</p><ul><li>@NotNull: indica que el atributo no puede ser nulo.</li><li>@Size: indica el tamaño mínimo y/o máximo permitido para un atributo de tipo String o Collection.</li><li>@Min y @Max: indican el valor mínimo y/o máximo permitido para un atributo numérico.</li><li>@Email: indica que el atributo debe ser una dirección de correo electrónico válida.</li><li>@Past y @Future: indican que un atributo de tipo Date o Calendar debe ser una fecha en el pasado o en el futuro, respectivamente.</li><li>@Pattern: indica un patrón que debe cumplir un atributo de tipo String.</li><li>@DecimalMin y @DecimalMax: indican el valor mínimo y/o máximo permitido para un atributo de tipo BigDecimal.</li><li>@NotEmpty: indica que un atributo de tipo String, Collection o Map no puede ser vacío.</li></ul><p>Por ejemplo, si tienes una clase que representa un formulario de búsqueda de libros, puedes usar las anotaciones de validación para validar que el título del libro no sea nulo ni vacío, que el precio mínimo y máximo sean números válidos y que la fecha de publicación sea una fecha en el pasado:</p><pre><code class="language-java">public class BookSearchForm {
    @NotNull
    @NotEmpty
    private String title;

    @DecimalMin("0.00")
    @DecimalMax("9999.99")
    private BigDecimal priceMin;

    @DecimalMin("0.00")
    @DecimalMax("9999.99")
    private BigDecimal priceMax;

    @Past
    private Date publicationDate;

    // getters y setters
}</code></pre><p>Toma en cuenta que el API de Bean Validator no es parte de Spring Boot, por lo que será necesario agregar la librerías a tu archivo POM.</p><pre><code class="language-xml">&lt;dependency&gt;
    &lt;groupId&gt;javax.validation&lt;/groupId&gt;
    &lt;artifactId&gt;validation-api&lt;/artifactId&gt;
    &lt;version&gt;2.0.1.Final&lt;/version&gt;
&lt;/dependency&gt;</code></pre><h2 id="clases-de-tipo-validador">Clases de tipo validador</h2><p>Una forma es creando una clase de tipo Validator y registrándola como un bean en la aplicación. La clase Validator tiene un método "supports" que indica qué tipo de objetos puede validar y un método "validate" que recibe el objeto a validar y un objeto de tipo Errors, en el que se pueden agregar los errores de validación encontrados. Por ejemplo:</p><pre><code class="language-java">public class ExampleFormValidator implements Validator {

    @Override
    public boolean supports(Class&lt;?&gt; clazz) {
        return ExampleForm.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        ExampleForm form = (ExampleForm) target;
        if (form.getParam1() == null || form.getParam1().trim().isEmpty()) {
            errors.rejectValue("param1", "field.required", "El campo param1 es requerido");
        }
        if (form.getParam2() == null || form.getParam2() &lt; 1) {
            errors.rejectValue("param2", "field.invalid", "El campo param2 es inválido");
        }
    }
}</code></pre><p>Para usar el validador, debes registrarlo como un bean en la aplicación y usar la anotación @InitBinder en el método del controlador para asociar el validador a los parámetros que deben ser validados. Por ejemplo:</p><pre><code class="language-java">@RestController
public class ExampleController {

    private final ExampleFormValidator validator;

    public ExampleController(ExampleFormValidator validator) {
        this.validator = validator;
    }

    @InitBinder("form")
    public void initBinder(WebDataBinder binder) {
        binder.setValidator(validator);
    }

    @PostMapping("/api/example")
    public ResponseEntity&lt;String&gt; example(@Valid @ModelAttribute("form") ExampleForm form) {
        // Tu código aquí
    }
}</code></pre><h2 id="controlar-los-errores-de-validaci-n">Controlar los errores de validación</h2><p>Cuando se produce un error de validación, Spring Boot lanzará una excepción de tipo MethodArgumentNotValidException. Puedes manejar esta excepción de varias formas, como por ejemplo creando una clase de tipo @ControllerAdvice que maneje la excepción y devuelva una respuesta adecuada al usuario. Por ejemplo:</p><pre><code class="language-java">@ControllerAdvice
public class ValidationErrorHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity&lt;String&gt; handleValidationErrors(MethodArgumentNotValidException ex) {
        List&lt;FieldError&gt; fieldErrors = ex.getBindingResult().getFieldErrors();
        // Crea una respuesta adecuada basada en los errores de validación
        return ResponseEntity.badRequest().body(/* Tu respuesta aquí */);
    }
}
</code></pre><p></p><p>Si quieres aprender más sobre el desarrollo de API con Spring Boot, no te puede perder nuestro curso <a href="https://codmind.com/courses/api-rest-con-spring-boot">Mastering API REST con Spring Boot</a>, donde aprenderás a crear un API REST desde cero con seguridad (JWT), validadores, DTO y las mejores prácticas de la industria.</p>]]></content:encoded></item><item><title><![CDATA[Agregar filtros dinámicos en Spring boot mediante Specification]]></title><description><![CDATA[La interfaz Specification le permite construir consultas dinámicas en función de los parámetros proporcionados.]]></description><link>https://blog.codmind.com/filtros-dinamicos-en-spring-boot-mediante/</link><guid isPermaLink="false">6391907824c7f14b9ccaf46d</guid><category><![CDATA[spring-boot]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Thu, 08 Dec 2022 16:00:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1545424273-4dd93a233016?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDR8fGZpbHRlcnxlbnwwfHx8fDE2NzA0ODQzMjQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1545424273-4dd93a233016?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDR8fGZpbHRlcnxlbnwwfHx8fDE2NzA0ODQzMjQ&ixlib=rb-4.0.3&q=80&w=2000" alt="Agregar filtros dinámicos en Spring boot mediante Specification"><p>Si desea agregar filtros dinámicos a un servicio de Spring Boot, puede hacerlo utilizando la interfaz <code>Specification</code> de JPA. La interfaz <code>Specification</code> le permite construir consultas dinámicas en función de los parámetros proporcionados.</p><p>Por ejemplo, supongamos que tiene una entidad <code>User</code> con los atributos <code>firstName</code>, <code>lastName</code> y <code>email</code>. Si desea crear un servicio que pueda buscar usuarios por cualquiera de estos tres campos, utilizando filtros dinámicos, podría hacer algo como esto:</p><pre><code class="language-java">public class UserSpecification implements Specification&lt;User&gt; {

    private String firstName;
    private String lastName;
    private String email;

    public UserSpecification(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    @Override
    public Predicate toPredicate(Root&lt;User&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder cb) {
        List&lt;Predicate&gt; predicates = new ArrayList&lt;&gt;();

        if (firstName != null) {
            predicates.add(cb.equal(root.get("firstName"), firstName));
        }

        if (lastName != null) {
            predicates.add(cb.equal(root.get("lastName"), lastName));
        }

        if (email != null) {
            predicates.add(cb.equal(root.get("email"), email));
        }

        return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    }
}</code></pre><p>Luego, en su servicio, puede utilizar la clase <code>UserSpecification</code> para construir una consulta dinámica utilizando los parámetros proporcionados. Por ejemplo:</p><pre><code class="language-java">public List&lt;User&gt; findUsers(String firstName, String lastName, String email) {
    UserSpecification spec = new UserSpecification(firstName, lastName, email);
    return userRepository.findAll(spec);
}</code></pre><p>De esta manera, puede proporcionar cualquiera de los tres parámetros de búsqueda al servicio, y la consulta se construirá dinámicamente en función de los parámetros proporcionados.</p><p>Si desea obtener más información sobre cómo utilizar la interfaz <code>Specification</code> en Spring, puede consultar la <a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications">documentación oficial de Spring</a>.</p><p>Si quieres conocer más sobre Spring boot y JPA, te invitamos a nuestros cursos profesionales de <a href="https://codmind.com/courses/api-rest-con-spring-boot">Mastering API REST con Spring boot</a> y <a href="https://codmind.com/courses/jpa">Mastering JPA con Hibernate</a>, para aprender como un pro a dominar estas tecnnologías.</p>]]></content:encoded></item><item><title><![CDATA[Establecer el Time Zone en Spring boot]]></title><description><![CDATA[El Time Zone se refiere al zona horaria que se utiliza para manejar las fechas y horas en una aplicación basada en Spring Boot]]></description><link>https://blog.codmind.com/establecer-el-time-zone-en-spring-boot/</link><guid isPermaLink="false">6391892124c7f14b9ccaf3f9</guid><category><![CDATA[spring-boot]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Thu, 08 Dec 2022 07:06:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1457883626133-458e5ec26948?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI3fHx0aW1lJTIwem9uZXxlbnwwfHx8fDE2NzA0ODMwMzQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1457883626133-458e5ec26948?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI3fHx0aW1lJTIwem9uZXxlbnwwfHx8fDE2NzA0ODMwMzQ&ixlib=rb-4.0.3&q=80&w=2000" alt="Establecer el Time Zone en Spring boot"><p>El Time Zone se refiere al zona horaria que se utiliza para manejar las fechas y horas en una aplicación basada en Spring Boot. El Time Zone se utiliza para asegurarse de que las fechas y horas sean consistentes en todas las partes de la aplicación y que se reflejen correctamente para los usuarios en diferentes zonas horarias.</p><p>Por ejemplo, si un usuario en Nueva York está utilizando una aplicación basada en Spring Boot que se ejecuta en San Francisco, es posible que las fechas y horas que se muestren en la aplicación se refieran a la hora local de San Francisco en lugar de a la hora local de Nueva York. Esto puede ser confuso para el usuario y puede causar problemas en la aplicación si no se maneja correctamente.</p><p>Para solucionar este problema, Spring Boot permite especificar la zona horaria en la que se ejecuta la aplicación. Esto se hace mediante la configuración del Time Zone en el archivo de configuración de la aplicación. Una vez que se ha establecido la zona horaria, Spring Boot se encarga de asegurarse de que todas las fechas y horas sean interpretadas correctamente en relación a esa zona horaria, lo que permite que la aplicación funcione correctamente para usuarios en diferentes zonas horarias.</p><h2 id="aqu-hay-algunos-ejemplos-de-c-mo-se-puede-utilizar-la-configuraci-n-del-time-zone-en-spring-boot-">Aquí hay algunos ejemplos de cómo se puede utilizar la configuración del Time Zone en Spring Boot:</h2><p></p><ul><li>Si su aplicación se ejecuta en Nueva York y desea que las fechas y horas se interpreten en relación a la zona horaria de Nueva York, puede establecer el Time Zone en "America/New_York" en el archivo de configuración de la aplicación.</li><li>Si su aplicación se ejecuta en Londres y desea que las fechas y horas se interpreten en relación a la zona horaria de Londres, puede establecer el Time Zone en "Europe/London" en el archivo de configuración de la aplicación.</li><li>Si su aplicación se ejecuta en San Francisco y desea que las fechas y horas se interpreten en relación a la zona horaria de San Francisco, puede establecer el Time Zone en "America/Los_Angeles" en el archivo de configuración de la aplicación.</li></ul><p>En cada uno de estos casos, Spring Boot se encargará de asegurarse de que las fechas y horas se interpreten correctamente en relación a la zona horaria especificada en la configuración. Esto permitirá que la aplicación funcione correctamente para usuarios en diferentes zonas horarias.</p><p></p><h2 id="como-establecer-el-time-zone">Como establecer el Time Zone<br></h2><p>Primero, debes configurar el TimeZone en tu archivo de propiedades de Spring Boot. Puedes hacerlo agregando la siguiente línea al archivo <code>application.properties</code>:</p><pre><code class="language-yaml">spring.jackson.time-zone=America/Mexico_City</code></pre><p>En lugar de especificar el TimeZone en el archivo de propiedades, también puedes configurarlo en tu código Java. Para hacerlo, puedes agregar la siguiente línea en tu archivo de configuración de Spring Boot:</p><pre><code class="language-java">@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
    b.timeZone(TimeZone.getTimeZone("America/Mexico_City"));
    return b;
}</code></pre><p>Si deseas establecer el TimeZone en una aplicación Spring Boot que utiliza JPA (Java Persistence API), puedes hacerlo agregando la siguiente línea en tu archivo de configuración de Spring Boot:</p><pre><code class="language-java">@Bean
public JpaProperties jpaProperties() {
    JpaProperties jpaProperties = new JpaProperties();
    jpaProperties.setDatabaseZone(TimeZone.getTimeZone("America/Mexico_City"));
    return jpaProperties;
}</code></pre><p></p><h2 id="o-en-el-caso-de-utc">O en el caso de UTC</h2><pre><code class="language-yaml">spring.jackson.time-zone=UTC</code></pre><pre><code class="language-java">@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
    b.timeZone(TimeZone.getTimeZone("UTC"));
    return b;
}</code></pre><pre><code class="language-java">@Bean
public JpaProperties jpaProperties() {
    JpaProperties jpaProperties = new JpaProperties();
    jpaProperties.setDatabaseZone(TimeZone.getTimeZone("UTC"));
    return jpaProperties;
}</code></pre><p></p><h2 id="establecer-el-time-zone-desde-la-l-nea-de-comandos">Establecer el Time Zone desde la línea de comandos</h2><p>Para establecer el TimeZone desde la línea de comandos en una aplicación Spring Boot, puedes usar el parámetro <code>spring.jackson.time-zone</code> en la línea de comandos al iniciar tu aplicación. Por ejemplo, si quieres establecer el TimeZone a UTC, puedes usar el siguiente comando:</p><pre><code class="language-bash">java -jar my-app.jar --spring.jackson.time-zone=UTC</code></pre><p>Si quieres establecer el TimeZone a America/Mexico_City, puedes usar el siguiente comando:</p><pre><code class="language-bash">java -jar my-app.jar --spring.jackson.time-zone=America/Mexico_City</code></pre><p>También puedes usar el parámetro <code>user.timezone</code> para establecer el TimeZone en la JVM. Por ejemplo, si quieres establecer el TimeZone a UTC, puedes usar el siguiente comando:</p><pre><code class="language-bash">java -Duser.timezone=UTC -jar my-app.jar</code></pre><p>Si quieres establecer el TimeZone a America/Mexico_City, puedes usar el siguiente comando:</p><pre><code class="language-bash">java -Duser.timezone=America/Mexico_City -jar my-app.jar</code></pre><p>En resumen, el Time Zone en Spring Boot es una configuración importante que se utiliza para manejar correctamente las fechas y horas en una aplicación basada en Spring Boot y asegurarse de que se interpreten correctamente en relación a la zona horaria en la que se encuentran los usuarios.</p>]]></content:encoded></item><item><title><![CDATA[¿Cómo detener un contenedor de Docker?]]></title><description><![CDATA[Para detener un contenedor de Docker, puedes usar el comando docker stop seguido del nombre o ID del contenedor que deseas detener]]></description><link>https://blog.codmind.com/como-detener-un-contenedor-de-docker/</link><guid isPermaLink="false">638ec68a24c7f14b9ccaf3d6</guid><category><![CDATA[docker]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Tue, 06 Dec 2022 04:40:27 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1605745341112-85968b19335b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGRvY2tlcnxlbnwwfHx8fDE2NzAzMDE0MjM&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1605745341112-85968b19335b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGRvY2tlcnxlbnwwfHx8fDE2NzAzMDE0MjM&ixlib=rb-4.0.3&q=80&w=2000" alt="¿Cómo detener un contenedor de Docker?"><p>Para detener un contenedor de Docker, puedes usar el comando <code>docker stop</code> seguido del nombre o ID del contenedor que deseas detener. Por ejemplo, si deseas detener un contenedor llamado "mi_contenedor", puedes usar el siguiente comando:</p><pre><code class="language-bash">docker stop mi_contenedor</code></pre><p>Si no conoces el nombre exacto del contenedor que deseas detener, puedes usar el comando <code>docker ps</code> para ver una lista de todos los contenedores en ejecución en tu máquina. Esto te mostrará el ID y el nombre de cada contenedor, lo que te permitirá detener el contenedor que desees de manera precisa.</p><p>Por ejemplo, si ejecutas el comando <code>docker ps</code>, puedes ver una salida similar a esta:</p><pre><code class="language-bash">CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES 
2f72b9733ccd  nginx  "nginx -g 'daemon of…"  3 minutes ago  Up 3 minutes  80/tcp  nginx_1</code></pre><p>En este ejemplo, el contenedor tiene un ID de <code>2f72b9733ccd</code> y un nombre de <code>nginx_1</code>. Para detener este contenedor, puedes usar el siguiente comando:</p><pre><code class="language-bash">docker stop 2f72b9733ccd</code></pre><p>O bien, puedes usar el nombre del contenedor en lugar del ID:</p><pre><code class="language-bash">docker stop nginx_1</code></pre><p>Ambos comandos detendrán el contenedor y lo sacarán del estado de ejecución. Si deseas volver a iniciar el contenedor, puedes usar el comando <code>docker start</code> seguido del nombre o ID del contenedor que deseas iniciar.</p><p>Puedes aprender más sobre Docker en muestro curso para <a href="https://codmind.com/courses/docker">Docker para desarrolladores</a>, donde aprenderás desde instalar, ejecutar contenedores, crear tus própias imáges, subir tus imágenes a Docker Hub y utilizar Docker Compose para levantar un ambiente de Microservicios.<br></p>]]></content:encoded></item><item><title><![CDATA[Table Id VS Natural Id]]></title><description><![CDATA[Natural id es un termino que se utiliza para hacer referencia a un identificador del mundo real, mas allá de como identifiquemos un registro en la base de datos.]]></description><link>https://blog.codmind.com/table-id-vs-natural-id/</link><guid isPermaLink="false">6305550a24c7f14b9ccaf2b0</guid><category><![CDATA[database]]></category><dc:creator><![CDATA[Oscar Javier Blancarte Iturralde]]></dc:creator><pubDate>Wed, 24 Aug 2022 17:31:32 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1469474968028-56623f02e42e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fG5hdHVyZXxlbnwwfHx8fDE2NjEzNjIzNDY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fG5hdHVyZXxlbnwwfHx8fDE2NjEzNjIzNDY&ixlib=rb-1.2.1&q=80&w=2000" alt="Table Id VS Natural Id"><p>Una de las cuestionas más relevantes al momento de diseñar muestro modelo de bases de datos es definir la llave primaria, sin embargo, esta acción casi siempre ovedece más a una necesidad de integridad que a un identificador real para el negocio.</p><p>Solo por poner algunos ejemplos, si creamos un tabla para libros, seguramente pondremos una columna autoincrementable llamada <code>id</code> o <code>libro_id</code>, cuando en realidad todos sabemos que el identificador del mundo real de un libro es el ISBN, del mismo modo, si creamos una tabla para guardar a las personas, vamos a crear una tabla similar con el <code>id</code> o <code>persona_id</code>, cuando en realidad el identificado sea el número de identificación de cada país, llamese CURP o DNI según cada país.</p><p>Si bien la estrategia de poner un identificado númerico ayuda mucho a consultar con mayor velocidad los registros y hacerlo de forma más uniforme, la realidad es que en el múndo moderno donde vivimos, muchos de los registros se buscan por su identificador del mundo real, es decir, lo que conocemos como Natural ID o Identificador Natural.</p><p>Por ejemplo, si estas leyendo este artículo, podrás observar que la URL de esta página sea algo así como https://codmind.com/blog/table-id-vs-natural-id, lo que quiere decir que en realidad el artículo está siendo buscado por su nombre (los guinos medios son para hacerlo amigables para el naveador) y no por un ID. </p><p>Otro ejemplo muy utilizado son las API, por ejemplo, imagina que estas desarrollando un servicio para crear un cobro recurrente a los usuario. Veamos como se vería un request con los IDs tradicionales:</p><pre><code class="language-json">{
  "moneda": 10,
  "precio": 199,
  "pais": 3,
  "status": 1,
  "frecuencia": 1
}</code></pre><p>El request anterior, en realidad requiere de varias entidades externas, como es la moneda, el país, el status y la frecuencia de cobro, en este sentido, podrías decir que moneda=10 sería como decir moneda=USD, pais=3 sería US, status=1 sería activo y frecuencia=1 sería mensual. En este sentido, accediendo a la información mediante el id de la tabla y no mediante el Natural ID, lo cual haría la vida más simple para los usuario de nuestra API, la cual se podría ver de esta otra forma:</p><pre><code class="language-json">{
  "moneda": "usd",
  "precio": 199,
  "pais": "MX",
  "status": "activo",
  "frecuencia": "mensual"
}</code></pre><p>Quiero que observer detenidamente estos dos request y cual crees que tenga más sentido para un usuario ageno a la aplicación y te darás cuenta que el natural id comienza a cobrar sentido.</p><h2 id="-c-mo-se-implementan-un-natural-id">¿Cómo se implementan un natural id?</h2><p>La realidad es que el ID número que ya conocemos no esta peleado con el natural id, al contrario, pueden coexitir en una misma tabla, de esta forma, tenemos tablas que tiene el ID de siempre y una columna que puede funsionar con natural id. Si bien esta columna se puede llamar como sea, ya que dependera de cada tabla, la idea es que debe estar marcada como única, para impedir que existe otro registro con el mismo natural id, de la misma forma, deberemos crear un índice que  ayude a realizar búsquedas más rápida sobre ese campo. </p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2022/08/image-1.png" class="kg-image" alt="Table Id VS Natural Id"></figure><p>Como podemos apreciar en el diagrama anterior, las tablas  <code>Monedas</code>, <code>Status</code> , <code>Paises</code> y <code>Frecuencias</code> cuanta con una columna que funciona como ID númerico y tenemos adicional una columna <code>nombre</code> que funciona como natural id. Esta útima columna, podrás apreciar que esta dentro de los índices marcada como única, lo que garantiza que cuando yo busque un registro por natural id siempre obtenga 0 o 1 registro, pero nunca más de 1.</p><p>Si vemos esto a nivel de aplicación, podríamos tener servicios que busquen los registros por su natural id, algo así:</p><pre><code class="language-java">public void suscripcion(SuscripcionRequest req) {
	
    Moneda moneda = monedaService.findByNombre(req.getMoneda())
    	.orElseThrow(() -&gt; new RuntimeException("No existe la moneda" ));
        
    Pais pais = paisService.findByNombre(req.getPais())
    	.orElseThrow(() -&gt; new RuntimeException("No existe el país" ));
    
    Frecuencia frecuencia = frecuenciaService.findByNombre(req.getFrecuencia())
    	.orElseThrow(() -&gt; new RuntimeException("No existe la frecuencia" ));
        
    Status status = statusService.findByNombre(req.getStatus())
    	.orElseThrow(() -&gt; new RuntimeException("No existe el status" ));
        
    Suscripcion suscripcion = Suscripcion.build
    	.moneda(moneda)
        .pais(pais)
        .frecuencia(frecuencia)
        .status(status)
        .precio(req.getPrecio())
        .build();
        
    suscripcionService.save(suscripcion);

}</code></pre><p>Podrás apreciar que la capa de controladores busca las relaciones por natural id y luego la asigna al objeto suscripción para terminar persistiendola.</p><h2 id="conclusi-nes">Conclusiónes</h2><p>Como podemos observar implementar un natural id no implica nada adicional de lo que ya hacemos, ya que por lo general muchas de las tablas ya cuenta con una columna que puede funcionar como natural id, solo faltaría agregar la restricción de único y not null para asegurar la integridad de los datos.</p>]]></content:encoded></item><item><title><![CDATA[Entendiendo los principios SOLID]]></title><description><![CDATA[Nada mejor que entender los principios de algo, consolida tus conocimientos como desarrollador siguiendo las buenas prácticas probadas y efectivas.]]></description><link>https://blog.codmind.com/entendiendo-los-principios-solid/</link><guid isPermaLink="false">60f77c47e6357f340b7e0cb5</guid><dc:creator><![CDATA[Gerson Azabache Martínez]]></dc:creator><pubDate>Tue, 12 Oct 2021 02:07:19 GMT</pubDate><media:content url="https://blog.codmind.com/content/images/2021/07/ashim-d-silva-fAImogU-ycw-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.codmind.com/content/images/2021/07/ashim-d-silva-fAImogU-ycw-unsplash.jpg" alt="Entendiendo los principios SOLID"><p>En esta, mi primera entrada en este reconocido blog, estaré tocando el tema de los principios SOLID, para tener los conceptos más claros, ya que es una de las preguntas más comunes en las entrevistas de trabajo para desarrolladores de software y además te permitirá tener una buena base en la programación orientada a objetos. Ya he escrito acerca de este tema y he recibido feedback, aprovechando eso trataré de manejar el tema con palabras sencillas y prácticas para una comprensión rápida del tema 😉.</p><p>El aprender estos principios SOLID te supondrá una ventaja competitiva respecto a la docena de programadores que pugnan también por el mismo puesto que tú y una vez dentro del trabajo te ayudará a que tu código sea más <em>mantenible</em>, organizado, legible y escalable, eso es invaluable con el tiempo y te hará más fácil tu trabajo a mediano plazo, además que estarás cumpliendo con un estándar de calidad mínimo en la industria del software y de la empresa misma, todo esto te hará más valioso y deseable como desarrollador para las empresas y eso significa que puedes tentar un cheque más grande a fin de mes ¡provecho!.</p><p>La palabra SOLID es un acrónimo de las primeras letras de los <strong>5 principios</strong> que veremos a continuación, fueron propuestos por Robert Martin en el 2000 (<a href="https://bravedeveloper.com/2020/11/07/top-5-libros-para-programadores/"><em>aquí</em> </a>recomiendo entre otros un libro de él), estos principios son guías y buenas prácticas a seguir para obtener un código de calidad, aun teniendo en cuenta esto, no debemos aplicarlos a rajatabla o forzar su aplicación en nuestro código porque hay ocasiones en los que podemos prescindir de alguno de sus principios por practicidad. </p><p>Hay que tener en cuenta que si forzamos la aplicación de estos principios SOLID podríamos hacer más mal que bien a nuestro código porque resultaría más confuso, intrincado e innecesariamente complejo, lo que hay que buscar es el equilibrio entre practicidad/calidad en nuestro código. Hazlo con buenas prácticas, hazlo simple, hazlo efectivo.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.codmind.com/content/images/2021/07/olivier-chatel-fAVlrFGQ83I-unsplash.jpg" class="kg-image" alt="Entendiendo los principios SOLID"><figcaption>Photo by <a href="https://unsplash.com/@beolive?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Olivier Chatel</a> on <a href="https://unsplash.com/s/photos/columns?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Single Responsibility Principle (SRP)</strong></p><p>Este principio postula que <em>una clase debe tener sólo una razón para existir,</em> con esto evitamos la mala práctica conocida como la "clase dios" o "super clase" en la cual queremos que una clase haga más de una cosa, y pensamos que esto es bueno, que la clase haga de todo y tratamos de hacerla todo poderosa y que con parámetros en sus métodos hagan diversas funcionalidades, y hasta puede que nos sintamos orgullosos de ello  sin embargo estamos cayendo en un vicio.</p><p>Un ejemplo de cómo aplicar este principio es <em>evitar hacer consultas SQL desde una vista</em>, ya que estaríamos añadiendo una responsabilidad de acceso a datos a una clase cuya responsabilidad primaria es la de mostrar controles e interfaces al usuario.</p><p><strong>Open Close Principle (OCP)</strong></p><p>Este principio dice que <em>nuestro código debe ser abierto a la extensión y cerrado a la modificación</em>, esto lo logramos aplicando el polimorfismo y la abstracción. En buen cristiano esto significa que si a un bloque de nuestro código por ejemplo un método le queremos añadir una nueva funcionalidad esta debe añadirse mediante agregarla en nuestro código no mediante cambiar todo el código existente a la ligera, esto nos obliga a manejar nuestras funcionalidades con código modular por llamarlo de alguna manera y no estar sobre-escribiéndolo o parchándolo si queremos añadir una funcionalidad o <em>feature </em>nuevo.</p><p><strong>Liskov Substitution Principle (LSP)</strong></p><p>Este principio se define así: "Si S es un subtipo de T, las apariciones de tipo T en un programa pueden ser reemplazadas por otra de tipo S sin que el funcionamiento del programa se vea alterado". Esto quiere decir que <em>sólo debemos derivar o heredar de una clase para añadir funcionalidades, nunca para modificar lo existente</em>, o en otras palabras una clase que hereda de otra puede usarse como su padre sin necesidad de conocer las diferencias entre ellas.</p><p><strong>Interface Segregation Principle (ISP)</strong></p><p>En el caso de este principio, <em>no debemos dar más información de la necesaria a los módulos para funcionar</em>. Esto se logra mediante separar las interfaces. Un ejemplo clásico de este principio es el de la transacción de un cajero automático postulado en el libro "Desarrollo de Software Ágil: Principios, patrones y prácticas" de Robert Martin, este ejemplo trata sobre la interfaz de usuario para un cajero automático, que maneja todas las peticiones (como consulta de saldos o retiros), y cómo esta interfaz necesita ser <em>segregada </em>en interfaces más específicas y más concretas.</p><p><strong>Dependency Inversion Principle (DIP)</strong></p><p>Este principio nos dice que <em>debemos reducir la dependencia entre los módulos de nuestra aplicación, los módulos no deben ser los encargados de crear los objetos con los que trabajan sino que deben ser creados por alguien más</em> y pasárselos a un constructor para que los use cuando quiera. </p><p>Este principio está muy relacionado con la buena práctica de Inyección de dependencias que puedes aprender más en <a href="https://bravedeveloper.com/2021/04/21/inyeccion-de-dependencias-que-es-y-para-que-sirve/">esta entrada</a>. Que tu código y su estructura sea tan SÓLIDOS como una montaña!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.codmind.com/content/images/2021/07/maxim-medvedev-a4b_-6EKLvI-unsplash.jpg" class="kg-image" alt="Entendiendo los principios SOLID"><figcaption>Photo by <a href="https://unsplash.com/@medvedevmax?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Maxim Medvedev</a> on <a href="https://unsplash.com/s/photos/mountain-good?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Pues bien, de momento lo que te toca a ti es investigar y repasar los conceptos aquí repasados estimado lector, pero sobre todo ponerlos en práctica, y ya sabes comparte si te aportó valor esta entrada crack! 💪😊</p>]]></content:encoded></item><item><title><![CDATA[Cuando la Agilidad no es tan buena idea]]></title><description><![CDATA[La Agilidad es un mindset muy útil para la gestión. Algunas situaciones deben estar presentes para su aplicación efectiva, de lo contrario, usarla podría no ser tan buena idea. A continuación se presentan recomendaciones para establecer adecuadamente el mindset ágil.]]></description><link>https://blog.codmind.com/cuando-la-agilidad-no-es-tan-buena-idea/</link><guid isPermaLink="false">6063f5bfe6357f340b7e0a3e</guid><category><![CDATA[agil]]></category><dc:creator><![CDATA[Cesar Vallejo]]></dc:creator><pubDate>Thu, 01 Apr 2021 05:41:56 GMT</pubDate><media:content url="https://blog.codmind.com/content/images/2021/03/collage-codmind-agilidad-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.codmind.com/content/images/2021/03/collage-codmind-agilidad-1.png" alt="Cuando la Agilidad no es tan buena idea"><p>El pensamiento ágil, más allá de ser algo que esté escrito como metodología, es una forma de vida que invita a estar atento a la incertidumbre en la gestión, abrirse a los cambios repentinos y reaccionar con  entregas frecuentes de productos que les resulten útiles a quienes los pagan y utilizan.</p><p>A primera vista, resulta seductor trabajar con este esquema. Sin embargo, la agilidad es una herramienta de gestión más, que surte nuestro repertorio profesional, y que no resuelve todos los problemas. Esta idea se extiende a todos los ámbitos de su aplicación: en proyectos, en cadena de abastecimiento, en estrategia, en auditoría, en recursos humanos, en desarrollo de software, en operaciones, en desarrollo organizacional, entre otras aplicaciones.</p><p>Bajo esta premisa, y tomando como piedra angular los principios del <a href="https://agilemanifesto.org/iso/es/principles.html">Manifiesto Ágil</a>, se presentan seis escenarios concretos en los que no es tan buena idea aplicar la agilidad, porque su uso como medicina podría resultar peor que la enfermedad.</p><p>Sin más preámbulos, no es tan buena idea aplicar la agilidad cuando:</p><p><strong>1.       No se conoce las motivaciones de los usuarios</strong></p><p>Conocer el segmento de usuarios es uno de los primeros pasos en cualquier tipo de gestión, incluyendo la agilidad. Se recomienda tener muy claro a quién involucrar y entender qué intereses tiene cada uno de estos individuos; esto se basa en los principios ágiles de: satisfacer al cliente, trabajar con individuos motivados y comunicar cara a cara la gestión. Para cumplir esto, se recomienda levantar información primaria y secundaria sobre sus rasgos de comportamiento, sus estructuras organizacionales formales, círculos informales de poder, las anécdotas que influyen en su comportamiento, los ritos y símbolos que los diferencia, entre otros.</p><p>Después, se esperaría entender los niveles de apoyo y auspicio que se requiere de los individuos de los segmentos en cuestión. Con este entendimiento, entonces se podría diseñar alguna estrategia de involucramiento en el momento que la gestión lo requiera. De no realizar lo descrito, se corre el riesgo de omitir algún resultado esperado, y, en consecuencia, no entregar un trabajo que agregue valor.</p><p><strong>2.       No se entiende el problema objetivamente</strong></p><p>En segundo lugar, se recomienda entender el problema desde la perspectiva de nuestro segmento, y más importante aún, desde los intereses formales de la organización. Esto significa conocer la causa raíz de aquello que se percibe como problema, de tal forma que nuestra solución resuelva tanto lo visible como lo invisible para el cliente y los usuarios. De omitir esta consideración, se desperdiciarán los recursos finitos, y posiblemente, se empeorará el problema en el corto y largo plazo.</p><p>Una de las formas objetivas de entender el problema, es rastrear la causa raíz hacia los elementos organizacionales que se deben crear, mejorar o eliminar. Esto a su vez, se lo puede analizar usando buenas prácticas de arquitectura empresarial que identifica los procesos, tecnologías o las estructuras organizacionales que se relacionan con el problema. Finalmente, se recomienda que esta evaluación arquitectónica considere el contexto de los objetivos estratégicos de la organización que se afectarán de manera positiva o negativa con nuestro accionar.</p><p><strong>3.       No se tiene mano de obra técnicamente calificada</strong></p><p>De manera textual, la agilidad demanda “la atención continua a la excelencia técnica y al buen diseño…”. Esto tiene dos implicaciones profundas. La primera es que, sin competencias técnicas de excelencia, no es posible entregar frecuentemente productos bien hechos. No confundir con la multidisciplinariedad, ya que el equipo puede ser multidisciplinario, pero con pobres competencias técnicas.</p><p>La segunda implicación, es que la agilidad no exime al gestor la tarea de realizar un buen diseño de ingeniería. Frecuentemente, se observan actividades de agilidad que se limitan a realizar ejercicios de creatividad, y bajo las implicaciones presentadas, esta tiene que ir acompañada (y validada) del pensamiento duro ingenieril.</p><p><strong>4.       No es algo novedoso o complejo</strong></p><p>Como se dijo al inicio de este artículo, la agilidad nace en respuesta a la incertidumbre de los requerimientos de la gestión. Es decir, ante lo desconocido se espera responder con flexibilidad para satisfacer requerimientos que se darán (o cambiarán) sobre la marcha en un contexto de costos y plazos previamente determinados.</p><p>Sin embargo, si la naturaleza de la gestión o trabajo a realizar es: repetitiva, recurrente, de baja complejidad, bien conocida, de poca envergadura, de bajo presupuesto, de mínima importancia estratégica o estable desde el punto de vista tecnológico y operativo, entonces no se necesita ser ágil. De no hacerlo así, se desperdiciarán tiempo y recursos en actividades frecuentes de identificación y definición para cosas que ya se conocen y que no ameritan ese esfuerzo. Esto no implica que no se realicen entregas frecuentes, pero esta situación cae en otro tipo de gestión que no es ágil al 100%. Por lo tanto, si no hay novedad en la gestión entonces se recomienda considerar el uso de enfoques tradicionales o híbridos de trabajo, que son eficientes frente al uso de recursos y situaciones de baja complejidad.</p><p><strong>5.       No se mide el rendimiento financiero</strong></p><p>Otro principio de la agilidad es la medición de productos efectivos. Adicionalmente, y en función de demostrar valor fehacientemente, se recomienda extender la medición al ámbito financiero. Es decir, con nuestra propuesta de solución debemos estar en la capacidad demostrar el "antes y el después financiero" de la organización o segmento social. Esto se recomienda hacer incluso, si se trata de una iniciativa sin fines de lucro o un proyecto social.</p><p>En caso de omitir esta recomendación, se podría caer en el terreno del juicio de valor, la opinión y la ambigüedad. Recordemos que en los negocios (y en las iniciativas sociales) la perspectiva financiera es la dominante, porque tenemos el deber profesional de demostrar el nivel de ahorro, incremento de ingresos o, monetizar el valor social entregado (necesario para tocar las puertas de organismos de financiamiento). Como profesionales en gestión, incluyendo a la tecnología y la agilidad, tenemos la obligación -de al menos- estimar los costos y los beneficios financieros de la solución propuesta.</p><p><strong>6.       La madurez empresarial es emergente</strong></p><p>La madurez empresarial se podría entender como el nivel de rigurosidad y formalidad para operar. No confundir con burocratizar o empapelar la gestión. Rigurosidad quiere decir que está claro lo que hay que hacer organizacionalmente (no me refiero al alcance de un proyecto), que las responsabilidades y roles están formalmente definidos, que los niveles de calidad están establecidos, que el resultado a conseguir se mide y se demuestra, y que las cosas se adaptan con un criterio de negocio.</p><p>Entonces, el error más común es encajar una forma rigurosa de trabajar en una cultura organizacional emergente informal. Esto conlleva a desperdicio de recursos, frustración y deterioro de la motivación. Como profesionales de la gestión -incluyendo de la agilidad- adaptamos lo que dicen los libros -y principios- en base a nuestro criterio profesional, y en base a los demás puntos narrados en este artículo. Evidencia de omisión de este punto es seguir cualquier metodología como libro de cocina, sin cuestionar elementos organizacionales internos y externos para adaptar los principios de gestión.</p><p><strong>Comentarios finales</strong></p><p>La agilidad es una herramienta muy útil de gestión, que finalmente es solo eso, una herramienta más. Nos permite reaccionar ante la incertidumbre, y que como toda herramienta, no es de uso para todos los casos ni para todas las ocasiones. Su aplicación efectiva requiere la presencia de una serie de factores críticos que la soportan y potencian: conocimiento formal a la organización, excelencia técnica en la materia, capacidad de medición operativa y financiera, entre otras.</p><p>Argumentando desde el <a href="https://agilemanifesto.org/iso/es/principles.html">Manifiesto Ágil</a>, se evidencia que la agilidad va mucho más allá de los ejercicios de lluvia de ideas, armado de prototipos o dinámicas de motivación. He de ahí, la invitación a revisar este manifiesto como una lista de chequeo que permita identificar las capacidades que se deben desarrollar previo a la aplicación efectiva de la agilidad, de lo contrario, podría no ser tan buena idea su uso en nuestras organizaciones. (O)</p><p>CV</p>]]></content:encoded></item><item><title><![CDATA[Mi primer API Rest con Spring Boot]]></title><description><![CDATA[En este artículo crearemos una API REST con Spring Boot, una tecnología de Spring, cabe mencionar que Spring framework es la tecnología más utilizada para la plataforma Java.]]></description><link>https://blog.codmind.com/mi-primer-api-rest-con-spring-boot/</link><guid isPermaLink="false">60274615e6357f340b7e05c1</guid><category><![CDATA[spring-boot]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Marcos Vazquez Gonzalez]]></dc:creator><pubDate>Wed, 17 Mar 2021 18:19:44 GMT</pubDate><media:content url="https://blog.codmind.com/content/images/2021/03/banner-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.codmind.com/content/images/2021/03/banner-2.png" alt="Mi primer API Rest con Spring Boot"><p>En este artículo crearemos una API REST con Spring Boot, una tecnología de Spring, cabe mencionar que Spring framework es la tecnología más utilizada para la plataforma Java.</p><p>Con Spring Boot nos facilitamos las configuraciones como las dependencias de conexión con la base de datos, despliegue del servidor, entre otras.</p><p>Utilizaremos MySQL como nuestro gestor de base de datos y maven como el gestor de la aplicación.</p><p></p><h2 id="crear-el-proyecto-con-spring-boot">Crear el proyecto con Spring Boot</h2><p>Como lo hemos dicho anteriormente utilizaremos la tecnología Spring Boot, esta nos facilitara las configuraciones y solo tendremos que enfocarnos en el código de nuestra aplicación.</p><p>Para iniciar con nuestro proyecto lo realizaremos con spring initializr.</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-6.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p></p><p><strong>Descripción de los campos:</strong></p><p>Project: Seleccionamos el gestor de nuestra aplicación maven o gradle, utilizaremos maven</p><p>Languaje: Elegimos con qué lenguaje queremos trabajar, utilizaremos Java</p><p>Spring Boot: Seleccionamos la versión con la que queremos trabajar, se deja la que está por default</p><p>Project Metadata: Aquí ingresamos el nombre de nuestro proyecto</p><p>Packaging: Seleccionamos el empaquetado de nuestra aplicaciones</p><p>Java: Seleccionamos la versión de Java</p><p>Dependecies: Aquí buscaremos las dependencias que necesitemos, buscamos y agregamos las que se muestran a continuación.</p><p></p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-7.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p></p><p>Damos clic en Generate para descargar el proyecto, una vez descargado lo descomprimimos.</p><p>Para el desarrollo de la aplicación utilizamos Spring Tool Suite (STS), en este IDE importamos el proyecto como Existing Maven Projects</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-8.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p></p><p>Nos aparecerá un archivo pom.xml, marcamos el check y damos clic en next.</p><p>Nuestro proyecto (STS) empezará a descargar las dependencias que seleccionamos anteriormente, estas se encuentran en el archivo pom.xml</p><p></p><h2 id="la-base-de-datos">La Base de datos</h2><p>Esta será la estructura de nuestra base de datos.</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-9.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p></p><p>En el archivo application.properties con la siguiente ruta de acceso: src/main/resources/ agregamos el string de conexión para ingresar a la base de datos que creamos anteriormente.</p><p></p><pre><code class="language-java">spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=

spring.jpa.show-sql=true</code></pre><p></p><h2 id="desarrollo-de-la-api">Desarrollo de la API</h2><p>La siguiente estructura de paquetes es la que creamos para la aplicación.</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-10.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p></p><p>La clase DemoApplication.java</p><p>Es la clase que arranca cuando iniciamos la aplicación.</p><pre><code class="language-java">package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
		
	}
	
}</code></pre><p></p><p>La clase Person.java</p><p>La entidad de nuestro objeto Person, esta clase va a mapear los atributos como campos en la base de datos.</p><pre><code class="language-java">package com.example.demo.model;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

@Entity
@Table(name = "users")
@EntityListeners(AuditingEntityListener.class)
public class Person {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	private String name;
	
	@Column(name = "user_name")
	private String userName;
	
	@Column(name = "date_registry")
	@CreatedDate
	private Date date;
	
	public Person() {

	}

	public Person(Long id, String name, String userName, Date date) {
		this.id = id;
		this.name = name;
		this.userName = userName;
		this.date = date;
	}
	
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", userName=" + userName + ", date=" + date + "]";
	}

}</code></pre><p></p><p>La clase PersonRepository.java</p><p>Esta clase nos ayuda a realizar operaciones en nuestra base de datos sin escribir tantas líneas de código, Spring Data realiza esto por nosotros, operaciones como delete, save, findAll, son algunos de los métodos que realiza automáticamente.</p><pre><code class="language-java">package com.example.demo.repository;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.example.demo.model.Person;

@Repository
public interface PersonRepository extends JpaRepository&lt;Person, Long&gt;{
	
	List&lt;Person&gt; findByName(@Param("name") String name);
	
}</code></pre><p></p><p>La clase PersonController.java</p><p>Esta clase le indica a spring que la clase va a ser un controlador de una API Rest, nos proveerá de todos los métodos para un CRUD.</p><pre><code class="language-java">package com.example.demo.Controlller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.model.Person;
import com.example.demo.repository.PersonRepository;

@RestController
@RequestMapping("/api")
public class PersonController {
	
	@Autowired
	private PersonRepository repository;
	
	
	@GetMapping("/persons")
	public List&lt;Person&gt; allPersons(){
		return repository.findAll();
	}
	
	@GetMapping("/person/{name}")
	public List&lt;Person&gt; findByName(@PathVariable("name") String name) {
		return repository.findByName(name);
	}
	
	@PostMapping("/person")
	public Person createPerson(@RequestBody Person person) {
		return repository.save(person);
	}
	
	@PutMapping("/person/{id}")
	public Person updatePerson(@PathVariable int id ,@RequestBody Person person) {
		return repository.save(person);
	}
	
	@DeleteMapping("/person/{id}")
	public void deletePerson(@PathVariable("id") Long id) {
		repository.deleteById(id);
	}
}


</code></pre><p></p><p>Para realizar las pruebas correspondientes vamos a utilizar postman una aplicación para probar api's.</p><p></p><p>Realizamos una prueba para almacenar un nuevo registro, para esto utilizamos un método POST.</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-15.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p>Con el método POST nosotros podemos almacenar nuevos registros en nuestra base de datos.</p><p></p><p>Probamos la petición Get</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-11.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p>Esta petición get nos traerá todos los registros</p><p></p><p>Prueba de la petición Get con parámetro</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-12.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p>Con la petición Get con parámetro name, podemos buscar un objeto Person por medio del name.</p><p></p><p>Prueba para actualizar un registro</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-13.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p>Este es el registro que queremos actualizar.</p><p></p><p>A continuación con el método PUT, actualizamos el registro</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/02/image-14.png" class="kg-image" alt="Mi primer API Rest con Spring Boot"></figure><p></p><p>Este es una API Rest muy sencilla, pero cuando recien estan empezando, sirve de mucho para entender como Spring maneja las anotaciones quienes nos ahorran líneas de código. </p><p>Recuerda que puedes aprender a crear API REST de forma profesional con nuestro curso <a href="https://codmind.com/courses/api-rest-con-spring-boot">Mastering API REST con Spring boot</a>, donde te enseñaremos desde cero a crear un API REST completa, con las mejores prácticas.</p>]]></content:encoded></item><item><title><![CDATA[¿Qué es Spring y Spring Boot?]]></title><description><![CDATA[Revisando Get on board (pagina de empleo chilena) se puede apreciar varias ofertas laborales que piden java y ¿Spring? (ninguna oferta que pida Java developer no incluye Spring Boot como requerimiento)]]></description><link>https://blog.codmind.com/que-es-spring/</link><guid isPermaLink="false">6012bb43e6357f340b7df5fe</guid><category><![CDATA[spring-boot]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[Daniel Quiaro (Quiarom)]]></dc:creator><pubDate>Wed, 17 Mar 2021 18:12:57 GMT</pubDate><media:content url="https://blog.codmind.com/content/images/2021/03/banner-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.codmind.com/content/images/2021/03/banner-1.png" alt="¿Qué es Spring y Spring Boot?"><p>Revisando Get on board (pagina de empleo chilena) se puede apreciar varias ofertas laborales que piden java y ¿Spring? (ninguna oferta que pida Java developer no incluye Spring Boot como requerimiento)</p><figure class="kg-card kg-image-card"><img src="https://blog.codmind.com/content/images/2021/01/imagen_2021-01-28_130752.png" class="kg-image" alt="¿Qué es Spring y Spring Boot?"></figure><p><strong>Spring es un framework para backend que se puede usar con Java, Kotlin y Groovy</strong>, Spring framework existe para facilitar la creación de aplicaciones, simplificando la estructura del proyecto y mejorando la velocidad de una aplicación empresarial.</p><!--kg-card-begin: markdown--><h2 id="quesunaaplicacinempresarial">¿Qué es una aplicación empresarial?</h2>
<!--kg-card-end: markdown--><p><strong>Una gran aplicación con fines comerciales</strong>, que será usada por muchas personas.</p><p>Es compleja de hacer, debe ser escalable (Dar la posibilidad de ser modificada sin generarle pesadillas a lxs encargadxs de mantenerla), brindarle comodidad y seguridad al usuario.</p><!--kg-card-begin: markdown--><h2 id="springspringboot">¿Spring = Spring Boot?</h2>
<!--kg-card-end: markdown--><p>Negativo, no son lo mismo, Spring Boot funciona con Spring core (Spring framework).</p><p>Spring Boot es una variación de Spring que viene con la configuración, que anteriormente, se tenía que hacer a mano, facilitando mucho el desarrollo con Spring, permitiendo al programador no tener que configurar nada, solo va a tener que echar código y pedir ayuda en Stackoverflow.</p><!--kg-card-begin: markdown--><h2 id="dndeaprenderspringboot">¿Dónde aprender Spring Boot?</h2>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>En Codmind tenemos un curso de <a href="https://codmind.com/courses/api-rest-con-spring-boot">Mastering de API REST con Spring Boot</a>, aprenderas conceptos claves como ¿Qué es una API REST?, después, daras tus primeros pasos con Spring Boot creando varias APIs REST y así fortaleces los conocimientos que conseguiste en este curso.</p>
<p>Este video es una clase del Mastering, es gratis, te invito a darle una oportunidad y calmar tu curiosidad.</p>
<p>Muchas gracias por leer y hasta la próxima.</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/I85YAKCSsB4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure>]]></content:encoded></item><item><title><![CDATA[Renombrar ramas en Git]]></title><description><![CDATA[**Github cambio el nombre de la rama principal**. Antes se llamaba master, ahora se llama main, una palabra más corta y que no se puede usar de manera ofensiva.]]></description><link>https://blog.codmind.com/renombrar-ramas-en-git/</link><guid isPermaLink="false">600afbe7e6357f340b7decb8</guid><category><![CDATA[git]]></category><dc:creator><![CDATA[Daniel Quiaro (Quiarom)]]></dc:creator><pubDate>Wed, 17 Mar 2021 18:11:16 GMT</pubDate><media:content url="https://blog.codmind.com/content/images/2021/03/banner-4.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://blog.codmind.com/content/images/2021/03/banner-4.jpg" alt="Renombrar ramas en Git"><p><strong>Github cambio el nombre de la rama principal</strong>. Antes se llamaba master, ahora se llama main, una palabra más corta y que no se puede usar de manera ofensiva.</p>
<p><img src="https://blog.codmind.com/content/images/2021/02/imagen_2021-02-01_180620.png" alt="Renombrar ramas en Git"></p>
<p>En Git sigue llamandose master la rama principal. En el flujo de desarrollo esto puede generar conflicto por tener en 2 herramientas distintas, la misma rama principal con diferentes nombres.</p>
<h2 id="todotienesolucin">Todo tiene solución</h2>
<p><strong>Se arregla con cambiar el nombre de la rama</strong>, estando en un directorio donde este un archivo .git y posicionandonos en la rama master, corremos el siguiente comando:</p>
<p><code>git branch -m main</code></p>
<p>Listo, con este cambiamos el nombre de la rama master a main, ahora esta igual que en Github. Comodamente podemos hacer push al repositorio en Github y no habra que hacer un pull request (esto ahorra tiempo, el tiempo es dinero).</p>
<h2 id="estoesparasiempre">¿Esto es para siempre?</h2>
<p>Me hice esta pregunta al enterarme de la noticia, un cambio en la integración de Git con Github, herramientas basicas para cualquier tipo de programador.</p>
<p><strong>Respuesta corta</strong>: Negativo, Es probable que Github hable con Git para arreglar diferencias.</p>
<p><strong>Respuesta larga</strong>: Github a ido aplicando estos cambios por fases, es decir, poco a poco para que que no sea un cambio brusco, además, escribir un comando significa invertir segundos en eso, segundos que se pueden usar en otra cosa, por ejemplo, ver algunos de los cursos que ofrecemos en <a href="https://blog.codmind.com/renombrar-ramas-en-git/codmind.com">codmind</a>. Al final, main es mucho mas corto que master y creo imposible asociar &quot;main&quot; con algo ofensivo.</p>
<p>Me despido e invito a ver esta situación como una prueba, una prueba fiable de la alta probabilidad de cambios en el mundo IT.</p>
<h2 id="linkdereferencia">Link de referencia</h2>
<p><a href="https://github.com/github/renaming">Anuncio del cambio</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>