<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>arquitectura &#8211; Oscar Blancarte &#8211; Software Architecture</title>
	<atom:link href="https://www.oscarblancarteblog.com/tag/arquitectura/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.oscarblancarteblog.com</link>
	<description>Software Architect &#38; FullStack developer</description>
	<lastBuildDate>Sun, 16 Aug 2020 20:52:25 +0000</lastBuildDate>
	<language>es-MX</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.15</generator>

<image>
	<url>https://www.oscarblancarteblog.com/wp-content/uploads/2019/03/cropped-ob-32x32.png</url>
	<title>arquitectura &#8211; Oscar Blancarte &#8211; Software Architecture</title>
	<link>https://www.oscarblancarteblog.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">89905023</site>	<item>
		<title>Circuit Breaker pattern</title>
		<link>https://www.oscarblancarteblog.com/2018/12/04/circuit-breaker-pattern/</link>
					<comments>https://www.oscarblancarteblog.com/2018/12/04/circuit-breaker-pattern/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Tue, 04 Dec 2018 16:00:44 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[microservicios]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=2436</guid>

					<description><![CDATA[<p>La llegada de nuevas arquitecturas como SOA o Microservicios han traído grandes ventajas, pero con ello, han surgido nuevas problemáticas que pocas veces se sabe cómo resolver con precisión, uno de estos casos, es identificar cuando un servicio ha dejado de funcionar para dejarle de enviar peticiones, pero por otro lado, identificar el fallo, reportarlo [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/12/04/circuit-breaker-pattern/">Circuit Breaker pattern</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="aligncenter size-large wp-image-2437" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/circuite-breaker.-1024x574.jpg" alt="" width="648" height="363" />La llegada de nuevas arquitecturas como SOA o Microservicios han traído grandes ventajas, pero con ello, han surgido nuevas problemáticas que pocas veces se sabe cómo resolver con precisión, uno de estos casos, es identificar cuando un servicio ha dejado de funcionar para dejarle de enviar peticiones, pero por otro lado, identificar el fallo, reportarlo y hacer algo en consecuencia, por suerte, la patrón Circuit Breaker (Corto circuito) permite cerrar la comunicación con un determinado servicio cuando se ha detectado que está fallado.<span id="more-2436"></span></p>
<p>&nbsp;</p>
<p>El patrón Circuit Breaker es muy parecido a un fusible, el cual se funde para evitar que una descarga eléctrica afecte al circuito, con la única diferencia de que el software, este fusible se puede restaurar cuando el problema allá pasado. Esto puede resultar un poco confuso, pero analicemos cómo funciona el patrón con el siguiente diagrama:</p>
<p><img loading="lazy" class="aligncenter size-large wp-image-2438" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/circuit-breaker-diagram-of-sequence-1024x590.png" alt="Circuit Breaker pattern diagrama de sequencia" width="648" height="373" /></p>
<p>&nbsp;</p>
<p>Antes de explicar cómo funciona el diagrama, debemos de comprender que son y el rol que tiene cada uno de los componentes involucrados:</p>
<ul>
<li><strong>Client</strong>: representa al cliente que intenta consumir los servicios del Supplier, sin embargo, este lo hace por medio del Circuit Breaker.</li>
<li><strong>Circuit Breaker</strong>: es el componente que se encarga de la comunicación con el Supplier, el cual, mantiene un registro del estado de salud del servicio que usará para abrir el circuito cuando detecte que el Supplier está fallando.</li>
<li><strong>Supplier</strong>: representa el servicio de negocio remoto, el cual expone una serie de funcionalidad para ser consumida por el Client.</li>
</ul>
<p>Una vez que entendemos esto, pasemos a explicar cómo funciona el patrón Circuit Breaker:</p>
<ol>
<li>El Client realiza una primera llamada al Supplier por medio del Circuit Breaker.
<ol>
<li>El Circuit Breaker determina que el servicio está operando correctamente el Supplier y redirecciona la petición al Supplier.</li>
<li>El Supplier responde correctamente y envía la respuesta al Circuit Breaker para que sea este quien finalmente reenvíe la respuesta al Client.</li>
</ol>
</li>
<li>El Client envía nuevamente una petición al Supplier por medio del Circuit Breaker
<ol>
<li>El Circuit Breaker redirecciona la petición al Supplier</li>
<li>En esta ocasión el Supplier responde con error o lanza un Timeout</li>
<li>El Circuit Breaker recibe la respuesta de error y toma nota del error, el cual tiene un contado que determina cuantas veces ha fallado el Supplier de forma simultánea. En este caso, el contado de errores se establece en 1.</li>
<li>El Circuit Breaker redirecciona el error al Client.</li>
</ol>
</li>
<li>Seguido de un tiempo, el Client envía nuevamente una petición al Supplier por medio el Circuit Breaker.
<ol>
<li>El Circuit Breaker redirecciona la petición al Supplier</li>
<li>El Supplier nuevamente responde con error o Timeout</li>
<li>El Circuit Breaker recibe la respuesta de error e incrementa el contado de errores en 2.
<ol>
<li>Dada una configuración, el Circuit Breaker puede determinar que 2 es el número máximo de errores simultáneos que puede tolerar antes de realiza el corto circuito y abre el circuito con el Supplier.</li>
<li>Un paso opcional pero muy deseable es tener algún componente de monitoreo que permite notificar a los administradores en tiempo real sobre los errores para poder tomar cartas en el asunto.</li>
</ol>
</li>
<li>El Circuit Breaker redirecciona el error al Client.</li>
</ol>
</li>
<li>El Client nuevamente envía una nueva petición al Supplier por medio del Circuit Breaker.
<ol>
<li>El Circuit Breaker determina el servicio no está respondiendo debido a los dos errores anteriores, por lo que retorna un error al Client indicándole que el Supplier está fuera de servicio.</li>
</ol>
</li>
</ol>
<p>&nbsp;</p>
<p>Como podemos observar en la explicación anterior, el Circuit Breaker puede determinar que un determinado servicio (Supplier) está fuera de servicio al detectar que ha respondido con error de forma consecutiva un número determinado de veces.</p>
<p>&nbsp;</p>
<blockquote><p>NOTA: es común confundirse con el termino abierto y cerrado, pues podemos pensar que el estado abierto es cuando el servicio está disponible, sin embargo, como estamos utilizando la nomenclatura de los circuitos eléctricos, por lo que un circuito cerrado es cuando la electricidad flujo, por lo tanto, en este patrón, cerrado significa que existe comunicación con el Supplier.</p></blockquote>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Abriendo el circuito</h2>
<p>En este punto te estarás preguntando, bien, ya he abierto el circuito, pero no me puedo quedar todo el tiempo así, necesito cerrarlo nuevamente una vez que el problema se ha resuelto. Pues bien, para eso, tenemos una funcionalidad adicional, en la cual configuramos cuanto tiempo debe esperar el Circuit Breaker antes de mandar una solicitud al Supplier. En este caso, por ejemplo, podríamos esperar una hora desde que se cerró el circuito para enviar una nueva petición, si esta petición retorna exitosamente, el Circuit Breaker cerrará nuevamente el circuito con el Supplier, pero, por el contrario, si este nuevamente retorna con error o Timeout, entonces el tiempo de espera se reiniciará y esperará otra hora antes de mandar una nueva petición para comprobar su disponibilidad.</p>
<p><img loading="lazy" class="aligncenter size-large wp-image-2439" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/circuit-breaker-diagram-of-sequence-open-1024x590.png" alt="Circuit Breaker pattern Diagrama de secuencia abierto" width="648" height="373" /></p>
<p>&nbsp;</p>
<p>Dicho lo anterior, veamos cómo quedaría el diagrama de secuencia para la reapertura del circuito:</p>
<ol>
<li>En la parte superior partimos del escenario donde hemos abierto el circuito, lo cual explicamos anteriormente, por lo que nos saltaremos esta explicación. Solo asumamos que, en este punto, el circuito se encuentra abierto.</li>
<li>Una hora después de que el circuito se abrió, el Circuit Breaker redirecciona la siguiente petición al Supplier que estaba fallando para comprobar si ya se encuentra en funcionamiento.
<ol>
<li>Tras redireccionar la petición al Supplier, este falla nuevamente y redirecciona el error al Circuit Breaker.</li>
<li>El Circuit Breaker al darse cuenta que sigue fallando, reinicia el contador para esperar otra hora antes de volver a intentar consumir los servicios del Supplier.</li>
</ol>
</li>
<li>Tras una hora desde el paso anterior, el Circuit Breaker redirecciona una nueva petición al Supplier para comprobar si ya se encuentra en funcionamiento.
<ol>
<li>En este caso, el Supplier ya se encuentra operando correctamente, por lo que recibe la petición, la procesa y retornar exitosamente.</li>
<li>El Circuit Breaker detecta la respuesta exitosa del Supplier y cierra nuevamente el circuito.</li>
</ol>
</li>
</ol>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Circuit Breaker y los microservicios</h2>
<p>En este punto ya hemos aprendido como es que el patrón Circuit Breaker abre el circuito ante una serie de errores consecutivos y como el circuito se cierra cuando el error es resuelto, pero hay algo de lo que no hemos hablado. ¿Te has preguntado que va a pasar con la aplicación si se abre el circuito? Es decir, una hora sin poder lanzar peticiones al Supplier podría causar un caos en nuestra aplicación, pues no podremos hacer nada hasta que el circuito sea restaurado.</p>
<p>Pues bien, te tengo buenas noticias, este patrón no fue diseñado para aplicaciones Standalone, si no que fue diseñado para arquitecturas cloud, donde tenemos alta disponibilidad y escalamiento, lo que quiere decir que debemos de tener múltiples instancias del Supplier, para asegurarnos de seguir operando ante la falla de una o múltiples instancias del mismo Supplier:</p>
<p><img loading="lazy" class="aligncenter size-large wp-image-2440" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/circuit-breaker-diagram-of-sequence-microservices-1024x646.png" alt="Circuit Breaker pattern arquitectura" width="648" height="409" /></p>
<p>&nbsp;</p>
<p>En la imagen anterior ya podemos observar cómo es que existe una serie de instancias de un mismo Supplier, por lo que en caso de que alguno falle, el Circuit Breaker deberá ser lo suficientemente inteligente para redireccionar la petición a otro Supplier en caso de que el primero falle, de esta forma, no retornamos el error al cliente, si no que reintentamos la ejecución en el siguiente Supplier disponible.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Ciclo de vida del Circuit Breaker</h2>
<p>El Circuit Breaker se puede implementar como máquina de estados, la cual puede pasar por 3 estados diferentes, y cada estado afectará la forma en que funciona, los estados son:</p>
<ul>
<li><strong>Closed</strong>: Este estado indica que el servicio destino está respondiendo correctamente. En caso de alcanzar un umbral de errores, pasará al estado Open.</li>
<li><strong>Open</strong>: Este estado indica que el servicio destino está fallando, por lo que toda invocación regresara un error de inmediato. Tras un tiempo de espera, pasará a estado Half-Open.</li>
<li><strong>Half-Open</strong> (medio abierto): Tras un tiempo en estado Open, el componente pase a Half-Open, lo que indica que puede recibir una pequeña cantidad de solicitudes para validar si el servicio está nuevamente activo. Si las solicitudes pasan exitosamente, el componente pasa a Closed, en otro caso, regresa a Open.</li>
</ul>
<p><img loading="lazy" class="aligncenter size-large wp-image-2441" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/circuit-breaker-lifecycle-1024x597.png" alt="Circuit Breaker pattern life cycle" width="648" height="378" /></p>
<p>&nbsp;</p>
<h2>Entornos Asíncronos</h2>
<p>Hasta este punto hemos analizado como es que este patrón se utiliza para servicios donde las invocaciones son síncronas, pero ¿qué pasaría si pasamos a un entorno donde los servicios a consumir se ejecutan de forma asíncrona? Por suerte, este patrón también se puede utilizar bajo estas circunstancias, aun que debemos de cambiar un poco la lógica, aunque el principio es el mismo.</p>
<p>En entornos síncronos, no tendremos respuestas con error ni timeout, por lo que las métricas que utilizábamos anteriormente no aplican, es por ello que podemos utilizar Colas (Queues):</p>
<p><img loading="lazy" class="aligncenter size-large wp-image-2442" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/12/circuit-breaker-queue-1024x574.png" alt="Circuit Breaker pattern life cycle asincrono" width="648" height="363" /></p>
<p>&nbsp;</p>
<p>En este caso, el Circuit Breaker en lugar de ejecutar directamente el servicio, tendrá que depositarlo en una Queue, de tal forma que el Supplier los podrá ir tomando a como pueda, lo que impide que lo saturemos de peticiones y lo hagamos colapsar, por otro lado, el Circuit Breaker podrá determinar el número de mensajes que tiene la Queue, y si este alcanza un umbral determinado, podríamos determinar que está fallando o que está procesando los mensajes demasiado lento, por lo que abrimos el circuito para impedir que se sature.</p>
<p>Como vemos, el funcionamiento es el mismo, lo que cambia es la forma de medir si un servicio está fallando o tarda mucho tiempo en procesar los mensajes.</p>
<p>&nbsp;</p>
<figure id="attachment_2333" aria-describedby="caption-attachment-2333" style="width: 648px" class="wp-caption aligncenter"><a href="https://reactiveprogramming.io/books/design-patterns/es" target="_blank" rel="noopener"><img loading="lazy" class="wp-image-2333 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/09/patrones-diseño-banner-1024x392.jpg" alt="" width="648" height="248" /></a><figcaption id="caption-attachment-2333" class="wp-caption-text">¿Te gustaría aprender más patrones como este? te invito a que veas mi libro &#8220;Introducción a los patrones de diseño&#8221; el único libro que te enseña los principales patrones de diseño utilizando ejemplos del mundo real. Olvídate de aprender con los ejemplos típicos de internet como, crear una pizza, animales que ladren o figuras geométricas.</figcaption></figure>
<p>&nbsp;</p>
<h2>Ventajas de implementar Circuit Breaker</h2>
<p>Adicional a las ventajas obvias que podemos ver, como la tolerancia a fallas y el envío de solicitudes a servicios que sabemos que van a fallar, existen otros tipos de ventajas:</p>
<p>&nbsp;</p>
<h3>Monitoreo:</h3>
<p>Dado que tenemos un componente que su única funcionalidad es sondear el estado de vida de los servicios, es posible tener un monitoreo en tiempo real, que nos indique los tiempos de respuesta promedio, frecuencia de falla, estado actual del servicio y, sobre todo, notificaciones en tiempo real si algún servicio comienza a fallar.</p>
<p>&nbsp;</p>
<h3>Sobrecarga:</h3>
<p>La capacidad de abrir el circuito ante un error o Timeout que sabemos que va a pasar, nos ahorra el hecho de tener muchos hilos esperando a que el servicio responda, y más aún, si tenemos miles de usuarios, es probable tener muchísimos hilos detenidos, lo que provocaría que nuestro sistema se sobre cargue, incluso, puede provocar una bola de nieve que comience a afectar a otros componentes.</p>
<p>&nbsp;</p>
<h3>Tolerancia a fallas</h3>
<p>Como ya lo dijimos, el Circuit Breaker puede redireccionar la petición al siguiente Supplier en caso de que alguno falle, evitando tener que enviarle el error al cliente.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Conclusiones</h2>
<p>Como hemos analizado a lo largo de este artículo, utilizar el patrón Circuit Breaker permite que inundemos nuestra aplicación con una gran cantidad de solicitudes que sabemos de antemano que van a fallar, por lo que, en lugar de eso, re direccionamos las peticiones a una instancia del servicio que está operativo.</p>
<p>Este patrón de diseño es altamente utilizado en entornos distribuidos y con arquitecturas de microservicios, por lo que no es para nada recomendable utilizarlo para operaciones en memoria o servicios albergados de forma local. Recordemos que este patrón está diseñado para recursos remotos.</p>
<p>&nbsp;		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/12/04/circuit-breaker-pattern/">Circuit Breaker pattern</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2018/12/04/circuit-breaker-pattern/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2436</post-id>	</item>
		<item>
		<title>Patrón Factory Method – Proyecto [Segunda parte] [Video]</title>
		<link>https://www.oscarblancarteblog.com/2018/08/15/patron-factory-method-proyecto-segunda-parte-video/</link>
					<comments>https://www.oscarblancarteblog.com/2018/08/15/patron-factory-method-proyecto-segunda-parte-video/#respond</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Thu, 16 Aug 2018 00:05:48 +0000</pubDate>
				<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[Patrones de diseño]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=2247</guid>

					<description><![CDATA[<p>Este video es la continuación del video de introducción a al patrón Factory Method. En esta segunda entrega aprenderemos a utilizar el patrón mediante in ejemplo del mundo real, en el cual aprenderemos a crear una aplicación que permite conectarse a más de una base de datos, la cual podrá ser intercambiada por medio de [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/08/15/patron-factory-method-proyecto-segunda-parte-video/">Patrón Factory Method – Proyecto [Segunda parte] [Video]</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<iframe class='youtube-player' width='648' height='365' src='https://www.youtube.com/embed/8sJai15H0iA?version=3&#038;rel=1&#038;fs=1&#038;autohide=2&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' allowfullscreen='true' style='border:0;'></iframe></p>
<p>Este video es la continuación del video de <a href="https://www.oscarblancarteblog.com/2018/08/01/patron-factory-method-introduccion/">introducción a al patrón Factory Method</a>. En esta segunda entrega aprenderemos a utilizar el patrón mediante in ejemplo del mundo real, en el cual aprenderemos a crear una aplicación que permite conectarse a más de una base de datos, la cual podrá ser intercambiada por medio de la configuración.		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/08/15/patron-factory-method-proyecto-segunda-parte-video/">Patrón Factory Method – Proyecto [Segunda parte] [Video]</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2018/08/15/patron-factory-method-proyecto-segunda-parte-video/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2247</post-id>	</item>
		<item>
		<title>Patrón Factory Method &#8211; Introducción [Primera parte] [Video]</title>
		<link>https://www.oscarblancarteblog.com/2018/08/01/patron-factory-method-introduccion/</link>
					<comments>https://www.oscarblancarteblog.com/2018/08/01/patron-factory-method-introduccion/#respond</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Wed, 01 Aug 2018 23:28:23 +0000</pubDate>
				<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[Patrones de diseño]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=2155</guid>

					<description><![CDATA[<p>En este video te enseñare la teoría que hay detrás del patrón Factory Method, este patrón permite la creación de objetos de un subtipo determinado a través de una clase Factory. Esto es especialmente útil cuando no sabemos, en tiempo de diseño, el subtipo que vamos a utilizar o cuando queremos delegar la lógica de [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/08/01/patron-factory-method-introduccion/">Patrón Factory Method &#8211; Introducción [Primera parte] [Video]</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<iframe class='youtube-player' width='648' height='365' src='https://www.youtube.com/embed/vb8gH4Ry7J8?version=3&#038;rel=1&#038;fs=1&#038;autohide=2&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' allowfullscreen='true' style='border:0;'></iframe></p>
<p>En este video te enseñare la teoría que hay detrás del patrón Factory Method, este patrón permite la creación de objetos de un subtipo determinado a través de una clase Factory. Esto es especialmente útil cuando no sabemos, en tiempo de diseño, el subtipo que vamos a utilizar o cuando queremos delegar la lógica de creación de los objetos a una clase Factory. Utilizando este patrón podemos crear instancias dinámicamente mediante la configuración, estableciendo cual será la implementación a utilizar en un archivo de texto, XML, properties o mediante cualquier otra estrategia.<span id="more-2155"></span></p>
<p>Puedes ver la segunda parte en <a href="https://youtu.be/8sJai15H0iA">aquí</a>		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2018/08/01/patron-factory-method-introduccion/">Patrón Factory Method &#8211; Introducción [Primera parte] [Video]</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2018/08/01/patron-factory-method-introduccion/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2155</post-id>	</item>
		<item>
		<title>Webhook una alternativa al Polling</title>
		<link>https://www.oscarblancarteblog.com/2017/09/11/webhook-una-alternativa-al-polling/</link>
					<comments>https://www.oscarblancarteblog.com/2017/09/11/webhook-una-alternativa-al-polling/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Mon, 11 Sep 2017 09:00:16 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[webhook]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=1845</guid>

					<description><![CDATA[<p>Los Webhook solucionan una de las problemáticas más comunes en la integración de aplicaciones, que es la obtención de actualizaciones en los sistemas de terceros, pues es difícil determinar cuándo una aplicación externa tiene nueva información de interés para nuestros sistemas. &#160; Solo imagina un escenario, tenemos una aplicación A y otra aplicación B, la [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/09/11/webhook-una-alternativa-al-polling/">Webhook una alternativa al Polling</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="size-full wp-image-1847 aligncenter" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/09/banner-small.jpg" alt="Webhook una alternativa al Polling" width="1199" height="672" />Los Webhook solucionan una de las problemáticas más comunes en la integración de aplicaciones, que es la obtención de actualizaciones en los sistemas de terceros, pues es difícil determinar cuándo una aplicación externa tiene nueva información de interés para nuestros sistemas.<span id="more-1845"></span></p>
<p>&nbsp;</p>
<p>Solo imagina un escenario, tenemos una <u>aplicación A</u> y otra <u>aplicación B</u>, la aplicación B genera nueva información de forma recurrente. La aplicación B no sabe de la existencia de la aplicación A y la aplicación A requiere obtener las novedades de la aplicación B.</p>
<p><img loading="lazy" class="aligncenter size-full wp-image-1848" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/09/1.png" alt="" width="1085" height="418" /></p>
<p>En este escenario, la aplicación A esta forzada a consultar frecuentemente por nuevas actualizaciones (Polling), lo que implica que la aplicación A no se entere al memento de los cambios, si no que tendrá que esperar a que el polling se ejecute nuevamente para obtener los nuevos datos, adicional, la aplicación B sufre un degrado en el performance, pues cada vez que la aplicación A realiza una consulta, la aplicación B tiene que buscar en la base de datos las actualizaciones, si esto lo multiplicamos por todos los posibles clientes podremos entender mejor el problema.</p>
<p>&nbsp;</p>
<h2>Webhook</h2>
<p>&nbsp;</p>
<p>Una mejor alternativa al polling tradicional, es la implementación de un Webhook, el cual consiste en crear un sistema de notificaciones mediante HTTP, para lo cual, la aplicación B permitiría que la aplicación A o cualquier otra registren una URL a cuál notificar en caso de actualizaciones. La ventaja que ofrece esta arquitectura es que la aplicación B sigue sin conocer a la aplicación A, y en su lugar solo conoce una URL a la cual deberá notificar en caso de haber actualizaciones.</p>
<p>&nbsp;</p>
<p>Cuando la aplicación B tiene nuevas actualizaciones, entonces lanza una llamada a la URL de la aplicación A. En esta llamada solo se envían los datos actualizados o un identificador para que posteriormente la aplicación A consulte todo el detalle.</p>
<p><img loading="lazy" class="aligncenter size-full wp-image-1849" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/09/2.png" alt="Arquitectura con Webhook" width="1128" height="554" /></p>
<p>Dado que las notificaciones son por medio de HTTP, hace que sea mucho más simple la comunicación, pues cualquier servidor puede recibir la petición y procesar el mensaje, también es compatible con servicios REST.</p>
<p>&nbsp;</p>
<p>Esta arquitectura ofrece un mejor rendimiento y una actualización en tiempo real. Para empezar, la aplicación A ya no requiere realizar consultar frecuentemente para saber si hay actualizaciones, por otra parte, la aplicación B yo requiere consultar su base de datos para cada petición, en su lugar este notificará a todos los interesados como parte del proceso.</p>
<p>&nbsp;</p>
<p>También puede interesarte como notificar aplicaciones mediante un sistema de mensajería como lo JMS, que explico en el articulo <a href="https://www.oscarblancarteblog.com/2014/07/15/jms-en-las-integraciones/">JMS en las integraciones</a>.</p>
<p>&nbsp;</p>
<h2>Conclusiones</h2>
<p>&nbsp;</p>
<p>Como podemos ver, utilizar un Webhook siempre será más eficiente que utilizar los tradicionales Polling, sin embrago, un Webhook es más complicado de implementar, pues requiere de contemplar las notificaciones en cada uno de los procesos de actualización sobre el sistema origen.</p>
<p>Esto no quiere decir que no debemos de utilizar polling, ya que esta arquitectura se utiliza cuando no existe otra alternativa y el sistema origen no tiene un mecanismo para notificar a los clientes.		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/09/11/webhook-una-alternativa-al-polling/">Webhook una alternativa al Polling</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2017/09/11/webhook-una-alternativa-al-polling/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1845</post-id>	</item>
		<item>
		<title>Single SingOn (SSO)</title>
		<link>https://www.oscarblancarteblog.com/2017/07/10/single-singon-sso/</link>
					<comments>https://www.oscarblancarteblog.com/2017/07/10/single-singon-sso/#respond</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Mon, 10 Jul 2017 10:00:09 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[Seguridad]]></category>
		<category><![CDATA[arquitectura]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=1792</guid>

					<description><![CDATA[<p>El Single SingOn (SSO o inicio de sesión única) es la capacidad de las aplicaciones modernas para permitir a los usuarios el acceso a varias aplicaciones mediante una solo autenticación, utilizando para ello, un proveedor de autenticación en común. Esto quieres decir que un usuario podría entrar a varias aplicaciones sin necesidad de tener que [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/07/10/single-singon-sso/">Single SingOn (SSO)</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="aligncenter wp-image-1799 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/07/Single-SingOn.jpg" alt="Single SingOn" width="794" height="446" />El Single SingOn (SSO o inicio de sesión única) es la capacidad de las aplicaciones modernas para permitir a los usuarios el acceso a varias aplicaciones mediante una solo autenticación, utilizando para ello, un proveedor de autenticación en común.</p>
<p><span id="more-1792"></span></p>
<p>Esto quieres decir que un usuario podría entrar a varias aplicaciones sin necesidad de tener que autenticarse en cada una, en su lugar, solo requerirá autenticarse la primera vez en cualquiera de las aplicaciones y posteriormente podrá acceder al resto si pasar por el proceso de autenticación.</p>
<p>&nbsp;</p>
<h2>Métodos de autenticación tradicional</h2>
<p>&nbsp;</p>
<p>Para comprender mejor este concepto es importante entender cómo funcionan los métodos de autenticación tradicional, en el cual, los usuarios requieren de un inicio de sesión en cada aplicación o página web en la que requieren entrar:</p>
<p>&nbsp;</p>
<h2><img loading="lazy" class="aligncenter wp-image-1794 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/07/Tradicional-authentication-method-1024x521.png" alt="Tradicional authentication method Single SingOn" width="648" height="330" /></h2>
<p style="text-align: center;">Ilustración 1 &#8211; Método de autenticación tradicional</p>
<p>&nbsp;</p>
<p>En los métodos de autenticación tradicional, el usuario tiene que autenticarse en cada aplicación en la que va requiriendo acceder, de esta manera, el usuario puede tener un usuario y contraseña diferente para cada aplicación. Cuando el usuario introduces sus credenciales, las aplicaciones van y comprueba que los datos del usuario son correctos directamente sobre su base de datos. Si las credenciales son correctas el usuario podrá acceder y operar el sistema.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Single SingOn (SSO)</h2>
<p>&nbsp;</p>
<p>A diferencia de los métodos tradicionales, SSO permite delegar el proceso de autenticación a una entidad externa, la cual tiene como única responsabilidad autenticar que el usuario es quien dice ser, una vez autenticado este regresa un comprobante o Ticket que deberá ser presentado a la aplicación a la cual se está solicitando el acceso. La aplicación toma el comprobante y lo valida contra la entidad de autenticación (SSO) y valida la veracidad del ticket y la vigencia del mismo, si todo está bien, entonces la aplicación permite al usuario operar el sistema. Cuando el usuario requiere entrar a otra aplicación distinta, tan solo requerirá presentar el ticket para poder autenticarse nuevamente hasta esta otra aplicación.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1800 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/07/Single-SingOn-Authentication-1024x548.png" alt="Single SingOn Authentication" width="648" height="347" /></p>
<p style="text-align: center;">Ilustración 2 &#8211; Autenticación mediante Single SingOut</p>
<p>&nbsp;</p>
<p>En esta imagen, podemos apreciar de forma más clara como es el proceso de autenticación mediante SSO. El usuario intenta entrar a la aplicación A, como el usuario no está autenticado, redirecciona al usuario a al proveedor de autenticación que soporte SSO, el usuario se autentifica ante el proveedor de autenticación, si se lleva acabo correctamente, este crea un token que le es enviado al usuario. A continuación, el proveedor de autenticación redirecciona nuevamente al usuario a la aplicación A. Cuando el usuario es redireccionado nuevamente a la aplicación A, el cliente ya cuenta con un token, el cual es enviado a la aplicación A para la autenticación. Finalmente, la aplicación A requiere validar el Token contra el proveedor de autenticación, si este es válido, entonces la aplicación A permite al usuario operar.</p>
<p>Puedes aprender más sobre los tokens y la autenticación en mi articulo <a href="https://www.oscarblancarteblog.com/2017/06/08/autenticacion-con-json-web-tokens/">autenticacion con json web tokens</a></p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1801 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/07/Single-SingOn-Authentication-away-1024x548.png" alt=" Single SingOn Authentication away" width="648" height="347" /></p>
<p>&nbsp;</p>
<p>Ilustración 3 &#8211; Autenticación en la aplicación B</p>
<p>&nbsp;</p>
<p>Otro escenario a estudiar, es cuando el usuario intenta entrar a una segunda aplicación (Aplicación B) justo después de haber autenticado en la aplicación A. Lo que pasa es muy parecido a lo que acabamos de analizar. Como el usuario ya cuenta con un Token, solo requiere enviar el token al momento de conectarse con la aplicación B, seguido, este valida que el token sea válido con ayuda del proveedor de autenticación, este último le indica a la aplicación B que el token es válido, entonces la aplicación B permite al usuario operar la aplicación.</p>
<p>En caso de que el proveedor de autenticación regresara que el token es invalido, entonces la aplicación redirecciona al usuario al proveedor de autenticación para que inicie sesión nuevamente.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Ventajas y Desventajas</h2>
<p>&nbsp;</p>
<p>A continuación, listo algunas de las ventajas/desventajas que veo implementar SSO</p>
<p>&nbsp;</p>
<h3>Ventajas</h3>
<ul>
<li>Simplifica la forma de autenticación para los usuarios.</li>
<li>Permite tener una sola credencial para todos los aplicativos.</li>
<li>Facilita el porte técnico, pues en caso de pérdida de contraseñas, solo modifica en un solo punto.</li>
</ul>
<p>&nbsp;</p>
<h3>Desventajas</h3>
<ul>
<li>Si falla la autoridad de autenticación, es muy probable que no se tenga accesos a las aplicaciones asociadas.</li>
<li>Un único usuario/password para todas las aplicaciones aumenta el riesgo de seguridad, pues las mismas credenciales dan acceso a todas las aplicaciones.</li>
<li>Requiere preparar a las aplicaciones para soportar SSO</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Conclusiones</h2>
<p>&nbsp;</p>
<p>Single SingOn se ha convertido es una de las tecnologías favoritas de las compañías, pues en muchas ocasiones, es posible autenticarse a las aplicaciones con tan solo estar logeados en la computadora.</p>
<p>También tenemos los inicios de sesión mediante redes sociales han sido un éxito en la web, pues es posible acceder a páginas con nuestra cuenta de Google, Facebook, Twitter, etc.</p>
<p>&nbsp;</p>
<p>En lo general, implementar Single SingOn es una muy buena estrategia, sin embargo, existe escenarios de alta seguridad, en donde tener un solo usuario/password podría ser muy riesgoso, ¿o te imaginas que los códigos nucleares de una nación se activarán con la contraseña de su Twitter?		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/07/10/single-singon-sso/">Single SingOn (SSO)</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2017/07/10/single-singon-sso/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1792</post-id>	</item>
		<item>
		<title>Concurrencia VS Paralelismo</title>
		<link>https://www.oscarblancarteblog.com/2017/03/29/concurrencia-vs-paralelismo/</link>
					<comments>https://www.oscarblancarteblog.com/2017/03/29/concurrencia-vs-paralelismo/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Wed, 29 Mar 2017 09:00:51 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[arquitectura]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=1648</guid>

					<description><![CDATA[<p>A pesar de que hoy en día casi todas las aplicaciones trabajan con múltiples hilos de ejecución y que los programadores saben utilizarlos, muy poca gente sabe distinguir entra Concurrencia y Paralelismo, ya que son conceptos bastantes relacionados, pero que no necesariamente significan lo mismo. &#160; &#160; Concurrencia: &#160; La concurrencia es la capacidad del [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/03/29/concurrencia-vs-paralelismo/">Concurrencia VS Paralelismo</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="aligncenter wp-image-1654 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/portada.jpg" alt="Concurrencia VS Paralelismo" width="795" height="446" />A pesar de que hoy en día casi todas las aplicaciones trabajan con múltiples hilos de ejecución y que los programadores saben utilizarlos, muy poca gente sabe distinguir entra Concurrencia y Paralelismo, ya que son conceptos bastantes relacionados, pero que no necesariamente significan lo mismo.<span id="more-1648"></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Concurrencia:</h2>
<p>&nbsp;</p>
<p><strong>La concurrencia es la capacidad del CPU para procesar más de un proceso al mismo tiempo</strong>, ¿simple no? Pero que implica esto realmente. Pues bien, para comprender esto es necesario entender cómo funciona un procesador. Un procesador puede procesar al mismo tiempo el mismo número de procesos que el número de CORES que tiene, de esta forma, si un procesador tiene un CORE, entonces solo podrá ejecutar un proceso a la vez, por otro parte, si tenemos 8 CORES, entonces podremos ejecutar hasta 8 procesos al mismo tiempo.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1649 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/1-1.png" alt="Concurrencia" width="699" height="456" /></p>
<p>Ya con este punto claro, solo quedaría agregar que, en la concurrencia, los procesos en ejecución no tienen por qué estar relacionados, es decir, cualquiera puede iniciar y terminar en el momento que sea, y el resultado de uno no afecta al otro.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Paralelismo:</h2>
<p>&nbsp;</p>
<p>El paralelismo sigue la filosofía de &#8220;divide y vencerás&#8221;, ya que consiste en<strong> tomar un único problema, y mediante concurrencia llegar a una solución más rápido</strong>. El paralelismo lo que hace es tomar el problema inicial, dividir el problema en fracciones más pequeñas, y luego cada fracción es procesada de forma concurrente, aprovechando al máximo la capacidad del procesador para resolver el problema. La principal diferencia del paralelismo contra la concurrencia es que, en el paralelismo, todos los procesos concurrentes están íntimamente relacionados a resolver el mismo problema, de tal forma que el resultado de los demás procesos afecta al resultado final.</p>
<p><strong>NOTA:</strong> En el paralelismo debe de haber un paso final que se encargue de unir los resultados de todos los procesos para poder arrojar un resultado final.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1650 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/2.png" alt="Paralelismo" width="874" height="347" /></p>
<p>Puede resultas complicado entenderlo a primera vista, pero observemos la imagen anterior. Primero que nada, llega un proceso grande (Amarillo), el cual es divididos en cuatro partes(Naranja), las cuales coinciden con el número de CORES del procesador(Verde). Ahora bien, por cada CORE disponible se lanza un proceso concurrente para resolver una fracción del problema. Cuando el proceso de un CORE termina, deja su resultado como una parte del resultado final (Naranja), así al terminar todos los procesos concurrentes, tenemos un resultado final (Amarillo).</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Escenario del mundo real:</h2>
<p>&nbsp;</p>
<p>Para comprender mejor como es que funcionan estos dos conceptos veremos un ejemplo simple de cada uno.</p>
<p>&nbsp;</p>
<h3>Ejemplo de concurrencia:</h3>
<p>Empecemos con la concurrencia, imagina una aplicación de descarga de música, en la cual puedes descargar un número determinado de canciones al mismo tiempo, cada canción es independiente de la otra, por lo que la velocidad y el tiempo que tarde en descargarse cada una no afectara al resto de canciones. Esto lo podemos ver como un proceso concurrente, ya que cada descarga es un proceso totalmente independiente del resto.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1651 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/3.png" alt="concurrencia" width="471" height="347" /></p>
<p>Observa la imagen, cada descarga se procesa de forma separada, y al final a una descarga no le importa el estado de las demás. Ya que cada descarga es una tarea completamente diferente.</p>
<p>&nbsp;</p>
<h3>Ejemplo de paralelismo:</h3>
<p>&nbsp;</p>
<p>En el caso del paralelismo podemos imaginas la clásica página de viajes, donde nos ayudan a buscar el vuelo más barato o las mejores promociones, para hacer esto, la página debe de buscar al momento en cada aerolínea el vuelo más barato, con menos conexiones, etc. Para esto puedo hacerlo de dos formas, buscar secuencialmente en cada aerolínea las mejores promociones (muy tardado) o utilizar el paralelismo para buscar al mismo tiempo las mejores promociones en todas las aerolíneas.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1652 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/4.png" alt="paralelismo" width="473" height="412" /></p>
<p>Observemos en la imagen como el proceso parte de una entrada inicial (inputs) los cuales definen las características del vuelo a buscar, luego se utiliza la concurrencia para buscar en las cuatro aerolíneas al mismo tiempo. Veamos que en este proceso es indispensable que las 4 búsquedas terminen para poder arrojar un resultado. Podemos ver claramente la relación entre los 4 procesos, ya que el resultado de uno puedo afectar al proceso final.</p>
<p>Observemos también que una vez que los cuatro procesos terminan, hay un subproceso adicional encargado de unir los resultados y arrojar un resultado final.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Conclusiones:</h2>
<p>Podrás observar que si bien, la concurrencia y el paralelismo está muy relacionados, no son la misma cosa, por lo tanto, la concurrencia ayuda a procesar varias tareas al mismo tiempo, mientras que el paralelismo resuelve una única tarea de una forma mucho más eficiente.</p>
<p>&nbsp;		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/03/29/concurrencia-vs-paralelismo/">Concurrencia VS Paralelismo</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2017/03/29/concurrencia-vs-paralelismo/feed/</wfw:commentRss>
			<slash:comments>17</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1648</post-id>	</item>
		<item>
		<title>Escalabilidad Horizontal y Vertical</title>
		<link>https://www.oscarblancarteblog.com/2017/03/07/escalabilidad-horizontal-y-vertical/</link>
					<comments>https://www.oscarblancarteblog.com/2017/03/07/escalabilidad-horizontal-y-vertical/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Tue, 07 Mar 2017 10:00:05 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[arquitectura]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=1560</guid>

					<description><![CDATA[<p>La escalabilidad es la capacidad del software para adaptarse a las necesidades de rendimiento a medida que el número de usuarios crece, las transacciones aumentan y la base de datos empieza a sufrir degradamiento del performance por las cargas crecientes. &#160; Hoy en día es muy común escuchar a los arquitectos de software que su [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/03/07/escalabilidad-horizontal-y-vertical/">Escalabilidad Horizontal y Vertical</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="aligncenter size-full wp-image-1567" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/escalamiento-vertical-y-horizanotal-1.jpg" alt="Escalabilidad horizontal y vertical" width="930" height="522" />La escalabilidad es la capacidad del software para adaptarse a las necesidades de rendimiento a medida que el número de usuarios crece, las transacciones aumentan y la base de datos empieza a sufrir degradamiento del performance por las cargas crecientes.<span id="more-1560"></span></p>
<p>&nbsp;</p>
<p>Hoy en día es muy común escuchar a los arquitectos de software que su solución es <strong>robusta, segura y escalable</strong> (Si cómo no!!!), pero la realidad es que pocas aplicaciones están realmente preparadas para ser escaladas, ya que desde su diseño de arquitectura no fueron concebidas para soportarlo o realmente no está muy claro que es realmente escalamiento.</p>
<p>&nbsp;</p>
<p>Como ya dijimos, el escalamiento es la capacidad del software para <em><strong>adaptarse al creciente</strong></em> número de usuario, transacciones, etc. ¿pero como un sistema se puede preparar para crecer indeterminadamente? La realidad es que las aplicaciones no pueden crecer infinitamente, por lo que siempre es clave determinar desde el diseño el <strong><em>grado de escalamiento</em></strong> que una aplicación podrá soportar, ya que por más estrategias que utilicemos el sistema ya no dará más.</p>
<p>Puede que los algoritmos utilizados no se puedan optimizarse más o la arquitectura no fue diseñada para un volumen tan alto de carga. Por otro lado, podríamos agregar más memoria al servidor, mas disco duro, cambiar a SSD, poner más cores, mejorar el enfriamiento, etc, etc. Sin embargo, llegara un momento que el hardware no puede crecer más, y tus sistemas simplemente explotaran, tendrás a los directores encima de ti preguntando cada 5 min ¿Qué paso? Y ¿En cuando tiempo quedarán listos los sistemas? El negocio está detenido, no podemos vender, los clientes están enojados, etc, etc, hasta el punto que tú mismo explotes con el sistema (hipotéticamente).</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Escalabilidad Horizontal y Vertical</h2>
<p>&nbsp;</p>
<p>En la práctica existen muchas formas de hacer que un software sea escalable ya que podemos combinar técnicas de software y hardware e incluso arquitecturas de RED (por qué no), pero en esta ocasión me quiere centrar en la escalabilidad horizontal y vertical, porque sin duda es una de las características más importantes para sistemas de alta demanda o uso crítico.</p>
<p>&nbsp;</p>
<p>Bien, como ya dijimos existen dos tipos de escalamiento, Horizontal y Vertical, ¿pero que quiere decir cada uno?</p>
<p>&nbsp;</p>
<h3>Escalabilidad vertical</h3>
<p>&nbsp;</p>
<p>La escalabilidad vertical o hacia arriba, este es el más simple, pues significa <strong><em>crecer el hardware</em></strong> de uno de los nodos, es decir aumentar el hardware por uno más potente, como disco duro, memoria, procesador, etc. pero también puede ser la migración completa del hardware por uno más potente. <strong><em>El esfuerzo de este crecimiento es mínimo</em></strong>, pues no tiene repercusiones en el software, ya que solo será respaldar y migrar los sistemas al nuevo hardware.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1562" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/escalamiento-vertical.png" alt="Escalabilidad Vertical" width="680" height="284" /></p>
<p>&nbsp;</p>
<p>¿Bastante fácil no?, la realidad es que este tipo de escalamiento tiene algunos aspectos negativos, ya que nuestro <strong><em>crecimiento está ligado al hardware</em></strong>, y este; tarde o temprano tendrá un límite, llegara el momento que tengamos el mejor procesador, el mejor disco duro, la mejor memoria y no podamos crecer más o podríamos a lo mejor comprar el siguiente modelo de servidores que nos costara un ojo de la cara y el rendimiento solo mejorar un poco, lo que nos traerá el mismo problema el próximo año.</p>
<p>Ahora bien, no significa que este modelo de escalamiento sea malo, ya que lo podemos combinar con el escalamiento horizontal para obtener mejores resultados.</p>
<p>&nbsp;</p>
<p><strong>Ventajas:</strong></p>
<ul>
<li>No implica un gran problema para las aplicaciones, pues todo el cambio es sobre el hardware</li>
<li>Es mucho más fácil de implementar que el escalamiento horizontal.</li>
<li>Puede ser una solución rápida y económica (compara con modificar el software)</li>
</ul>
<p>&nbsp;</p>
<p><strong>Desventajas:</strong></p>
<ul>
<li>El crecimiento está limitado por el hardware.</li>
<li>Una falla en el servidor implica que la aplicación se detenga.</li>
<li>No soporta la Alta disponibilidad.</li>
<li>Hacer un upgrade del hardware al máximo pues llegar a ser muy caro, ya que las partes más nuevas suelen ser caras con respecto al rendimiento de un modelo anterior.</li>
</ul>
<p>&nbsp;</p>
<h3>Escalabilidad horizontal</h3>
<p>&nbsp;</p>
<p>El escalamiento horizontal es sin duda el más potente, pero también el más complicado. <strong><em>E</em><em>ste modelo implica tener varios servidores</em><em> (conocidos como Nodos) trabajando como un todo</em></strong>. Se crea una red de servidores conocida como <strong><em>Cluster</em></strong>, con la finalidad de repartirse el trabajo entre todos nodos del cluster, cuando el performance del cluster se ve afectada con el incremento de usuarios, se añaden nuevos nodos al cluster, de esta forma a medida que es requeridos, más y más nodos son agregados al cluster.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1563" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/escalamiento-horizontal.png" alt="Escalabilidad horizontal" width="758" height="317" /></p>
<p>&nbsp;</p>
<p>Para que el escalamiento horizontal funcione deberá existir un servidor primario desde el cual se administra el cluster. Cada servidor del cluster deberá tener un software que permite integrase al cluster, por ejemplo, para las aplicaciones Java, tenemos los servidores de aplicaciones como Weblogic, Widfly, Websphere, etc. y sobre estos se montan las aplicaciones que queremos escalar.</p>
<p>&nbsp;</p>
<p><strong>Ventajas:</strong></p>
<ul>
<li>El crecimiento es prácticamente infinito, podríamos agregar cuantos servidores sean necesarios</li>
<li>Es posible combinarse con el escalamiento vertical.</li>
<li>Soporta la alta disponibilidad</li>
<li>Si un nodo falla, los demás sigue trabajando.</li>
<li>Soporta el balanceo de cargas.</li>
</ul>
<p>&nbsp;</p>
<p><strong>Desventajas</strong>:</p>
<ul>
<li>Requiere de mucho mantenimiento</li>
<li>Es difícil de configurar</li>
<li>Requiere de grandes cambios en las aplicaciones (si no fueron diseñadas para trabajar en cluster)</li>
<li>Requiere de una infraestructura más grande.</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2>Failover</h2>
<p>&nbsp;</p>
<p>A pesar de que escalamiento vertical no soporta de forma natural la alta disponibilidad, sí que es posible habilitarla mediante una estrategia llamada Failover, la cual consiste en que cuando el servidor falla, mediante hardware se redireccionan las peticiones a un servidor secundario que es un espejo del principal, este servidor normalmente se encuentra en stand by, y solo se habilita cuando el primario falla, de la misma manera, cuando el primario se recupera, el secundario vuelve a pasar a stand by.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1564 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/escalamiento-vertical-failover.png" alt="Escalabilidad vertical failover" width="663" height="314" /></p>
<p>&nbsp;</p>
<p>Por otra parte, la escalabilidad horizontal ya utiliza de forma natural el Failover, ya que al haber varios nodos, es posible pasar la carga al resto de nodos activos en caso de que uno falle. Ahora bien, esto no garantiza una alta disponibilidad total, ya que si el servidor primario falla puede tumbar todo el cluster, por lo que también se suele utilizar un ambiente espejo del cluster para garantizar la alta disponibilidad. Cabe mencionar que esto solo lo hacen empresas gigantes, ya que administrar dos cluster completos es un verdadero reto.</p>
<p>&nbsp;</p>
<p><img loading="lazy" class="aligncenter wp-image-1565 size-full" src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/escalamiento-horizontal-failover.png" alt="Escalabilidad horizontal failover" width="662" height="347" /></p>
<p>&nbsp;</p>
<h2>Failover</h2>
<p>&nbsp;</p>
<p>Hoy en día que las aplicaciones son parte fundamental de las empresas y que la falla en ellas puede incluso detener la operación de la empresa, llevándolas a perder grandes cantidades de dinero, es por eso que sumamente importante tener en mente el escalamiento de la aplicaciones y siempre tener un plan B en caso de que estas fallen, ¿Te imaginas la cantidad de dinero que perdería por hora, si la página de Amazon se callera? probablemente millones. Es por eso que debemos de estar preparados para escalar nuestras aplicaciones.</p>
<p>Si en este punto aun no estás seguro que escalamiento te va mejor, puedes analizar lo siguiente, si tu aplicación es de baja demanda y el número de usuarios está pensado para crecer poco a poco, la mejor solución puede ser el escalamiento vertical, ahora, si esta misma aplicación a pesar de su poco crecimiento es crítica para el negocio, entonces la puedes combinar con Failover para asegurar la alta disponibilidad.</p>
<p>Por otra parte, si tu aplicación esta pensaba para un crecimiento acelerado y crees que un servidor pueda quedar chico en un corto o mediano plazo, lo mejor será que empieces a pensar en escalamiento horizontal. Ahora bien si además del crecimiento la aplicación es de uso crítico, lo mejor será implementar un Failover. Si ya está utilizando escalamiento horizontal, recuerda que también puedes realizar escalamiento vertical a cada nodo del cluster, siempre y cuando el escalamiento vertical resulte más económico que agregar un nodo más.</p>
<p>&nbsp;</p>
<p>Bueno, esas son mis conclusiones, que piensas ahora, ¿estas realmente preparado para el desastre?</p>
<p>&nbsp;		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/03/07/escalabilidad-horizontal-y-vertical/">Escalabilidad Horizontal y Vertical</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2017/03/07/escalabilidad-horizontal-y-vertical/feed/</wfw:commentRss>
			<slash:comments>24</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1560</post-id>	</item>
		<item>
		<title>SOAP vs REST ¿cual es mejor?</title>
		<link>https://www.oscarblancarteblog.com/2017/03/06/soap-vs-rest-2/</link>
					<comments>https://www.oscarblancarteblog.com/2017/03/06/soap-vs-rest-2/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Mon, 06 Mar 2017 09:00:02 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[soa]]></category>
		<category><![CDATA[webservice]]></category>
		<guid isPermaLink="false">https://www.oscarblancarteblog.com/?p=1535</guid>

					<description><![CDATA[<p>SOAP vs REST es una comparación que muchos programadores o incluso arquitectos de software suelen preguntarse a la hora de desarrollar las API para sus sistemas, pero cual es realmente la diferencia que existe entre ellas, ¿Será que una es superior a la otra? ¿Será que REST llego para remplazar a SOAP? Pues bien, en [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/03/06/soap-vs-rest-2/">SOAP vs REST ¿cual es mejor?</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="aligncenter"><img src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/SOAP-vs-REST-1024x576.png" alt="SOAP vs REST" class="wp-image-1536"/></figure></div>



<p>SOAP vs REST es una comparación que muchos programadores o incluso arquitectos de software suelen preguntarse a la hora de desarrollar las API para sus sistemas, pero cual es realmente la diferencia que existe entre ellas, ¿Será que una es superior a la otra? ¿Será que REST llego para remplazar a SOAP? Pues bien, en este artículo trataremos de resolver esta gran duda.</p>



<span id="more-1535"></span>



<p>Primero que nada, me gustaría aclarar un error muy común que puede hacer que distorsione por completo tu entendimiento con respecto a los Web Services y es que <strong>SOA no es igual que SOAP y tener Web Services no significa que tenemos SOA</strong>. Hace un tiempo publique un artículo donde hablaba acerca de la <a href="https://www.oscarblancarteblog.com/2014/07/23/que-es-service-oriented-architecture-soa/">Arquitectura SOA</a> por si quieres darle una repasada al tema.<br>Pues bien, ya con este punto aclaro, debemos entender que SOA (Service-Oriented Architecture) es un <em><strong>tipo de Arquitectura de Software</strong></em> y no una tecnología o producto. SOA es una arquitectura que se base en la integración de aplicaciones mediante Servicios, los servicios representan la medida más granular de la arquitectura, sobre la que se construyen otros artefactos como: composiciones, proxys, fachadas, BPM e incluso API completas. Ahora bien, si SOA tiene como médula espinal los servicios, ¿no son SOAP y REST servicios? ¡Revelador no!!<br>Entonces si REST y SOAP son en realidad servicios, entonces que diferencia existe entre las dos, cual es el propósito de que existan dos tecnologías que aparentemente hacen lo mismo. Primero entendamos que SOAP y REST siguen la misma Arquitectura (SOA), por lo que las dos deberían de apegarse a los mismos principios.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/SOAP_VS_REST_SOA.png" alt="SOAP vs REST" class="wp-image-1537"/></figure></div>



<p>En este punto nos debe de quedar claro que tanto SOAP como REST son tecnologías que implementan la arquitectura SOA.</p>



<h2>&nbsp;</h2>



<h2>Que es SOAP:</h2>



<p>Los servicios SOAP o mejor conocimos simplemente como Web Services, son servicios que basan su comunicación bajo el protocolo SOAP (Simple Object Access Protocol) el cual este definido por Wikipedia como “protocolo estándar que define cómo dos objetos en diferentes procesos pueden comunicarse por medio de intercambio de datos XML”. Por lo tanto, queda claro que la comunicación se realiza mediante XML, lo cual nos debe de quedar muy claro, pues es en este aspecto donde radican las principales diferencias contra REST. Los servicios SOAP funcionan por lo general por el protocolo HTTP que es lo más común cuando invocamos un Web Services, sin embargo, SOAP no está limitado a este protocolo, si no que puede ser enviado por FTP, POP3, TCP, Colas de mensajería (JMS, MQ, etc). Pero como comentaba, HTTP es el protocolo principal.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/soap-services.png" alt="SOAP vs REST" class="wp-image-1538"/></figure></div>



<p>Si bien, me gustaría poner una sección de ventajas y desventajas, la realidad es que estas pueden ser lo contrario dependiendo del punto de vista y la situación concreta del problema a resolver por lo que me gustaría dejar un breve análisis de cuando utilizar SOAP. A mi parecer SOAP sigue siendo el mejor protocolo para <strong>la comunicación de Server to Server o Partner to Partner</strong>&nbsp;pues es un protocolo mucho más robusto, tiene un tipiado mucho más fuerte, permite agregar <em><strong>metadatos</strong></em> mediante los atributos (cosa que JSON no tiene), permite definir <strong><em>espacios de nombre</em></strong>, evitando la ambigüedad. Por lo mismo, SOAP es un formato más pesado, tanto en tamaño como en procesamiento, pues los XML tiene que ser parseado a un árbol DOM, resolver espacios de nombre (namespaces) antes de poder empezar a procesar el documento. Los XML además tienen métodos de validación muy potentes y ampliamente utilizados, a diferencia de JSON, el cual, si tiene forma de validar, pero no son tan potente y su utilización es pobremente utilizada (no significa que en el futuro no se estandarice su uso).</p>



<p>Nótese que, SOAP solo soporta formato XML, por lo que cuando lo que necesitamos es flexibilidad y un performance superior, podemos optar por REST. Tengo otro artículo donde hablo de <a href="https://www.oscarblancarteblog.com/2014/07/18/json-vs-xml/">XML vs JSON</a> por si quieres profundizar en el tema.</p>



<h2>Que es REST</h2>



<p>Por otra parte, tenemos REST, el chico nuevo de la cuadra. REST ya tiene unos años, pero en realidad tiene poco que se le empezó a dar la importancia que hoy tiene. REST es una tecnología mucho más flexible que transporta datos por medio del protocolo HTTP, pero este permite utilizar los diversos métodos que proporciona HTTP para comunicarse, como lo son GET, POST, PUT, DELETE, PATCH y a la vez, utiliza los códigos de respuesta nativos de HTTP (404,200,204,409). REST es tan flexible que permite transmitir prácticamente <strong><em>cualquier tipo de datos</em></strong>, ya que el tipo de datos está definido por el Header Content-Type, lo que nos permite mandar, XML, JSON, Binarios (imágenes, documentos), Text, etc. que contrasta con SOAP que solo permite la transmisión de datos en formato XML. A pesar de la gran variedad de tipos de datos que podemos mandar con REST, la gran mayoría transmite en JSON por un motivo muy importante, <strong><em>JSON es interpretado de forma natural por JavaScript</em></strong>, lo que ha hecho que frameworks como Angular y React se aprovechen al máximo, pues pueden enviar peticiones directas al servidor por medio de AJAX y obtener los datos de una forma nativa. Los formularios de HTML pueden ser apuntados a los servicios REST sin ningún problema (por ejemplo).</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://www.oscarblancarteblog.com/wp-content/uploads/2017/03/rest-services.png" alt="SOAP vs REST" class="wp-image-1539"/></figure></div>



<p>Otra de las grandes ventajas que presenta JSON sobre SOAP es el <strong><em>performance</em></strong>, ya que los JSON son considerablemente más livianos en peso y mucho más rápido en su procesamiento. Pero como ya vimos, el performance tiene un costo, y es la robustez del mensaje como tal.<br><br></p>



<div class="wp-block-image"><figure class="aligncenter"><a href="https://codmind.com/courses/api-rest-con-spring-boot" target="_blank" rel="noreferrer noopener"><img loading="lazy" width="800" height="450" src="https://www.oscarblancarteblog.com/wp-content/uploads/2019/08/banner-lg.jpg" alt="" class="wp-image-3146" srcset="https://www.oscarblancarteblog.com/wp-content/uploads/2019/08/banner-lg.jpg 800w, https://www.oscarblancarteblog.com/wp-content/uploads/2019/08/banner-lg-300x169.jpg 300w, https://www.oscarblancarteblog.com/wp-content/uploads/2019/08/banner-lg-768x432.jpg 768w" sizes="(max-width: 800px) 100vw, 800px" /></a><figcaption>Te invito a mi curso de Mastering API REST con Spring Boot</figcaption></figure></div>



<p>Ahora bien, desde mi punto de vista REST debería ser utilizado para obtener datos en aplicaciones WEB que funcionan principalmente con el Modelo MVC del lado del cliente, es decir, que todos los procesamientos se realizan desde el navegador y que solo va al backend para obtener o actualiza la base de datos. Otra de las situaciones es cuando tenemos aplicaciones donde los recursos de procesamiento son bajos y con ancho de banda limitado, como sería el caso de las aplicaciones móviles o robótica.</p>



<p>Te invito a que vas mi articulo &#8220;<a href="https://www.oscarblancarteblog.com/2018/01/11/construir-api-rest-nodejs-primera-parte/">Construir un API REST con NodeJS</a>&#8220;, en el cual hablo desde cero como implementar un API REST de la forma más simple y clara, utilizando NodeJS y Express. O puedes puedes ver la guia completa de cómo implementar un <a href="https://www.oscarblancarteblog.com/api-rest-java-jax-rs/">API REST con Java</a> desde cero.</p>



<p>Te puede interesar mi video de Youtube&#8221;<a href="https://youtu.be/RbBPuMlgdUU" target="_blank" rel="noreferrer noopener"><strong>Qué es API REST? &#8211; 🚀Y por que es importante aprenderlo 🚀</strong></a>&#8220;</p>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe class='youtube-player' width='648' height='365' src='https://www.youtube.com/embed/RbBPuMlgdUU?version=3&#038;rel=1&#038;fs=1&#038;autohide=2&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' allowfullscreen='true' style='border:0;'></iframe>
</div></figure>



<h2>SOAP vs REST Conclusiones</h2>



<p>Como vimos en este análisis, no hay un claro ganador, pues tanto SOAP como REST siguen siendo muy útiles en condiciones diferentes, incluso existen aplicaciones que ya exponente todas sus API’s en SOAP y REST para asegurar que la integración con ellas sea lo más natural posible sin importar la aplicación con la que se estén integrado.</p>



<p>Cabe mencionar que REST ha estado tomando fuerza a una velocidad impresionante y más con la llegada de NodeJS y las bases de datos NoSQL como MongoDB. Sin embargo, el hecho de que REST tome fuerza, no significa que le esté quitando protagonismo a SOAP, pues recordemos que con la llegada del Internet de las cosas (IOT) cada vez se conectan más dispositivos a internet que necesitan ser integrados (una gran oportunidad para REST) y es donde REST está tomando la delantera.</p>



<p>La verdad es que el futuro no se ve claro, pero lo que, si es que a pesar de que REST siga tomando fuerza, SOAP sigue siendo una tecnología muy robusta y extremadamente utilizada por lo que una cosa si es segura, a SOAP todavía le queda un largo camino.</p>



<p>A pesar de todo este análisis, lo importante es tu qué opinas, ¿cuál crees que sea el futuro?, ¿crees que REST poco a poco matara a SOAP? O ¿simplemente SOAP seguirá funcionando a la par con REST?.</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2017/03/06/soap-vs-rest-2/">SOAP vs REST ¿cual es mejor?</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2017/03/06/soap-vs-rest-2/feed/</wfw:commentRss>
			<slash:comments>126</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1535</post-id>	</item>
		<item>
		<title>Integración de aplicaciones con Cross Reference</title>
		<link>https://www.oscarblancarteblog.com/2015/11/04/integracion-de-aplicaciones-con-cross-reference/</link>
					<comments>https://www.oscarblancarteblog.com/2015/11/04/integracion-de-aplicaciones-con-cross-reference/#respond</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Wed, 04 Nov 2015 16:00:26 +0000</pubDate>
				<category><![CDATA[EAI]]></category>
		<category><![CDATA[arquitectura]]></category>
		<guid isPermaLink="false">http://www.oscarblancarteblog.com/?p=783</guid>

					<description><![CDATA[<p>Cross Reference o Referencias cruzadas es una de las técnicas más utilizadas para la integración de aplicaciones basadas en Arquitectura SOA, en donde las distintas aplicaciones comparten información similar pero replicada en cada una de ellas.  De entrada puede resultar un poco tonto decir que la información se encuentre en varias aplicaciones, sin embargo existen [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2015/11/04/integracion-de-aplicaciones-con-cross-reference/">Integración de aplicaciones con Cross Reference</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<a href="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/cross.png"><img loading="lazy" class="alignleft wp-image-795" src="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/cross.png" alt="cross reference" width="99" height="100" /></a></p>
<p>Cross Reference o Referencias cruzadas es una de las técnicas más utilizadas para la integración de aplicaciones basadas en Arquitectura SOA, en donde las distintas aplicaciones comparten información similar pero replicada en cada una de ellas.  De entrada puede resultar un poco tonto decir que la información se encuentre en varias aplicaciones, sin embargo existen escenarios donde esto es así y en realidad no está mal. Pero antes de debatir este punto me gustaría explicar en qué consiste Cross Reference.</p>
<p><span id="more-783"></span></p>
<h2>Como funciona Cross Reference</h2>
<p>Imaginemos un escenario de la vida real. Estamos a cargo del desarrollo de un ERP, el cual dentro de sus características está la de comunicarse con los proveedores para realizar pedidos de los productos que vendemos desde nuestro B2C (Business To Customer). Estos productos son solicitados a nuestros proveedores por medio de un WebService, el cual nos requiere como entrada los productos a comprar y la cantidad, entre otros datos más, los productos a comprar son indicados al proveedor por medio del ID del producto. El problema viene a continuación, tu pueden vender una Laptop marca ACME modelo XX la cual tiene un ID de producto XYZ, sin embargo este mismo producto para tu proveedor tiene un ID distinto, por ejemplo ABC. En este punto creo que ya somos más conscientes del problema ¿NO?. Sin entrar más en detalle imagina que el área de compras realizar su orden de compra para abastecer el producto bajo en existencia, esto generará la orden con el producto Laptops marca ACME modelo XX con ID XYZ. Aquí tenemos un problema, si yo le mando esa orden a mi proveedor me la rechazará por que el ID no lo reconoce, no sabe que producto le estas solicitando por lo que tendríamos que hacer un mapeo de los ID de nuestros productos con los productos de nuestro proveedor.</p>
<p><figure id="attachment_785" aria-describedby="caption-attachment-785" style="width: 436px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF11.png"><img loading="lazy" class="wp-image-785 size-full" src="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF11.png" alt="Tabla XREF" width="436" height="267" /></a><figcaption id="caption-attachment-785" class="wp-caption-text">Tabla XREF</figcaption></figure></p>
<p>Este mapeo se realiza con las tablas XREF o Tablas de referencia cruzada, en la imagen podemos apreciar una tabla llamada products la cual tiene la relación de los ID de los productos con los ID de nuestros partners, de esta manera, cada ID nuestro corresponde contra un ID de nuestro partner. Cuando un producto es enviado al partner este deberá primero mapeado contra nuestra tabla XREF para obtener los ID que correspondan con el partner.</p>
<p><figure id="attachment_786" aria-describedby="caption-attachment-786" style="width: 546px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/Cross-Reference1.png"><img loading="lazy" class="size-full wp-image-786" src="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/Cross-Reference1.png" alt="Cross Reference" width="546" height="308" /></a><figcaption id="caption-attachment-786" class="wp-caption-text">Cross Reference</figcaption></figure></p>
<p>En la imagen podemos ver el proceso por el cual el pedido es procesado, el ERP genera el pedido y lo envía a una integración, el cual podrías ser un servicio o un <a href="http://www.oscarblancarteblog.com/2014/07/15/que-es-bpel/">BPEL </a>para automatizar el proceso, el proceso realizaría el mapeo de claves contra la XREF generando un nuevo documento con los identificadores para el partner especifico.</p>
<p>&nbsp;</p>
<h2>Tablas XREF</h2>
<p>Ya hablamos del proceso en sí, pero no hemos hablado de cómo es que las tablas XREF funcionan y cuál es la estructura que estas tablas deben de tener.  En la actualidad sobresalen dos formatos para estas tablas.</p>
<h3>XREF por entidad</h3>
<p>Este formato consiste en crear una tabla por cada entidad del sistema, en esta tabla todos los registros que encontremos pertenecerán siempre a la misma entidad como por ejemplo todos los productos, pero solo productos.</p>
<p><figure id="attachment_787" aria-describedby="caption-attachment-787" style="width: 244px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF2.png"><img loading="lazy" class="size-full wp-image-787" src="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF2.png" alt="XREF por producto" width="244" height="109" /></a><figcaption id="caption-attachment-787" class="wp-caption-text">XREF por producto</figcaption></figure></p>
<p>En la imagen ponemos un ejemplo de una tabla XREF por entidad, lo primero que vemos es que se llama PRODUCTS aunque el nombre no es relevante, lo segundo es que tenemos una columna llamada ERP, esta columna nos indica el ID del producto en nuestro ERP, la columna PARTNER nos indica el ID del mismo producto pero para nuestro PARTNER.  Para obtener el ID de nuestro partner solo tendremos que lanzar un query muy simple: SELECT PARTNER FROM PRODUCTS WHERE ERP =&#8217;XYZ&#8217;.</p>
<p>Este modelo tiene el inconveniente de que necesitaremos una tabla por cada entidad que necesitemos mapear, aunque por otro lado nos permite dar privilegios a las aplicaciones solo para las tablas requeridas.</p>
<p>&nbsp;</p>
<h3>XREF General:</h3>
<p>La segunda manera es crear una tabla general en la cual tengamos todas las entidades con una columna especial que nos indica de qué tipo de entidad se trata el registro. De esta manera todas las entidades que se manejen estarán aquí, por ejemplo productos, proveedores, clientes, etc.</p>
<p><figure id="attachment_788" aria-describedby="caption-attachment-788" style="width: 323px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF3.png"><img loading="lazy" class="size-full wp-image-788" src="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF3.png" alt="XREF general" width="323" height="170" /></a><figcaption id="caption-attachment-788" class="wp-caption-text">XREF general</figcaption></figure></p>
<p>En esta tabla podemos ver que se agrega la columna ENTITY, la cual indica de qué tipo de objeto es el registro. Esta tabla funciona de forma muy similar a la XREF por entidad, solo que en esta tendríamos que añadir en la búsqueda el tipo de entidad que estamos buscando, por ejemplo: SELECT PARTNER FROM XREF WHERE ENTITY = &#8216;PRODUCT&#8217; AND ERP = &#8216;XYZ&#8217;, este query buscara el ID de nuestro partner pero filtrando solo los registros de productos.</p>
<h3></h3>
<h3>XREF para varios partners</h3>
<p>Una de las características de las XREF es que nos permiten agregar más de un solo partner, por ejemplo, ¿qué pasaría si un mismo producto no lo puede surtir más de un proveedor?, agregar una tabla XREF por proveedor sería algo muy incómodo e impráctico, por esta razón, a las tablas XREF se les pues agregar una nueva columna por cada partner con el que tenemos comunicación.</p>
<p><figure id="attachment_790" aria-describedby="caption-attachment-790" style="width: 441px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF4.png"><img loading="lazy" class="size-full wp-image-790" src="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/XREF4.png" alt="XREF Multiples partners" width="441" height="269" /></a><figcaption id="caption-attachment-790" class="wp-caption-text">XREF Multiples partners</figcaption></figure></p>
<p>En la imagen podemos apreciar que un mismo productos puede estar mapeado contra 3 partner distintos, lo que nos permite en cualquier momento obtener el ID del productos para cualquier de ellos. Es este caso el query cambia un poco según al partner al que nos estemos comunicando, por ejemplo: SELECT PARTNER1 FROM PRODUCTS WHERE ERP = &#8216;XYZ&#8217;, otra variante seria tener una tabla XREF general, en la cual solo agregamos la Entidad que estamos buscando.</p>
<p>&nbsp;</p>
<h2>Sincronización de las XREF</h2>
<p>Otro de los puntos fundamentales para que una tabla XREF funcione, es tener la tabla actualizada, es decir que cada nuevo producto nuevo sea sincronizado, esto se puedo hacer de dos formas, automatizada o manual. Cuando es manual, no hay mucho que decir, pues se requiere de una persona o personas que estén constantemente actualizando los catálogos para que la información cuadre. Este escenario lo dejaremos de lado, ya que lo que nos interesa es automatizar el proceso.</p>
<p>En el escenario que explicamos anteriormente es mucho más complejo automatizar el proceso, pues la creación de los productos no está en nuestro control, y no es posible determinar qué productos es cual en nuestro aplicación, por este motivo expondremos un segundo escenario en el cual la creación de entidades si este bajo nuestro control.</p>
<p>Imaginemos que dentro de nuestra arquitectura tenemos una aplicación CRM desde la cual ofrecemos los productos a nuestros clientes y otra aplicación que se encarga de la facturación, del lado del CRM se crean los productos y se personalizan y desde el lado del facturador se asignan los precios y se generan las facturas mensuales a los clientes. Ambos sistemas comparten los mismos productos pero estos tienen sus propias copias en su base de datos. Cuando el CRM le vende productos a un cliente, este le envía al facturador los productos vendidos, luego el facturador le envía al CRM el detalle de la factura con los productos facturados.</p>
<p>En este punto es más que evidente que cada aplicación tiene su propia copia local del producto, por lo tanto cada uno maneja ID distintos, por otra lado, los productos son creados por el CRM aunque también podrían ser creados por el facturador. La pregunta es ¿Cómo podemos sincronizar los productos?, para resolver esta pregunta veamos la siguiente imagen:</p>
<p>&nbsp;</p>
<p><figure id="attachment_791" aria-describedby="caption-attachment-791" style="width: 603px" class="wp-caption aligncenter"><a href="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/syncCrossReference.png"><img loading="lazy" class="size-full wp-image-791" src="http://www.oscarblancarteblog.com/wp-content/uploads/2015/11/syncCrossReference.png" alt="sync Cross Reference" width="603" height="331" /></a><figcaption id="caption-attachment-791" class="wp-caption-text">sync Cross Reference</figcaption></figure></p>
<p>La sincronización se da de la siguiente manera:</p>
<ol>
<li>Un producto es creado en el CRM</li>
<li>El CRM ejecuta una integración para replicar el producto a los demás sistemas</li>
<li>La integración crea el mismo objeto en el facturador y espera hasta que le regresa el ID generado.</li>
<li>El ID del CRM que fue enviado y el ID generado por el facturador son insertados en la tabla XREF.</li>
<li>De igual forma, si el facturador crea un nuevo producto este es replicado con la misma técnica.</li>
</ol>
<p>Si un nuevo sistema es agregado y requiere de la sincronización de productos es simplemente es agregado en el proceso de sincronización y se agrega una columna extra a la tabla para poder guardar el ID generado para este nuevo sistema.</p>
<h2>Conclusiones:</h2>
<p>Cabe mencionar que esta técnica es implementada por lo fabricantes de Middleware más importantes y en muchos de los casos este tipo de integraciones son vendidas como paquetes para conectar los principales ERP, CRM, etc.  En el caso de Oracle, este los vende como Process Integration Packs o PIP&#8217;s que son parte de un paquete llamado AIA o Application Integration Architecture.</p>
<p>Mi recomendación es investigar si nuestros productos ya tienen integraciones previamente desarrolladas que nos permitan ahorrarnos un gran esfuerzo antes de decidir desarrollar nuestras propias integraciones.</p>
<p>&nbsp;		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2015/11/04/integracion-de-aplicaciones-con-cross-reference/">Integración de aplicaciones con Cross Reference</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2015/11/04/integracion-de-aplicaciones-con-cross-reference/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">783</post-id>	</item>
		<item>
		<title>Patrón de diseño Command</title>
		<link>https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/</link>
					<comments>https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/#comments</comments>
		
		<dc:creator><![CDATA[oblancarte]]></dc:creator>
		<pubDate>Wed, 19 Nov 2014 10:00:00 +0000</pubDate>
				<category><![CDATA[Patrones de Diseño]]></category>
		<category><![CDATA[arquitectura]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Patron de diseño]]></category>
		<guid isPermaLink="false">http://javamex.wordpress.com/?p=427</guid>

					<description><![CDATA[<p>El patrón de diseño Command es muy utilizado cuando se requiere hacer ejecuciones de operaciones sin conocer realmente lo que hacen, estas operaciones son conocidas como comandos y son implementadas como una clase independiente que realiza una acción muy concreta, para lo cual,únicamente recibe un conjunto de parámetros para realizar su tarea. La siguiente imagen [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/">Patrón de diseño Command</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>				<img loading="lazy" class="aligncenter wp-image-1570 " src="https://www.oscarblancarteblog.com/wp-content/uploads/2014/11/Command-pattern.jpg" alt="Patrón de diseño Command" width="859" height="482" />El patrón de diseño <strong>Command</strong> es muy utilizado cuando se requiere hacer ejecuciones de operaciones sin conocer realmente lo que hacen, estas operaciones son conocidas como comandos y son implementadas como una clase independiente que realiza una acción muy concreta, para lo cual,únicamente recibe un conjunto de parámetros para realizar su tarea.<span id="more-427"></span></p>
<p style="text-align: justify;">La siguiente imagen muestra la estructura del patrón de diseño:</p>
<p><figure style="width: 581px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise1.png" alt="Patrón de diseño Command" width="581" height="453" /><figcaption class="wp-caption-text">Fig.1: En la imagen podemos apreciar cómo está diseñado el patrón de diseño Command.</figcaption></figure></p>
<p>&nbsp;</p>
<p>En la imagen podemos apreciar los siguientes elementos:</p>
<p><strong>ICommand: </strong>Esta es la pieza más importante del patrón, ya que cada comando deberá implementar esta interface y deberá implementar el método <strong>execute</strong>, el cual, de forma <a title="Que es el Polimorfismo?" href="http://oscarblancarteblog.com/2014/07/15/que-es-el-polimorfismo/">polimórfica </a>realizara la operación que deseamos. Este componente generalmente es una interface o una clase abstract.</p>
<p><strong>Concrete Command: </strong>Para este componente hablaremos en plural, ya que cada Concrete Command que tengamos implementado se convertirá en un comando en nuestro patrón. Este componente tiene que implementar <strong>ICommand </strong>de forma directa o indirecta y deberá implementar el método <strong>execute</strong>, en el cual se realizara la operación que deseamos que realice el comando.</p>
<p><strong>Command Manager: </strong>Este componente nos servirá para administrar los comandos que tenemos disponibles en tiempo de ejecución, desde aquí podemos ejecutar un Comando o registrar nuevos comandos para que estén disponibles en tiempo de ejecución. Esta clase es importante, ya que de nada sirve tener un conjunto de <strong>Concrete Command</strong> que implementan <strong>ICommand</strong> regados por nuestro proyecto si no tenemos un componente que los administre y nos permite ejecutarlos.</p>
<p><strong>Invoker: </strong>El invoker representa a la acción que dispara alguno de los comandos, un invoker podría ser un usuario, una aplicación o algún evento generado por nuestra aplicación.</p>
<p>Ya que conocemos los componentes es hora de hablar un poco más del Patrón de diseño, Al comienzo comentamos que nos sirve para realizar operaciones sin conocer realmente que hace la operación. Para lo cual utilizaremos un ejemplo y veremos de qué forma este patrón lo resuelve.</p>
<p>A estas alturas me imagino que todos ya hemos utilizado alguna vez la consola de Windows o Unix. Si observamos la consola, veremos que ella response a base de comandos, estos comandos pueden o no necesitar parámetros para funcionar, lo asombroso aquí es que la consola tiene la característica de saber siempre que operación va a realizar sin tener que decirle que clase o que software utilice para realizar la tarea, ya que la consola es capaz de determinar el comando utilizado y ejecutar el componente o software que realizar la operación deseada.</p>
<p>Otro punto importante es que la consola tiene la característica de agregarle comandos a medida que instalamos nuevo software como es el caso de Java, si intentamos ejecutar el comando <strong><em>java –version</em></strong>, con una computadora la cual no tiene instalado Java veras que te arrojara un mensaje de comando no encontrado, sin embargo si tu ejecutas de nuevo el comando una vez instalado java, entonces obtener un mensaje como el siguiente <strong><em>java version &#8220;1.7.0_51&#8243;…..</em></strong>, En el patrón Command podemos registrar nuevos comandos mediante el componente CommandManager lo cual lo veremos más a delante.</p>
<p>Para analizar mejor este Patrón de diseño analizaremos el ejemplo de la consola y desarrollaremos una mediante el <strong>Patrón Command</strong>. Para iniciar el ejemplo tendremos que pensar primero en la funcionalidad que le daremos a nuestra consola, en este ejemplo desarrollaremos comandos muy simples pero útiles que ayuden a demostrar la utilidad del patrón, para lo cual les dejo la siguiente imagen:</p>
<p><figure style="width: 572px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise2.png" alt="Patrón de diseño Command" width="572" height="447" /><figcaption class="wp-caption-text">Fig.2: La siguiente imagen muestra los comandos que desarrollaremos en el ejemplo.</figcaption></figure></p>
<p>Podemos identificar a los comandos de forma muy simple ya que son todos aquellos que implementan <strong>ICommand</strong> de forma directa o indirecta, cada comandos tiene un nombre diferente el cual lo utilizaremos para ejecutarlos desde nuestra consola. La explicación de los comandos está a continuación.</p>
<p><strong>Exit: </strong>finaliza la consola y termina con nuestro programa.</p>
<p><strong>Memory: </strong>Nos muestra en pantalla la cantidad de memoria total disponible, utilizada y máxima que podemos utilizar.</p>
<p><strong>Batch: </strong>Comando que ejecuta en lote un conjunto de comandos definidos en un archivo plano.</p>
<p><strong>Echo: </strong>Comando que nos imprime en pantalla lo que escribimos en la consola.</p>
<p><strong>Date: </strong>Comando que nos imprime en pantalla la hora y la fecha en el formato que queramos.</p>
<p><strong>File: </strong>Comando que nos permite interactuar con archivos, como crear, borrar, escribir, etc.</p>
<p><strong>Dir: </strong>Nos permite realizar operaciones con directorios, ya sea crearlos o borrarlos.</p>
<p><strong>WaitHello:</strong> Comando que nos permite demostrar la ejecución en segundo plano, este comando al ejecutarse escribe &#8220;Hello!&#8221; Después de un tiempo determinado.</p>
<p>A demás de los comandos tenemos los Abstract Command, los cuales están representados en el diagrama de color azul, estos comandos no hacen una funcionalidad como tal, sin embargo ayudan a crear otros comandos más complejos, los <strong>Abstract Command</strong> que tenemos aquí hace lo siguiente:</p>
<p><strong>BaseCommand: </strong>Comando que agrega únicamente el método <strong>write</strong> el cual nos ayuda a escribir en pantalla los eventos generados por nuestros comandos, además de que nos permite tener un método estándar de escritura que podría ser modificado para afectar a todos los comandos, ahorrándonos el problema de modificar cada comando para que escriba de forma distinta.</p>
<p><strong>AsyncCommand: </strong>Este comando tiene como finalidad demostrar que también se pueden crear comandos que se ejecuten en segundo plano, este comando tiene la característica que ejecuta la acción en un hilo independiente por lo que podemos seguir trabajando con la consola sin que el comando haya terminado de ejecutarse. Otro punto importante es que implementa el método <strong>execute</strong>, pero agrega el método abstracto <strong><em>executeOnBackground</em></strong>, en el cual deberemos implementar la función que queremos que realice en segundo plano.</p>
<p><figure style="width: 627px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise3.png" alt="Patrón de diseño Command" width="627" height="404" /><figcaption class="wp-caption-text">Fig.3: La imagen muestra un diagrama de secuencia de cómo se lleva a cabo la ejecución de un comando.</figcaption></figure></p>
<p>&nbsp;</p>
<h2><span style="font-size: 12pt;"><strong>Implementación:</strong></span></h2>
<p>Una vez platicado el escenario podemos pasar a la implementación de la consola.</p>
<p><strong>Clase ICommand:</strong> Interface que tiene como propósito definir la estructura mínima de un comando, Esta interface define dos métodos, <strong><em>getCommandName</em></strong> el cual regresa el nombre del comando para uso informativo, También tiene el método <strong><em>execute</em></strong> el cual es implementado por los comandos para realizar la operación deseada, el método recibe un arreglo de String que corresponde a los parámetros del comando y un OutputStream el cual utilizaremos para ir notificando al usuario todas las cosas relevantes como un mensaje o un error.</p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Interface ICommand ">package javamex.patronesdiseño.command;

import java.io.OutputStream;

public interface ICommand {

    public String getCommandName();

    public void execute(String[] args, OutputStream out);
}</pre>
<p>&nbsp;</p>
<p>Clase CommanManager: Esta clase es utilizada para gestionar los comandos disponibles en nuestra aplicación, desde esta clase podremos registrar nuevos comandos y recuperar los comandos solicitados por el usuario, La clase contiene los siguientes métodos:</p>
<ul>
<li>getCommand: Este método recibe como parámetro un String el cual corresponde al nombre del comando solicitado, El comando es buscado y retornado, pero si un comando no es encontrado se regresa un comando de error el cual explicaremos más a delante.</li>
<li>registCommand: Método utilizado para registrar los commandos que tendremos disponibles en tiempo de ejecución, para que un comando esté disponible en la aplicación primero tendrá que ser registrado.</li>
<li>getIntance: Método que nos permite obtener una instancia de la clase CommanManager ya que la esta clase sigue el patrón de diseño Singleton(Hablare de el en otra entrada).</li>
</ul>
<p>Un punto importante a resaltar el constructor de la clase, en el cual registramos todos los comandos disponibles de forma predefinida para que estén disponibles en tiempo de ejecución, por defecto, cualquier comandos que creemos y que no se encuentre registrados no podrá ser reconocido.<span style="font-size: 10pt;"><br />
</span></p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Clase CommandManager">package javamex.patronesdiseño.command;

import java.util.HashMap;
import javamex.patronesdiseño.command.impl.*;

public class CommandManager {

    private static CommandManager commandManager;

    private static final HashMap&lt;String, Class&lt;? extends ICommand&gt;&gt; COMMANDS =
            new HashMap&lt;String, Class&lt;? extends ICommand&gt;&gt;();

    private CommandManager() {
        registCommand(EchoCommand.COMMAN_NAME, EchoCommand.class);
        registCommand(DirCommand.COMMAND_NAME, DirCommand.class);
        registCommand(DateTimeCommand.COMMAND_NAME, DateTimeCommand.class);
        registCommand(MemoryCommand.COMMAN_NAME, MemoryCommand.class);
        registCommand(FileCommand.COMMAND_NAME, FileCommand.class);
        registCommand(ExitCommand.COMMAND_NAME, ExitCommand.class);
        registCommand(BatchCommand.COMMAND_NAME, BatchCommand.class);
        registCommand(WaitAndSayHello.COMMAND_NAME, WaitAndSayHello.class);
    }

    public static synchronized CommandManager getIntance() {
        if (commandManager == null) {
            commandManager = new CommandManager();
        }
        return commandManager;
    }

    public ICommand getCommand(String commandName) {
        if (COMMANDS.containsKey(commandName.toUpperCase())) {
            try {
                return COMMANDS.get(commandName.toUpperCase()).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                return new ErrorCommand();
            }
        } else {
            return new NotFoundCommand();
        }
    }

    public void registCommand(String commandName, 
            Class&lt;? extends ICommand&gt; command) {
        COMMANDS.put(commandName.toUpperCase(), command);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Commandos: </strong>Las siguientes clases representan las implementaciones de los comandos que tendremos disponibles en la aplicación, los cuales fueron registrados en el constructor de CommandManager. Las clases siguientes representan los comandos que analizamos en la figura 2.</p>
<p><strong>Clase ExitCommand: </strong>Comandos que termina con la aplicación. Este comando implementa <em><strong>ICommand</strong> </em>por lo que representa unos de los comandos más simples de la aplicación.<strong><br />
</strong></p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Clase ExitCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import javamex.patronesdiseño.command.ICommand;

public class ExitCommand implements ICommand {

    public static final String COMMAND_NAME = "exit";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        System.exit(0);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Clase BaseCommand: </strong>Esta clase implementa ICommand, sin embargo no es como tal un comando ya que es una <strong><em>Clase Abstracta</em></strong>, Esta clase fue diseñado como ejemplo para servir como una base para los demás comandos que imprimen un mensaje en pantalla, esta clase únicamente agrega el método <strong><em>write, </em></strong>El cual es utilizados para que todos los comandos impriman en pantalla los mensajes de una forma controlada, ya que si decidimos cambiar la forma que se escribe solo tendremos que cambiar este método y todas las clases que la heredan serán afectadas.</p>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase BaseCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import javamex.patronesdiseño.command.ICommand;

public abstract class BaseCommand implements ICommand {

    @Override
    public abstract String getCommandName();

    @Override
    public abstract void execute(String[] args, OutputStream out);

    public void write(OutputStream out, String message) {
        try {
            out.write(message.getBytes());
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}</pre>
<p>&nbsp;</p>
<p style="text-align: justify;"><strong>Clase DirCommand: </strong>Comando que nos permite crear o borrar una carpeta de nuestro FileSytem, el comando recibe como parámetro la operación a realizar (crear o borrar {-N|-D}) más la ruta de la carpeta.</p>
<pre class="theme:idle font:consolas lang:java decode:true" title="Clase DirCommand">package javamex.patronesdiseño.command.impl;

import java.io.File;

import java.io.OutputStream;

import java.nio.channels.WritableByteChannel;

public class DirCommand extends BaseCommand {

    public static final String COMMAND_NAME = "dir";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        if (args == null || args.length &lt; 2) {
            write(out, COMMAND_NAME + " argumentos insuficientes");
        }
        String operation = args[0];
        if ("-D".equals(operation.toUpperCase())) {
            write(out, deleteDir(args[1]));
        } else if ("-N".equals(operation.toUpperCase())) {
            write(out, newDir(args[1]));
        } else {
            write(out, "Se esperaba una operación correcta -d | -n");
        }
    }

    private String deleteDir(String url) {
        try {
            File file = new File(url);
            if (!file.exists()) {
                return "El archivo no existe";
            }
            if (!file.canWrite()) {
                return "Privilegios insuficientes";
            }
            file.delete();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String newDir(String url) {
        try {
            File file = new File(url);
            if (file.exists()) {
                return "El archivo ya existe";
            }
            file.mkdirs();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }
}</pre>
<p>&nbsp;</p>
<p><strong>FileCommand: </strong>Comando que nos permitirá realizar operaciones con archivos, las operaciones son las siguientes:</p>
<ul>
<li><strong>WRITE_APPEND = -WA:</strong> Permite escribir en un archivo conservando el contenido existente previamente. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo el contenido a escribir<strong><br />
</strong></li>
<li><strong>WRITE_OVERRIDE = -WO: </strong>Permite escribir en un archive sobrescribiendo su contenido. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo el contenido a escribir.<strong><br />
</strong></li>
<li><strong>WRITE_NEW = -WN: </strong>Permite crear un archive y luego escribir en él. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo el contenido a escribir. <strong><br />
</strong></li>
<li><strong>RENAME_FILE = -R: </strong>Permite renombrar un archive existente. Recibe dos parámetros, el primero corresponde al path del archivo y el segundo corresponde al nuevo nombre.<strong><br />
</strong></li>
<li><strong>DELETE_FILE = -D: </strong>Permite borrar un archive. Recibe únicamente el path del archivo a eliminar.<strong><br />
</strong></li>
</ul>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase FileCommand">package javamex.patronesdiseño.command.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.util.Arrays;

public class FileCommand extends BaseCommand {

    public static final String COMMAND_NAME = "file";
    private static final String WRITE_APPEND = "-WA";
    private static final String WRITE_OVERRIDE = "-WO";
    private static final String WRITE_NEW = "-WN";
    private static final String RENAME_FILE = "-R";
    private static final String DELETE_FILE = "-D";

    @Override
    public void execute(String[] args, OutputStream out) {
        if (args.length &lt; 2) {
            write(out, "Parametros insuficientes");
            return;
        }
        String operation = args[0].toUpperCase();
        String[] reduce = Arrays.copyOfRange(args, 1, args.length);
        if (WRITE_APPEND.equals(operation)) {
            write(out, writeAppend(reduce));
        } else if (WRITE_NEW.equals(operation)) {
            write(out, writeNew(reduce));
        } else if (WRITE_OVERRIDE.equals(operation)) {
            write(out, writeOverride(reduce));
        } else if (RENAME_FILE.equals(operation)) {
            write(out, renameFile(reduce));
        } else if (DELETE_FILE.equals(operation)) {
            write(out, deleteFile(reduce));
        } else {
            write(out, "No se encontro la operacion {" + WRITE_APPEND + "|" + WRITE_NEW + "|" + WRITE_OVERRIDE + "|" + RENAME_FILE + "|DELETE_FILE}");
        }
    }

    private String renameFile(String[] args) {
        String filePath = args[0];
        String newFileName = args[1];
        try {
            File file = new File(filePath);
            file.renameTo(new File(newFileName));
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String writeOverride(String[] args) {
        String filePath = args[0];
        String fileContent = args[1];
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                if (!file.createNewFile()) {
                    return "ERROR: Error al crear el archivo";
                }
            }
            FileWriter fileW = new FileWriter(file);
            fileW.write(fileContent.toCharArray());
            fileW.flush();
            fileW.close();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String writeAppend(String[] args) {
        String filePath = args[0];
        String fileContent = args[1];
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                return "ERRRO: El archivo no existe";
            }
            FileWriter fileW = new FileWriter(file, true);
            fileW.append(fileContent);
            fileW.flush();
            fileW.close();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String writeNew(String[] args) {
        String filePath = args[0];
        String fileContent = args[1];
        try {
            File file = new File(filePath);
            if (file.exists()) {
                return "ERRRO: El archivo ya existe";
            }
            if (!file.createNewFile()) {
                return "ERROR: No fué posible crear el archivo";
            }
            FileWriter fileW = new FileWriter(file);
            fileW.write(fileContent.toCharArray());
            fileW.flush();
            fileW.close();
            return "";
        } catch (Exception e) {
            return "ERROR: " + e.getMessage();
        }
    }

    private String deleteFile(String[] args) {
        String filePath = args[0];
        File file = new File(filePath);
        if (!file.delete()) {
            return "No fué posible eliminar el archivo";
        }
        return "";
    }

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }
}</pre>
<p>&nbsp;</p>
<p><strong>EchoCommand: </strong>Comando que únicamente imprime en pantalla lo que se escribe. Como un Eco.</p>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase EchoCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import java.util.Arrays;

public class EchoCommand extends BaseCommand {

    public static final String COMMAN_NAME = "echo";

    @Override
    public void execute(String[] args, OutputStream out) {
        String message = getCommandName() + " " + Arrays.toString(args);
        write(out, message);
    }

    @Override
    public String getCommandName() {
        return COMMAN_NAME;
    }
}</pre>
<p>&nbsp;</p>
<p><strong>DateCommand: </strong>Comando que nos permite conocer la fecha y hora del sistema en el formato que deseemos. El comando únicamente recibe como entrada el formato en el que queremos ver la fecha y hora.</p>
<pre class="theme:idle font:consolas lang:java decode:true " title="Clase DateTimeCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateTimeCommand extends BaseCommand {

    public static final String COMMAND_NAME = "date";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        SimpleDateFormat dateFormater = null;
        if (args == null) {
            dateFormater = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
        } else {
            try {
                dateFormater = new SimpleDateFormat(args[0]);
            } catch (Exception e) {
                write(out, "formato invalido");
                return;
            }
        }
        String date = dateFormater.format(new Date());
        write(out, date);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>MemoryCommand: </strong>Comando sin parámetros que nos arroja la información de la memoria que utiliza nuestra aplicación.</p>
<pre class="lang:java decode:true" title="Clase MemoryCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public class MemoryCommand extends BaseCommand {

    public static final String COMMAN_NAME = "memory";

    @Override
    public String getCommandName() {
        return COMMAN_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        double heap = Runtime.getRuntime().totalMemory() / 1000000d;
        double heapMax = Runtime.getRuntime().maxMemory() / 1000000d;
        double heapFree = Runtime.getRuntime().freeMemory() / 1000000d;
        String salida = "Heap: " + heap + "nMax Heap: " 
                + heapMax + "nFree Heap: " + heapFree;
        write(out, salida);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>BatchCommand: </strong>Commando complejo que nos permite abrir un archivo de comandos, este archivo es parecido a los archivos en batch ya que podemos escribir un conjunto de comandos que serán ejecutados en el orden en el que se encuentran en el archivo(Se asume que cada línea es un comando). El comando únicamente recibe como parámetro el Path del archivo a ejecutar.</p>
<pre class="lang:java decode:true" title="Clase BatchCommand">package javamex.patronesdiseño.command.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.Arrays;
import javamex.patronesdiseño.command.CommandManager;
import javamex.patronesdiseño.command.CommandUtil;
import javamex.patronesdiseño.command.ICommand;

public class BatchCommand extends BaseCommand {

    public static final String COMMAND_NAME = "batch";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        if (args == null || args.length &lt; 1) {
            write(out, "Número de parametros invalido");
            return;
        }
        CommandManager manager = CommandManager.getIntance();
        String[] lines = readLinesFromFile(args[0]);
        for (String line : lines) {
            String[] argsCommand = CommandUtil.tokenizerArgs(line);
            ICommand command = manager.getCommand(argsCommand[0]);
            String[] reduce = Arrays.copyOfRange(argsCommand, 1, argsCommand.length);
            command.execute(reduce, out);
            write(out, "n");
        }
        write(out, "Batch executado");
    }

    private String[] readLinesFromFile(String filePath) throws RuntimeException {
        File file = new File(filePath);
        FileInputStream stream = null;
        try {
            if (!file.exists()) {
                throw new RuntimeException("Archivo no encotrado");
            }
            stream = new FileInputStream(file);
            byte[] byteArray = new byte[stream.available()];
            stream.read(byteArray);
            String commands = new String(byteArray);
            String[] lines = commands.split("n");
            return lines;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            try {
                stream.close();
            } catch (Exception e2) {}
        }
    }
}</pre>
<p>&nbsp;</p>
<p><strong>AsyncCommand: </strong>Esta clase al igual que <strong><em>BaseCommand</em></strong> no es como tal un comando ya que es una <strong><em>Clase Abstract</em></strong>, esta clase tiene como propósito demostrar que podemos implementar comandos que se ejecuten en segundo plano o de forma asíncrona.</p>
<p>Esta clase agrega el método <strong><em>executeOnBackground</em></strong> en el cual deberemos implementar la funcionalidad que deseamos que realice el comando. Ya que el método original <strong><em>execute</em></strong> es sobre escritor para ejecutar el método <strong><em>executeOnBackground</em></strong> en un hilo independiente.</p>
<pre class="lang:java decode:true " title="Clase AsyncCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public abstract class AsyncCommand extends BaseCommand {

    public void execute(final String[] args, final OutputStream out) {
        new Thread(new Runnable() {
            public void run() {
                executeOnBackground(args, out);
            }
        }).start();
    }

    public abstract void executeOnBackground(String[] args, OutputStream out);
}</pre>
<p>&nbsp;</p>
<p>Clase WaitAndSeyHello: Comando que extiende de AsyncCommand, lo cual lo convierte automáticamente en un comando que se ejecuta en segundo plano. Ha este comando únicamente se le envía un tiempo en milisegundos, el cual lo utilizara para esperar este tiempo antes de decir Hello! .</p>
<pre class="lang:java decode:true " title="clase WaitAndSayHello">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public class WaitAndSayHello extends AsyncCommand {

    public static final String COMMAND_NAME = "waithello";

    @Override
    public void executeOnBackground(String[] args, OutputStream out) {
        if (args == null || args.length &lt; 1) {
            write(out, "Parametros insuficientes");
            return;
        }
        Long time = null;
        try {
            time = Long.parseLong(args[0]);
        } catch (Exception e) {
            write(out, "Tiempo inválido");
            return;
        }

        try {
            Thread.sleep(time.longValue());
            write(out, "Hello!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Clase ErrorCommand:</strong> Este comando no esté definido en nuestro diagrama y es utilizado por el CommandManager únicamente para regresar un Error al intentar instanciar un comando. Este comando no puede ser ejecutado por el cliente ya que no es un comando registrado, sin embargo CommandManager lo maneja como un comando propio del sistema para representa un error.</p>
<pre class="lang:java decode:true " title="Clase ErrorCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

import java.nio.channels.WritableByteChannel;

public class ErrorCommand extends BaseCommand {

    private static final String COMMAND_NAME = "ERROR";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        String message = "Error al invokar el comando";
        write(out, message);
    }
}</pre>
<p>&nbsp;</p>
<p><strong>Clase NotFoundCommand: </strong>Comando parecido a ErrorCommand pero este es regresado cuando un comando no es encontrado.</p>
<pre class="lang:java decode:true " title="Clase NotFoundCommand">package javamex.patronesdiseño.command.impl;

import java.io.OutputStream;

public class NotFoundCommand extends BaseCommand {

    private static final String COMMAND_NAME = "NOT FOUND";

    @Override
    public String getCommandName() {
        return COMMAND_NAME;
    }

    @Override
    public void execute(String[] args, OutputStream out) {
        write(out, "Commando no encontrado");
    }
}</pre>
<p>&nbsp;</p>
<p>Otra clase que se utiliza es <strong><em>CommandUtil, </em></strong>la cual la utilizamos únicamente para procesar los datos tecleados por el usuario y dividir las instrucciones en tokens, los tokes pueden ser el nombre del comando y los parámetros. La regla que se sigue para dividir los comandos es la siguiente.</p>
<p>Cada palabra separada por un espacio es considera como un token a excepción que se encuentre en medio de comillas dobles, ejemplo &#8220;Hola Mundo&#8221;, en este caso toda la oración es considera un único token.</p>
<pre class="lang:java decode:true " title="Clase CommandUtil">package javamex.patronesdiseño.command;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

public class CommandUtil {

    public static String[] tokenizerArgs(String args) {
        List&lt;String&gt; tokens = new ArrayList&lt;String&gt;();
        char[] charArray = args.toCharArray();
        String contact = "";
        boolean inText = false;
        for (char c : charArray) {
            if (c == ' ' &amp;&amp; !inText) {
                if (contact.length() != 0) {
                    tokens.add(contact);
                    contact = "";
                }
            } else if (c == '"') {
                if (inText) {
                    tokens.add(contact);
                    contact = "";
                    inText = false;
                } else {
                    inText = true;
                }
            } else {
                contact += c;
            }
        }
        if (contact.trim().length() != 0) {
            tokens.add(contact.trim());
        }
        String[] argsArray = new String[tokens.size()];
        argsArray = tokens.toArray(argsArray);
        return argsArray;

    }
}</pre>
<p>&nbsp;</p>
<p>Hasta este momento ya tenemos definidos el CommandaManager y todos los comandos que utilizaremos, sin embargo no tenemos un mecanismo que nos ayude interactuar con los comandos, para eso tenemos la clase <strong><em>CommandMain</em></strong>, la cual servirá de invoker, Esta clase se cicla para solicitar al usuario comandos desde la consola.</p>
<pre class="lang:java decode:true " title="Clase CommandMain">package javamex.patronesdiseño.command;

import java.util.Arrays;
import java.util.Scanner;

public class CommandMain {

    public static void main(String[] args) {
        System.out.println("Command Line is Start");
        CommandManager manager = CommandManager.getIntance();
        Scanner in = new Scanner(System.in);
        while (true) {
            String line = in.nextLine();
            if ("EXIT".equals(line.toUpperCase())) {
                System.exit(0);
            }
            if (line.trim().length() == 0) {
                continue;
            }
            String[] commands = CommandUtil.tokenizerArgs(line);
            String commandName = commands[0];
            String[] commandArgs = null;
            if (commands.length &gt; 1) {
                commandArgs = Arrays.copyOfRange(commands, 1, commands.length);
            }
            ICommand command = manager.getCommand(commandName);
            command.execute(commandArgs, System.out);
            System.out.println("");
        }
    }
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><figure id="attachment_2333" aria-describedby="caption-attachment-2333" style="width: 648px" class="wp-caption aligncenter"><a href="https://reactiveprogramming.io/books/design-patterns/es" target="_blank" rel="noopener"><img loading="lazy" class="wp-image-2333 size-large" src="https://www.oscarblancarteblog.com/wp-content/uploads/2018/09/patrones-diseño-banner-1024x392.jpg" alt="Introducción a los patrones de diseño" width="648" height="248" /></a><figcaption id="caption-attachment-2333" class="wp-caption-text">¿Quieres aprender más patrones de diseño como este? te invito a que veas mi libro.</figcaption></figure></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><span style="font-size: 14pt;"><strong>Ejecución:<br />
</strong></span></h2>
<p>Finalmente, ya tenemos listo todo, por lo que comenzaremos ejecutando la aplicación y tendremos como resultado lo siguiente:</p>
<p><figure style="width: 703px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise4.png" alt="Patrón de diseño Command" width="703" height="279" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Iniciaremos ejecutando el comando <strong><em>date </em></strong>y le pediremos que nos arroje la fecha en el formato &#8220;DD/MM/YYYY&#8221;, seguido le pediremos la hora en el formato &#8220;HH:MM:SS&#8221; y finalmente le pediremos fecha y hora el formato &#8220;DDMMYYYY HHMMSS&#8221; para lo cual utilizaremos la nomenclatura estándar de java para la fecha y hora la cual podremos apreciar en la siguiente pagina <a href="https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html">https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html</a>.</p>
<p><figure style="width: 703px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise5.png" alt="Patrón de diseño Command" width="703" height="238" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Para el siguiente ejemplo, utilizaremos el comando <strong><em>Dir </em></strong>para crear un nuevo directorio y luego lo borraremos.</p>
<p><figure style="width: 710px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise6.png" alt="Patrón de diseño Command" width="710" height="270" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>&nbsp;</p>
<p><figure style="width: 722px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise7.png" alt="Patrón de diseño Command" width="722" height="308" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Para el siguiente ejemplo utilizaremos el comando <strong><em>echo</em></strong> para decir &#8220;Hola Mundo&#8221;.</p>
<p><figure style="width: 678px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise8.png" alt="Patrón de diseño Command" width="678" height="327" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Para el siguiente ejemplo utilizaremos el comando <strong><em>File</em></strong> para crear un nuevo archivo de texto y escribir en el <strong>&#8220;Hola Mundo&#8221; </strong></p>
<p><figure style="width: 715px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise9.png" alt="Patrón de diseño Command" width="715" height="261" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>El siguiente comando a utilizar es <strong><em>Memory, </em></strong>El cual nos dará datos acerca de la memoria de la aplicación.</p>
<p><figure style="width: 607px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise10.png" alt="Patrón de diseño Command" width="607" height="340" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Utilizaremos nuevamente el comando <strong><em>File </em></strong>para renombrar el archivo dummy.txt a helloword.txt</p>
<p><figure style="width: 739px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise11.png" alt="Patrón de diseño Command" width="739" height="231" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Hasta aquí, solamente hemos ejecutado comandos síncronos, pero en este ejemplo ejecutaremos el comando WaitAndSeyHello, el cual lo ejecutaremos y le diremos que espere 10 segundos antes de decir Hello!.</p>
<p><figure style="width: 633px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise12.png" alt="Patrón de diseño Command" width="633" height="283" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p style="text-align: center;">Después de esperar 10 segundos tenemos el siguiente resultado.</p>
<p><figure style="width: 640px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise13.png" alt="Patrón de diseño Command" width="640" height="290" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>En el siguiente ejemplo ejecutaremos el comando <strong><em>Batch </em></strong>el cual lee un archivo de texto y ejecuta todos los comandos que tenemos en el, para este ejemplo ejecutaremos el comando y le diremos que lea un archivo en la ruta c:/dummy/batch.txt el cual tendrá el siguiente contenido:</p>
<pre class="lang:sh decode:true ">date dd/MM/yyyy hh:mm:ss
dir -n "c:/dummy/dummy2"
echo "Se creo el archivo dummy2"
file -wn "c:/dummy/dummy2/dummy.txt" "Hola mundo con el comando file"
memory
file -r "c:/dummy/dummy2/dummy.txt" "c:/dummy/dummy2/dummy2.txt"
date dd/MM/yyyy hh:mm:ss</pre>
<p>&nbsp;</p>
<p>Lo que esperemos que realice el comando es lo siguiente: imprime la fecha y hora, cree el directorio c:/dummy/dummy2, escriba en pantalla Se creó el archivo dummy2&#8243;, cree un archivo en &#8220;c:/dummy/dummy2/dummy.txt&#8221; con el contenido &#8220;Hola mundo con el comando file&#8221;, imprima en pantalla los datos de la memoria, renombre el archivo que acabamos de crear y le ponga de nombre dummy2.txt y finalmente imprima nuevamente la fecha y hora.</p>
<p><figure style="width: 661px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise14.png" alt="Patrón de diseño Command" width="661" height="219" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p style="text-align: center;"><strong> </strong></p>
<p>Otra cosa que podemos intentar es ejecutar un comando que no existe, por ejemplo &#8220;java&#8221;, el cual nos indicara que no fue encontrado.</p>
<p><figure style="width: 665px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise15.png" alt="Patrón de diseño Command" width="665" height="298" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Finalmente ejecutamos el comando <strong><em>Exit</em></strong>, el cual terminara con la aplicación.</p>
<p><figure style="width: 670px" class="wp-caption aligncenter"><img loading="lazy" class="" src="http://www.oscarblancarteblog.com/wp-content/uploads/2014/11/111814_2343_patrndedise16.png" alt="Patrón de diseño Command" width="670" height="301" /><figcaption class="wp-caption-text">Resultado de la ejecución</figcaption></figure></p>
<p>Hasta este punto ya habremos creado una consola que es capaz de ejecutar comandos, los cuales serán ejecutados sin saber realmente que clase está realizando el trabajo, sin embargo en la vida real no nos interés saber cómo es atendido un comando siempre y cuando realice la tarea que esperamos que realice. Y como ya vimos con el patrón de diseño Command esto es posible.</p>
<p>Ya con esta base tú podrás crear nuevos comandos y registrarlos al CommandManager para que los puedes utilizar en tu consola, también podrías crear un comando que se encargue de registrar nuevos comandos desde algún Jar para que esté disponible desde la consola. O podrías modificar la forma en la carga los comandos al inicio para que lea algún archivo de configuración.</p>
<p>Acabamos de ver uno de los muchos aplicativos que tiene el Patrón de diseño Command, Si tú tienes alguna experiencia con este patrón por favor coméntala.</p>
<p>&nbsp;</p>
<p>Ya está a la venta mi nuevo libro &#8220;<a href="http://www.oscarblancarteblog.com/libros/introduccion-los-patrones-diseno/">Introducción a los patrones de diseño</a>&#8220;, en donde expongo los 25 patrones de diseño más utilizados y explicados desde un enfoque del mundo real, con ejemplos que pueden ser aplicados en tus proyectos. Sin duda es unos de los libros más completos de patrones de diseño en español.		</p>
<p>The post <a rel="nofollow" href="https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/">Patrón de diseño Command</a> appeared first on <a rel="nofollow" href="https://www.oscarblancarteblog.com">Oscar Blancarte - Software Architecture</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.oscarblancarteblog.com/2014/11/19/patron-de-diseno-command/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">427</post-id>	</item>
	</channel>
</rss>
