<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Agustin Tosco</title>
    <description>The latest articles on DEV Community by Agustin Tosco (@agustintosco).</description>
    <link>https://dev.to/agustintosco</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F767346%2F621e2ecd-19db-482c-bf57-c10c01544f2b.png</url>
      <title>DEV Community: Agustin Tosco</title>
      <link>https://dev.to/agustintosco</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/agustintosco"/>
    <language>en</language>
    <item>
      <title>ORMs - Active Record &amp; Data Mapper</title>
      <dc:creator>Agustin Tosco</dc:creator>
      <pubDate>Fri, 24 Dec 2021 00:53:57 +0000</pubDate>
      <link>https://dev.to/agustintosco/orms-active-record-data-mapper-4mpm</link>
      <guid>https://dev.to/agustintosco/orms-active-record-data-mapper-4mpm</guid>
      <description>&lt;h2&gt;
  
  
  ¿Cuál es la diferencia entre Active Record y Data Mapper?
&lt;/h2&gt;

&lt;p&gt;Cuando trabajamos con datos en una aplicación, probablemente necesitemos un ORM (Object Relational Mapping). Un ORM es la capa entre la base de datos y nuestra aplicación. Al usar un ORM, la mayoría del trabajo de crear, actualizar, leer y eliminar de la base de datos es hecho por este ORM.&lt;/p&gt;

&lt;p&gt;La mayoría de los frameworks actuales están preparados para trabajar con un ORM sin problemas. Por ejemplo, Laravel trabaja normalmente con &lt;a href="https://laravel.com/docs/8.x/eloquent"&gt;Eloquent&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Las dos más famosas implementaciones de ORMs son Active Record y Data Mapper. En este artículo vamos a explorar la diferencia entre estos dos patrones, cuales son los beneficios y desventajas de elegir uno u otro.&lt;/p&gt;




&lt;h2&gt;
  
  
  ¿Qué es un ORM y por qué necesitamos uno?
&lt;/h2&gt;

&lt;p&gt;Antes de comenzar a hablar acerca de las diferencias entre Active Record y Data Mapper, vamos a hablar un poco sobre qué es un ORM y cuál es su utilidad.&lt;/p&gt;

&lt;p&gt;Como dijimos anteriormente, un ORM es la capa que existe entre la base de datos y nuestra aplicación. En POO, trabajamos con objetos como nuestro principal punto de referencia.&lt;/p&gt;

&lt;p&gt;Por ejemplo, podríamos tener el siguiente objeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elodin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sin embargo, las bases de datos pueden almacenar valores como strings o integers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iJyjCC25--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fy7bs6qbvb78wu2wc2z8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iJyjCC25--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fy7bs6qbvb78wu2wc2z8.png" alt="Image description" width="657" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un &lt;code&gt;User&lt;/code&gt; podría tener varios posteos en nuestra aplicación. Para conseguirlos, podríamos hacer algo así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sin embargo, en la base de datos, los posteos estarían almacenados en un tabla, así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WaAikKcU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmnanaw6kvzfa2245sk0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WaAikKcU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmnanaw6kvzfa2245sk0.png" alt="Image description" width="674" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando trabajamos con objetos en nuestra aplicación, trabajamos con objetos simples que almacenan todas sus propiedades y relaciones.&lt;/p&gt;

&lt;p&gt;No obstante, estos datos son almacenados individualmente en las diferentes tablas de la base de datos.&lt;/p&gt;

&lt;p&gt;Un ORM es esa capa "mágica" que transforma los datos en forma de objetos en datos relacionales que pueden ser guardados en la base de datos y viceversa.&lt;/p&gt;




&lt;h2&gt;
  
  
  ¿Qué es el patrón Active Record?
&lt;/h2&gt;

&lt;p&gt;Este patrón de ORMs es probablemente el más popular.&lt;/p&gt;

&lt;p&gt;Un ejemplo de uso típico sería el siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elodin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el ejemplo de arriba creamos un nuevo objeto &lt;code&gt;User&lt;/code&gt;, configurando el &lt;code&gt;username&lt;/code&gt; y luego guardando el objeto en la base de datos.&lt;/p&gt;

&lt;p&gt;ORMs del estilo Active Record mapean un objeto con una fila de la base de datos. En el ejemplo anterior, estaríamos mapeando el objeto &lt;code&gt;User&lt;/code&gt; a una fila en la tabla &lt;code&gt;users&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cuando abramos el archivo de modelo &lt;code&gt;User&lt;/code&gt;, notaremos que no necesitamos especificar las propiedades del objeto o como se relaciona con la base de datos. Con este tipo de ORMs, el modelo es capaz de determinar las propiedades del modelo automáticamente tomando como referencia el esquema de la base de datos.&lt;/p&gt;

&lt;p&gt;Uno de los beneficios de este estilo de ORMs es que podemos llamar al método &lt;code&gt;save()&lt;/code&gt; en el objeto para actualizar la base de datos. Cada modelo hereda de un objeto base (del patrón Active Record) por lo que tenemos acceso a todos los métodos relacionados a la presistencia de datos. Esto hace que comenzar a trabajar con ORMs de estilo Active Record sea muy fácil ya que son muy intuitivos.  &lt;/p&gt;




&lt;h2&gt;
  
  
  ¿Qué es el patrón Data Mapper?
&lt;/h2&gt;

&lt;p&gt;La gran diferencia entre ambos patrones es que el Data Mapper separa completamente el dominio de nuestra aplicación y la capa de persistencia. Esto significa que ninguno de nuestros modelos (objetos) sabe nada acerca de la base de datos.&lt;/p&gt;

&lt;p&gt;Cuando usamos el patrón Data Mapper nuestro código luciría algo así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elodin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hasta ahora, no hay diferencias con el patrón Active Record.&lt;/p&gt;

&lt;p&gt;No obstante, los objetos del modelo Data Mapper no son más que objetos que no tienen conocimiento alguno sobre la base de datos. Esto significa que no podemos llamar al método &lt;code&gt;save()&lt;/code&gt; en el objeto a almacenar porque este método no existe en este objeto.&lt;/p&gt;

&lt;p&gt;En cambio, necesitaremos usar un servicio completamente diferente, por ejemplo, llamado Entity Manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elodin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;EntityManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El gran beneficio del patrón Data Mapper es que los objetos que utilizamos en el dominio de nuestra aplicación no necesitan conocer nada acerca de cómo están guardados en la base de datos. Esto significa que nuestros objetos serán más livianos ya que no deberán heredar el ORM completo, sino que también habrá un proceso más estricto y formal para interactuar con la base de datos debido a que no podremos llamar al método &lt;code&gt;save()&lt;/code&gt; en cualquier lugar en nuestro código.&lt;/p&gt;




&lt;h2&gt;
  
  
  Entonces, ¿cuáles son las diferencias entre Active Record y Data Mapper?
&lt;/h2&gt;

&lt;p&gt;Ambos patrones tienen aspectos positivos y negativos, por supuesto. Como ocurre con casi todo lo demás en el ámbito de la programación, no hay uno que sea mejor que otro, sino que... depende.&lt;/p&gt;

&lt;p&gt;Con todo esto en mente, puede haber dos formas de juzgar cuál patrón nos conviene más usar en nuestro caso.&lt;/p&gt;




&lt;h3&gt;
  
  
  El tipo de aplicación que estemos construyendo
&lt;/h3&gt;

&lt;p&gt;Generalmente y a grandes rasgos, existen dos tipos de aplicaciones: aquellas basadas en los métodos CRUD y las basadas en el propio dominio de la aplicación.&lt;/p&gt;

&lt;p&gt;En una aplicación basada en los métodos CRUD típicamente estaremos creando, leyendo, actualizando y eliminando entidades. También, puede que tengamos relaciones entre nuestros modelos, pero sobre todo, no hay reglas estrictas respecto a cómo estas relaciones están dadas.&lt;/p&gt;

&lt;p&gt;Cuando construimos una aplicación que está basada o pensada desde el lado de la base de datos, la solucíon más óptima es el patrón Active Record. Éste último, nos permitirá rápida y fácilmente levantar y correr nuestra aplicación.&lt;/p&gt;

&lt;p&gt;Si por el contrario, nuestra aplicación es construida pensando en satisfacer las reglas y procedimientos de un negocio, el patrón Data Mapper puede que sea la mejor opción. Éste patrón hará cumplir ciertas restricciones de tratar con datos y su persistencia, y también nos permitirá encapsular esas reglas de negocio dentro de las entidades.&lt;/p&gt;




&lt;h3&gt;
  
  
  La aplicación y el entorno en el que está siendo construida
&lt;/h3&gt;

&lt;p&gt;Si estamos construyendo un MVP (Producto Mínimo Viable) para testear un nuevo mercado, puede que tenga más sentido usar el patrón Active Record. Al principio, generalmente no sabemos del todo cuales reglas del negocio serán más importantes, y nunca lo sabremos si nos obsesionamos con la arquitectura de nuestra aplicación.&lt;/p&gt;

&lt;p&gt;Por otro lado, si la idea es trabajar en una aplicación para un negocio ya existente, puede que sea mejor idea usar un patrón Data Mapper. Un negocio existente ya tendrá reglas y procedimientos por medio de los cuales funciona. Si usáramos un patrón Active Record terminaríamos intentando forzar estas reglas del negocio para que se adapten a nuestra idea de una aplicación pensada desde el lado de la base de datos. El patrón Data Mapper nos permitirá encapsular las reglas de dominio del negocio permitiéndonos trabajar de manera intuitiva y clara.&lt;/p&gt;




&lt;h2&gt;
  
  
  Nota
&lt;/h2&gt;

&lt;p&gt;Este artículo ha sido maś que nada teoría sin muchos ejemplos prácticos. Para ver un tutorial práctico sobre las diferencias entre estos dos patrones, el siguiente enlace será de utilidad =&amp;gt; &lt;a href="https://fideloper.com/how-we-code"&gt;How We Code: ORMs and Anemic Domain Models&lt;/a&gt; by &lt;a href="https://twitter.com/fideloper"&gt;Chris Fidao&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Fuente: &lt;a href="https://www.culttt.com/2014/06/18/whats-difference-active-record-data-mapper"&gt;https://www.culttt.com/2014/06/18/whats-difference-active-record-data-mapper&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>¿Qué es Kubernetes?</title>
      <dc:creator>Agustin Tosco</dc:creator>
      <pubDate>Sun, 19 Dec 2021 19:08:44 +0000</pubDate>
      <link>https://dev.to/agustintosco/que-es-kubernetes-ool</link>
      <guid>https://dev.to/agustintosco/que-es-kubernetes-ool</guid>
      <description>&lt;p&gt;Kubernetes es una plataforma open-source, extensible y portable para el manejo de programas, aplicaciones y servicios contenerizados que hace más fácil tanto la configuración declarativa como la automatización.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Retrocediendo al pasado&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Era del despliegue tradicional: hace tiempo, la mayoría de las organizaciones corrían sus aplicaciones en servidores físicos. No había manera de definir los límites de recursos para aplicaciones en un caso como éste, esto causaba diversos problemas. Por ejemplo, si muchas aplicaciones corrían en un mismo servidor físico, podría haber habido una instancia en donde una aplicación acaparara la mayoría de los recursos, y como resultado, las otras aplicaciones tendrían un rendimiento inferior.&lt;br&gt;
Una solución a este problema hubiese sido correr cada aplicación en un servidor físico diferente. Pero esta solución no prosperó ya que la utilización de recursos sería muy ineficiente y muy costoso para las organizaciones de mantener múltiples servidores.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Era del despliegue virtual&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Como solución, se introdujo la virtualización. Esto permite correr múltiples Máquinas Virtuales (MV) en la CPU de un solo servidor físico. También nos permite aislar aplicaciones entre MVs y provee cierta seguridad ya que la información de una aplicación no puede ser accedida libremente desde otra aplicación.&lt;/p&gt;

&lt;p&gt;La virtualización permite una mejor utilización de los recursos y permite la escalabilidad. &lt;/p&gt;

&lt;p&gt;Cada MV es una máquina corriendo todos los componentes, incluyendo su propio sistema operativo, sobre el hardware virtualizado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Era del despliegue en contenedores&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Los contenedores son similares a las MVs, tienen su propio sistema de archivos, misma memoria, espacio de procesamiento, entre otros. Debido a que están desacoplados de la estructura subyacente, son totalmente portables.&lt;/p&gt;

&lt;p&gt;Los contenedores se volvieron muy populares debido a ciertas ventajas extras, como las siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ágil creación y despliegue de aplicaciones&lt;/strong&gt;: mayor facilidad y eficiencia de la creación de imágenes de contenedores en comparación con el uso de imágenes de MV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Desarrollo, integración y despliegue continuo&lt;/strong&gt;: permiten una frecuente y confiable construcción de imágenes y despliegue con la posibilidad de realizar rápidos y eficientes rollbacks (restauración a una versión anterior), debido a la inmutabilidad de las imágenes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separación de tareas entre Dev y Ops&lt;/strong&gt;: podemos crear imágenes al momento de compilar y no al desplegar, desacoplando la aplicación de la infraestructura.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observabilidad&lt;/strong&gt;: no solo muestra información y métricas a nivel del sistema operativo, sino la salud de la aplicación y otra información.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistencia entre los entornos de desarrollo, pruebas y producción&lt;/strong&gt;: la aplicación corre de la misma manera en nuestra laptop como en la nube.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portabilidad entre nubes y distribuciones&lt;/strong&gt;: puede correr en Ubuntu, RHEL, CoreOS, un datacenter físico, Google Kubernetes Engine, entre otros.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gestión centrada en la aplicación&lt;/strong&gt;: aumenta el nivel de abstracción de ejecutar un sistema operativo en hardware virtual a ejecutar una aplicación en un sistema operativo utilizando recursos lógicos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservicios elásticos, distribuidos y bajamente acoplados&lt;/strong&gt;: las aplicaciones son divididas entre piezas más pequeñas e independientes y pueden ser deployadas y gestionadas dinámicamente, no teniendo un monolito corriendo en una única máquina de gran capacidad.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aislación de recursos&lt;/strong&gt;: rendimiento de la aplicación más predecible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utilización de recursos&lt;/strong&gt;: alta eficiencia y densidad.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ¿Por qué necesitas Kubernetes y qué puedes hacer?
&lt;/h2&gt;

&lt;p&gt;Los contenedores son una buena forma de agrupar y correr nuestras aplicaciones. En un entorno de producción, debemos manejar los contenedores que corren las aplicaciones y asegurarnos de que no haya momentos en que nuestra aplicación esté caída. Por ejemplo, si se cae un contenedor, otro debe iniciarse inmediatamente. ¿No sería más fácil si este comportamiento fuese manejado por un sistema en vez de hacerlo manualmente?&lt;/p&gt;

&lt;p&gt;¡Así es como Kubernetes viene al rescate! Kubernetes provee de un marco de trabajo para correr sistemas distribuidos de una manera más resistente y robusta. Se encarga de la escalabilidad y del manejo de fallos de nuestra aplicación, provee patrones de despliegue, y más. Por ejemplo, Kubernetes puede gestionar fácilmente &lt;em&gt;canary deployments&lt;/em&gt; para nuestro sistema.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nota: Canary deployment es un patrón para desplegar nuevos lanzamientos a un pequeño grupo de servidores, realizar testeos y luego aplicar estos cambios al resto de nuestros servidores.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes nos provee de lo siguiente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Balanceo de carga y exposición de servicios&lt;/strong&gt;: Kubernetes permite ubicar a un contenedor usando su nombre por DNS o su propia dirección IP. Si el tráfico hacia un contenedor es elevado, Kubernetes es capaz de balancear la carga y distribuirla hacia otro despliegue más estable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orquestación de almacenamiento&lt;/strong&gt;: nos permite montar automáticamente un sistema de almacenamiento a nuestra elección, como almacenamientos locales, proveedores cloud públicos, y más.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementaciones y restauraciones automatizadas&lt;/strong&gt;: podemos definir el estado deseado de nuestros contenedores desplegados usando Kubernetes, y podemos cambiar el estado actual a otro estado deseado a un ritmo controlado. Por ejemplo, podemos automatizar Kubernetes para que cree nuevos contenedores para nuestro despliegue, eliminando los contenedores existentes y tomando esos recursos para asignarlos a este nuevo despliegue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agrupación automática&lt;/strong&gt;: podemos indicar cuánta memoria RAM y CPU cada contenedor necesita para que Kubernetes se encargue de ubicarlos de una manera óptima y así aumentar la utilización y el ahorro de recursos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autoreparación&lt;/strong&gt;: Kubernetes puede reiniciar contenedores que fallan, reemplazarlos y detener a los que no respondan a la configuración establecida por el usuario, no exponiéndolos a clientes hasta que no estén listos para funcionar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gestión de configuraciones y secretos (credenciales de autenticación)&lt;/strong&gt;: podemos gestionar y guardar información sensible, como contraseñas, tokens de OAuth, y claves SSH. Podemos desplegar y actualizar nuestras credenciales y configuraciones sin tener que reconstruir las imágenes, y sin exponer dicha información.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ¿Qué NO es Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Kubernetes no es el tradicional sistema todo incluido de Plataforma como Servicio (PaaS). Dado que opera a un nivel de contenedores en lugar de a un nivel de hardware, proporciona algunas características de aplicación general que son comunes a lo que ofrecen las PaaS, como despliegue, escalabilidad, balanceo de carga y permite a los usuarios integrar sus soluciones de registro, monitoreo y alerta. No obstante, Kubernetes no es un monolíto, y estas soluciones por defecto son opcionales y vinculables. Kubernetes proporciona los componentes básicos para la creación de plataformas para desarrolladores, pero conserva la elección y la flexibilidad del usuario donde realmente es importante.&lt;/p&gt;

&lt;p&gt;Kubernetes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No limita los tipos de aplicaciones soportadas. Su objetivo es admitir una gran variedad de aplicaciones y programas, incluyendo los de tipo stateless, statefull y de procesamiento de datos.&lt;/li&gt;
&lt;li&gt;No despliega código fuente ni tampoco compila nuestra aplicación. Los flujos de trabajo de desarrollo, integración y despliegue continuo (CI/CD) están determinados por las preferencias y la cultura de la organización como así también los requerimientos técnicos.&lt;/li&gt;
&lt;li&gt;No provee servicios a nivel de la aplicación, como middleware, frameworks de procesamiento de datos, bases de datos, caches, o sistemas de almacenamiento como servicios integrados. Estos componentes pueden correr en Kubernetes y/o ser accedidos a través de aplicaciones que corren en Kubernetes por medio de mecanismos portables, como &lt;a href="https://www.openservicebrokerapi.org/"&gt;Open Service Broker&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;No impone soluciones de registro, monitoreo o alerta. Sí proporciona algunas integraciones como prueba de concepto, y mecanismos para recopilar y exportar métricas.&lt;/li&gt;
&lt;li&gt;No provee ni impone un lenguaje o sistema de configuración (como por ejemplo, Jsonnet), sino que proporciona una API declarativa que puede ser utilizada con cualquier tipo de especificacion declarativa. [más información(&lt;a href="https://www.meshcloud.io/2021/08/02/should-i-provide-a-declarative-api-you-propably-should/)"&gt;https://www.meshcloud.io/2021/08/02/should-i-provide-a-declarative-api-you-propably-should/)&lt;/a&gt;].&lt;/li&gt;
&lt;li&gt;No proporciona ni adopta ningún sistema exhaustivo de mantenimiento, gestión, autorepación o configuración.&lt;/li&gt;
&lt;li&gt;Adicionalmente, Kubernetes no es más que un simple sistema de orquestamiento. De hecho, elimina la necesidad de orquestamiento. La definición técnica de este concepto es la ejecución de un flujo de trabajo definido: primero hacer A, luego B, luego C. En contraste, Kubernetes comprende un conjunto de procesos componibles e independientes que continuamente buscan llegar a un estado deseado partiendo del estado actual. Sin importar como llegamos de ese estado A al estado C. El control centralizado tampoco es requerido. Esto resulta en un sistema que es fácil de usar y muy robusto, poderoso, sólido y totamente extensible.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Fuente: &lt;a href="https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/"&gt;https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Refactorización de un monolito (Refactoring of a monolith)</title>
      <dc:creator>Agustin Tosco</dc:creator>
      <pubDate>Wed, 08 Dec 2021 00:05:12 +0000</pubDate>
      <link>https://dev.to/agustintosco/refactorizacion-de-un-monolito-4fon</link>
      <guid>https://dev.to/agustintosco/refactorizacion-de-un-monolito-4fon</guid>
      <description>&lt;p&gt;Lo primero a tener en cuenta es que el título del artículo no sugiere directamente comenzar a migrar un proyecto de una arquitectura monolítica a una de microservicios. Previamente, deben tenerse en cuenta algunos puntos importantes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La arquitectura monolítica no es un anti-patrón de diseño.&lt;/li&gt;
&lt;li&gt;La arquitectura de microservicios no es la solución a todos nuestros problemas. Adoptar este tipo de arquitectura no solucionará problemas como código de mala calidad, falta de testing, baja calidad en el proceso de desarrollo.&lt;/li&gt;
&lt;li&gt;Éxito != Cantidad de microservicios&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Arquitectura monolítica&lt;/strong&gt;&lt;br&gt;
Es una estructura que consta de un gran sistema en el que se integran la gran mayoría de las funcionalidades y componentes de un proyecto. Son aplicaciones basadas en un lenguaje de programación específico, al igual que poseen una sola base de datos.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Algunas ventajas:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicidad: fáciles de construir, testear y deployar.&lt;/li&gt;
&lt;li&gt;Asuntos interdisciplinarios: al ser un "único" código, pueden manejarse de una mejor manera estos asuntos interdisciplinarios (cross-cutting concerns), como el logging, manejo de configuraciones, monitoreo de performance.&lt;/li&gt;
&lt;li&gt;Performance: Normalmente los componentes en un monolito comparten memoria, lo que hace que las comunicaciones entre los diferentes servicios sean más rápidas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Algunas desventajas:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confiabilidad: un simple error en cualquiera de los módulos/componentes puede comprometer y dejar fuera de servicio a toda la aplicación.&lt;/li&gt;
&lt;li&gt;Actualizaciones: debido a que es un gran bloque de código una actualización requiere deployar toda la aplicación nuevamente.&lt;/li&gt;
&lt;li&gt;Stack de tecnologías: un monolito usa el mismo stack de tecnologías. Realizar un cambio del mismo es muy costoso, tanto en tiempo como en costos involucrados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Arquitectura de microservicios&lt;/strong&gt;&lt;br&gt;
Por otro lado, consisten en servicios independientes y poco acoplados entre sí. De hecho, esta arquitectura divide los componentes de nuestra aplicación en pequeños y autónomos servicios que pueden ser deployados y escalados independientemente. A diferencia de los monolitos, estos microservicios pueden estar programados en diferentes lenguajes de programación, al igual que poseer varias bases de datos.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Algunas ventajas:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Escalabilidad: para escalar una aplicación de microservicios solamente se necesitan escalar ciertos componentes, lo que optimiza el uso de recursos.&lt;/li&gt;
&lt;li&gt;Bajo nivel de acoplamiento: los microservicios están poco acoplados entre sí, por ende no son interdependientes y pueden ser testeados individualmente. Además, hace a la aplicación más adaptable a los cambios a lo largo del tiempo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Algunas desventajas:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Equipo humano preparado: los beneficios de los microservicios son discutibles si no se tiene un equipo preparado.&lt;/li&gt;
&lt;li&gt;Testeo y monitoreo: Una vez que dividimos a la aplicación en componentes, tendremos un montón de partes individuales sobre las que realizar seguimiento y eventualmente fixes. Sin unas buenas herramientas de testeo y monitoreo, las cosas pueden salirse de control muy rápido.&lt;/li&gt;
&lt;li&gt;Velocidad de comunicación: al ser servicios aislados la comunicación es más complicada. O bien, usan HTTP o directamente queues.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Cómo decidir&lt;/strong&gt;&lt;br&gt;
Generalmente, las arquitecturas monolíticas son la opción correcta para aplicaciones simples y pequeñas.&lt;/p&gt;

&lt;p&gt;Por otro lado, una arquitectura de microservicios es una buena opción cuando queremos desarrollar sistemas más complejos, especialmente cuando se tiene un equipo de trabajo capacitado para este tipo de aplicaciones.&lt;/p&gt;

&lt;p&gt;Entonces, cuando tenemos que elegir entre una y otra arquitectura, debemos considerar estos cuatro puntos básicos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;¿Tenemos un equipo capacitado y que puede trabajar con microservicios?&lt;/li&gt;
&lt;li&gt;¿Tenemos la infraestructura suficiente para trabajar con aplicaciones distribuidas?&lt;/li&gt;
&lt;li&gt;¿Hemos evaluado los riesgos de negocio involucrados?&lt;/li&gt;
&lt;li&gt;¿Están definidos claramente los límites de nuestra aplicación?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si se decide adoptar una estructura de microservicios, deben tenerse en cuenta beneficios y costos al momento de elegir por cual servicio comenzar.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Relación costo-beneficio de extracción de un servicio&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Beneficios&lt;/th&gt;
&lt;th&gt;Costos&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Resuelve un problema significativo&lt;/td&gt;
&lt;td&gt;Adaptar / Reescribir el módulo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frecuencia de uso del servicio&lt;/td&gt;
&lt;td&gt;Dificultad en desacoplar dependencias&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Escalabilidad del servicio&lt;/td&gt;
&lt;td&gt;Nivel de participación del servicio en &lt;a href="https://https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/saga/saga"&gt;sagas&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Características de cada (micro)servicio:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Altamente mantenible y testeable.&lt;/li&gt;
&lt;li&gt;Puede ser deployado independientemente.&lt;/li&gt;
&lt;li&gt;Bajo responsabilidad de un pequeño equipo.&lt;/li&gt;
&lt;li&gt;Organizado en torno a las capacidades del negocio.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Pasos recomendados para migrar de una arquitectura monolítica a una de microservicios&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identificar los componentes de nuestra aplicación / proyecto.&lt;/li&gt;
&lt;li&gt;Refactorizar los componentes.&lt;/li&gt;
&lt;li&gt;Identificar las dependencias de los componentes.&lt;/li&gt;
&lt;li&gt;Identificar los diferentes grupos de componentes.&lt;/li&gt;
&lt;li&gt;Crear una API para utilizarla como el único modo de comunicación entre el sistema, sus componentes y los usuarios del sistema.&lt;/li&gt;
&lt;li&gt;Migrar los grupos de componentes a macroservicios.&lt;/li&gt;
&lt;li&gt;Migrar de macroservicios a microservicios.&lt;/li&gt;
&lt;li&gt;Repetir los pasos 6 y 7.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Fuentes:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://searchapparchitecture.techtarget.com/tip/Pros-and-cons-of-monolithic-vs-microservices-architecture"&gt;https://searchapparchitecture.techtarget.com/tip/Pros-and-cons-of-monolithic-vs-microservices-architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://insights.sei.cmu.edu/blog/8-steps-for-migrating-existing-applications-to-microservices/"&gt;https://insights.sei.cmu.edu/blog/8-steps-for-migrating-existing-applications-to-microservices/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chrisrichardson.net/post/refactoring/2020/08/21/ten-principles-for-refactoring-to-microservices.html"&gt;https://chrisrichardson.net/post/refactoring/2020/08/21/ten-principles-for-refactoring-to-microservices.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Array - ArrayList / Array List - Linked List</title>
      <dc:creator>Agustin Tosco</dc:creator>
      <pubDate>Fri, 03 Dec 2021 12:20:09 +0000</pubDate>
      <link>https://dev.to/agustintosco/array-arraylist-in-java-jbp</link>
      <guid>https://dev.to/agustintosco/array-arraylist-in-java-jbp</guid>
      <description>&lt;h2&gt;
  
  
  Array and Array Lists
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Arrays
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fixed length&lt;/li&gt;
&lt;li&gt;Anything =&amp;gt; Primitives (integer, long, boolean) and also Objects (string, Dog, etc) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ArrayList
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic length&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only hold objects. ArrayList =&amp;gt; Error! but can you can use its class wrapper, e.g.: Integer for int.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access elements&lt;br&gt;
&lt;code&gt;array[1];&lt;/code&gt;&lt;br&gt;
&lt;code&gt;arrayList.get(1);&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get length&lt;br&gt;
&lt;code&gt;array.length;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;arrayList.size();&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add elements&lt;br&gt;
&lt;code&gt;Cannot do it with Arrays&lt;/code&gt;&lt;br&gt;
&lt;code&gt;arrayList.add("New element"));&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set an element&lt;br&gt;
&lt;code&gt;array[0] = "New element";&lt;/code&gt;&lt;br&gt;
&lt;code&gt;arrayList.set(0, "New element");&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove elements&lt;br&gt;
&lt;code&gt;Cannot be done it in arrays&lt;/code&gt;&lt;br&gt;
&lt;code&gt;arrayList.remove(1)&lt;/code&gt;&lt;br&gt;
or&lt;br&gt;
&lt;code&gt;arrayList.remove("Name of element to be removed")&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Array Lists and Linked Lists
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;They are both part of the Collection framework and they implement the List interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  LinkedList
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Each element is called a node and it has a reference / pointer to the next  and the previous node.&lt;/li&gt;
&lt;li&gt;The linked list start with a pointer to the first element (HEAD).&lt;/li&gt;
&lt;li&gt;They are not in contiguous memory spots.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ArrayList
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Good performance for random access.&lt;/li&gt;
&lt;li&gt;Not so good when adding or removing new elements, because it needs to run over all the array for changing only one element.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
    </item>
  </channel>
</rss>
