<?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/"
	>

<channel>
	<title>HAT Blog</title>
	<atom:link href="http://blog.hexacta.com/hat/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hexacta.com/hat</link>
	<description></description>
	<lastBuildDate>Tue, 21 May 2013 16:16:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Agregando funcionalidad a objetos de dominio en Grails</title>
		<link>http://blog.hexacta.com/hat/agregando-funcionalidad-a-objetos-de-dominio-en-grails/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=agregando-funcionalidad-a-objetos-de-dominio-en-grails</link>
		<comments>http://blog.hexacta.com/hat/agregando-funcionalidad-a-objetos-de-dominio-en-grails/#comments</comments>
		<pubDate>Tue, 21 May 2013 16:16:22 +0000</pubDate>
		<dc:creator>emalvino</dc:creator>
				<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[ORM]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=3230</guid>
		<description><![CDATA[En este post vamos a ver algunos conceptos interesantes de Grails y Groovy que podemos aplicar en nuestros objetos de dominio, y un ejemplo práctico para implementar auditoria a nuestras entidades de dominio. Mixins Los mixins se usan para poder inyectar el comportamiento (métodos) de una o más clases en otra. Normalmente los usamos con el annotation @Mixin: [groovy] class Bird { def fly(){ &#8220;Flying!&#8221; } } class Fish { def swim(){ &#8220;Swiming!&#8221; } } @Mixin([Bird, Fish]) class Duck{ String name def talk(){ &#8220;Cuack!&#8221; } } def duck = new Duck() assert &#8220;Flying!&#8221; == duck.fly() assert &#8220;Swiming!&#8221; == duck.swim() assert &#8220;Cuack!&#8221; == duck.talk() [/groovy] O también los podemos inyectar en runtime: [groovy] Duck.mixin Bird, Fish def duck = new Duck() [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/skynet-roomba-knife-earlyyears-terminator-13315954576.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/skynet-roomba-knife-earlyyears-terminator-13315954576-300x259.png" alt="" title="skynet-roomba-knife-earlyyears-terminator-13315954576" width="200" height="180" class="alignleft size-medium wp-image-3232" /></a>En este post vamos a ver algunos conceptos interesantes de Grails y Groovy que podemos aplicar en nuestros objetos de dominio, y un ejemplo práctico para implementar auditoria a nuestras entidades de dominio.<br />
<span id="more-3230"></span></p>
<h1>Mixins</h1>
<p>Los mixins se usan para poder inyectar el comportamiento (métodos) de una o más clases en otra.<br />
Normalmente los usamos con el annotation @Mixin:<br />
[groovy]<br />
class Bird {<br />
	def fly(){<br />
		&#8220;Flying!&#8221;<br />
	}<br />
}</p>
<p>class Fish {<br />
	def swim(){<br />
		&#8220;Swiming!&#8221;<br />
	}<br />
}</p>
<p>@Mixin([Bird, Fish])<br />
class Duck{<br />
	String name</p>
<p>	def talk(){<br />
		&#8220;Cuack!&#8221;<br />
	}<br />
}</p>
<p>def duck = new Duck()<br />
assert &#8220;Flying!&#8221; == duck.fly()<br />
assert &#8220;Swiming!&#8221; == duck.swim()<br />
assert &#8220;Cuack!&#8221; == duck.talk()<br />
[/groovy]</p>
<p>O también los podemos inyectar en runtime:<br />
[groovy]<br />
Duck.mixin Bird, Fish</p>
<p>def duck = new Duck()<br />
assert &#8220;Flying!&#8221; == duck.fly()<br />
assert &#8220;Swiming!&#8221; == duck.swim()<br />
assert &#8220;Cuack!&#8221; == duck.talk()<br />
[/groovy]</p>
<p>De esta manera podríamos implementar herencia múltiple en Java.</p>
<pre>[Insertar 5 páginas de discusión sobre herencia múltiple aquí]</pre>
<p>Que pasa si en un método del mixin queremos hacer referencia a un método o propiedad de la clase que lo implementa? Por ejemplo usar la propiedad name de Duck en el método fly. Quizás pensemos desde el mixin ejecutar super.name, pero siendo que no es una herencia, super no lleva a Duck.<br />
Lo que hacemos es escribir los métodos del mixin como closures y dentro de los mismos podemos usar <strong>delegate </strong>para acceder a la clase en cuyo contexto esta corriendo el closure, en este caso Duck:<br />
[groovy]<br />
class Bird {<br />
	def fly = {<br />
		&#8220;Flying ${delegate.name}!&#8221;<br />
	}<br />
}</p>
<p>&#8230;</p>
<p>def duck = new Duck(name: &#8220;Duckie&#8221;)<br />
assert &#8220;Flying Duckie!&#8221; == duck.fly()<br />
[/groovy]</p>
<h1>Embedded</h1>
<p>Embedded es una propiedad estática de las clases de dominio de Grails, la cual nos permite desnormalizar algunas propiedades en la base de datos.<br />
Esto no afecta al modelo de objetos, las propiedades siguen siendo accedidas a través de la relación con la otra clase.<br />
[groovy]<br />
class Lake{<br />
	def address<br />
}</p>
<p>class Duck{<br />
	String name<br />
	Lake lake<br />
	static embedded = ['lake']<br />
}<br />
[/groovy]</p>
<p>Esto generaría la tabla DUCK con las columnas: NAME y LAKE_ADDRESS.<br />
Aun así se accedería a la dirección como duck.lake.address.</p>
<h1>Delegate</h1>
<p>Delegate nos permite muy fácilmente implementar un wrapper de un objeto. Simplemente agregamos el annotation @Delegate delante de la propiedad que hace referencia a otra clase, y de esta manera todos los llamados a los métodos de la clase referenciada se delegan a esta:<br />
[groovy]<br />
class Nest{<br />
	int eggs<br />
}</p>
<p>class Duck{<br />
	@Delegate Nest nest<br />
}</p>
<p>def nest = new Nest(eggs: 3)<br />
def duck = new Duck(nest: nest)<br />
assert 3 == duck.eggs<br />
[/groovy]</p>
<h1>Eventos de GORM</h1>
<p>Si bien se usa Hibernate como implementación de ORM y tenemos acceso a los eventos del mismo, Grails ademas expone sus propios eventos de ORM para implementar:</p>
<ul>
<li>beforeInsert</li>
<li>beforeUpdate</li>
<li>beforeDelete</li>
<li>beforeValidate</li>
<li>afterInsert</li>
<li>afterUpdate</li>
<li>afterDelete</li>
<li>onLoad</li>
</ul>
<p>Es importante aclarar que se ejecutan los eventos mientras se hace un flush de la transacción de Hibernate. Para persistir cualquier cambio en otro objeto es necesario abrir otra transacción usando el método withNewSession. Por ejemplo:<br />
[groovy]<br />
class Duck {<br />
	String name<br />
	String type<br />
	def beforeInsert(){<br />
		type = &#8220;Baby duck&#8221;<br />
		Notification.withNewSession {<br />
			new Notification(message: &#8220;New baby duck is born!&#8221;).save()<br />
		}<br />
	}<br />
}<br />
[/groovy]</p>
<h1>Llevándolo a la práctica</h1>
<p>Vamos a ver un ejemplo real para implementar información de auditoria en una clase de dominio, usando algunas de estas funcionalidades. La idea es agregar las propiedades modificationDate y modificationUser cada vez que se crea o actualiza una entidad. Normalmente haríamos algo como:<br />
[groovy]<br />
class Duck {<br />
	String name</p>
<p>	// Auditory code<br />
	Date modificationDate<br />
	User modificactionUser</p>
<p>	def beforeUpdate() {<br />
		modificationDate = new Date()<br />
		User.withNewSession {<br />
			modificationUser = userService.getCurrentUser()<br />
		}<br />
	}<br />
}<br />
[/groovy]<br />
Pero esto no seria reusable, tendríamos que repetir la misma lógica en cada entidad que queramos hacer auditable.<br />
Aprovechando lo que vimos podemos definir 2 clases mas:<br />
[groovy]<br />
class UpdateData {<br />
	Date modificationDate<br />
	User modificactionUser<br />
}</p>
<p>class Auditable {<br />
	def beforeUpdate = {<br />
		delegate.modificationDate = new Date()<br />
		User.withNewSession {<br />
			delegate.modificationUser = userService.getCurrentUser()<br />
		}<br />
	}<br />
}<br />
[/groovy]</p>
<p>Y de esta manera podemos reusar esta lógica en otras clases de dominio:</p>
<p>[groovy]<br />
@Mixin(Auditable)<br />
class Duck {<br />
	String name</p>
<p>	// Auditory code<br />
	@Delegate UpdateData updateData = new UpdateData()<br />
	static transients = ['updateData']<br />
}<br />
[/groovy]</p>
<p>Nota: Agregamos la propiedad updateData como transient para que no intente crear una relación entre ambas clases. Solo queremos incluir las propiedades de UpdateData en las entidades de dominio.<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/white_duck.jpg"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/white_duck-291x300.jpg" alt="" title="white_duck" width="291" height="300" class="aligncenter size-medium wp-image-3272" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/agregando-funcionalidad-a-objetos-de-dominio-en-grails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python / Django &#8211; Tips</title>
		<link>http://blog.hexacta.com/hat/python-django-tips/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=python-django-tips</link>
		<comments>http://blog.hexacta.com/hat/python-django-tips/#comments</comments>
		<pubDate>Thu, 16 May 2013 15:53:40 +0000</pubDate>
		<dc:creator>mperezvega</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=3200</guid>
		<description><![CDATA[La idea general de este post es generar una serie de tips o recomendaciones dadas por haber transitado por un proyecto en estas tecnologías. Este blog no pretende enseñar a usar django ni python, para eso existen un montón de sitios que lo hacen muy bien. Simplemente se pretende recomendar algunas cuestiones relacionadas con el ambiente de desarrollo y decisiones generales. virtualenv virtualenv es una herramienta para la gestión de las distintas versiones de python que se puedan necesitar. Te permite tener distintos ambientes configurados dentro de una misma máquina, pudiendo switchear entre ellos y probar el mismo proyecto con distintas versiones de python, django o cualquier otra librería. [bash]sudo pip install virtualenv virtualenvwrapper[/bash] A modo ejemplo defino que para [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/python-django.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/python-django-300x123.png" alt="" width="300" height="123" class="alignnone size-medium wp-image-3211" /></a></p>
<p>La idea general de este post es generar una serie de tips o recomendaciones dadas por haber transitado por un proyecto en estas tecnologías.</p>
<p>Este blog no pretende enseñar a usar django ni python, para eso existen un montón de sitios que lo hacen muy bien. Simplemente se pretende recomendar algunas cuestiones relacionadas con el ambiente de desarrollo y decisiones generales.<br />
<span id="more-3200"></span></p>
<h3><strong>virtualenv</strong></h3>
<p>virtualenv es una herramienta para la gestión de las distintas versiones de python que se puedan necesitar.<br />
Te permite tener distintos ambientes configurados dentro de una misma máquina, pudiendo switchear entre ellos y probar el mismo proyecto con distintas versiones de python, django o cualquier otra librería. </p>
<p>[bash]sudo pip install virtualenv virtualenvwrapper[/bash]<br />
A modo ejemplo defino que para un proyecto dado (prrac) se utilizará la versión 2.6 de python (por defecto Ubuntu tiene la 2.7):<br />
[bash]virtualenv prrac &#8211;python=/usr/bin/python2.6 &#8211;distribute[/bash]<br />
y luego la utilizo:<br />
[bash]workon prrac[/bash]<br />
<a href="http://www.virtualenv.org/en/latest/" title="viertualenv" target="_blank">Más Info</a></p>
<h3><strong>pip</strong></h3>
<p>pip es una herramienta para la gestión de las librerías de python, actualmente tiene alrededor de 30.000 librerías.<br />
Es de muy fácil instalación y de muy fácil uso:<br />
[bash]sudo apt-get install python-pip python-dev build-essential[/bash]<br />
Y luego por ejemplo:<br />
[bash]pip install simplejson[/bash]<br />
[bash]pip install mock[/bash]<br />
[bash]pip install django[/bash]<br />
[bash]pip install django-facebook-api[/bash]<br />
<a href="http://www.pip-installer.org/en/latest/" title="pip" target="_blank">Más Info</a></p>
<h3><strong>PyCharm</strong></h3>
<p>PyCharm no tiene nada que envidiarle a eclipse para java, y sin duda es muy superior a cualquier plugin que éste último pudiera incorporar.<br />
<a href="http://www.jetbrains.com/pycharm/features/index.html" title="PyCharm" target="_blank">Más Info</a></p>
<h3><strong>South</strong></h3>
<p>Si alguien quisiera llevar en todo momento el versionado de la base de datos sincronizado con el código, ésta es la herramienta.<br />
<a href="http://south.readthedocs.org/" title="South" target="_blank">Más Info</a></p>
<h3><strong>ipython</strong></h3>
<p>Es un plugin para agregarselo a la consola de django en la cual se puede ejecutar código python y utilizar la base de datos con el modelo de negocio.<br />
<a href="http://ipython.org/" title="ipython" target="_blank">Más Info</a></p>
<h3><strong>REST + json</strong></h3>
<p>En líneas generales no existen archivos XML, si existen configuraciones y demás cuestiones, pero están en archivos de python .py.<br />
En caso de necesitar servicios web, si bien existen librerías para SOAP, lo más recomendado es utilizar REST + json.</p>
<h3><strong>Levantar el servidor en tan solo 3 segundos</strong></h3>
<p>Sacando ventaja de python como lenguaje interpretado, levantar el servidor &#8220;cuesta&#8221; 3 segundos, y si la aplicación creciera 100 veces, también seguiría costando lo mismo levantar el servidor. </p>
<p><strong>Resumen final:</strong> es sin duda una alternativa excelente para la construcción de aplicaciones web.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/python-django-tips/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grails &#8211; ABMs rápidos y sencillos</title>
		<link>http://blog.hexacta.com/hat/grails-abms-rapidos-y-sencillos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=grails-abms-rapidos-y-sencillos</link>
		<comments>http://blog.hexacta.com/hat/grails-abms-rapidos-y-sencillos/#comments</comments>
		<pubDate>Wed, 08 May 2013 15:44:31 +0000</pubDate>
		<dc:creator>Ariel Debernardi</dc:creator>
				<category><![CDATA[Grails]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=3108</guid>
		<description><![CDATA[Grails está muy relacionado con el concepto de scaffolding. Scaffolding es una técnica utilizada por algunos frameworks con arquitectura MVC en los cuales el desarrollador sólo debe especificar el dominio. El framework hace el resto: genera la base, las vistas y controladores para que la aplicación pueda realizar las operaciones CRUD sobre las entidades definidas. En Grails, generamos nuestro objeto de dominio con todos los atributos que el mismo necesita, como así también las constraints necesarias. A partir del mismo, generamos el controller, el cual sera la vía de comunicación con las vista (.gsp) . Al generar un controller, Grails crea una clase groovy de la entidad (&#60;nombreEntidad&#62;Controller.groovy) con los siguientes métodos, los cuales nos permite: List, ver un listado de la entidad. Show,  mostrar el detalla de una entidad. Create, crear la [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/Parthenon_scaffolding_2010_2.jpg"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/Parthenon_scaffolding_2010_2-300x223.jpg" alt="" title="Parthenon_scaffolding_2010_2" width="250" height="175" class="alignleft size-medium wp-image-3184" /></a>Grails está muy relacionado con el concepto de <a title="Scaffolding" href="http://en.wikipedia.org/wiki/Scaffold_(programming)" target="_blank">scaffolding</a>. Scaffolding es una técnica utilizada por algunos frameworks con arquitectura MVC en los cuales el desarrollador sólo debe especificar el dominio. El framework hace el resto: genera la base, las vistas y controladores para que la aplicación pueda realizar las operaciones CRUD sobre las entidades definidas.<br />
<span id="more-3108"></span><br />
En Grails, generamos nuestro <a href="http://grails.org/doc/latest/guide/GORM.html">objeto de dominio</a> con todos los atributos que el mismo necesita, como así también las <a href="http://www.grails.org/doc/2.2.x/ref/Constraints/Usage.html">constraints</a> necesarias. A partir del mismo, generamos el <a href="http://grails.org/doc/2.2.x/ref/Plug-ins/controllers.html">controller</a>, el cual sera la vía de comunicación con las vista (.gsp) . Al generar un controller, Grails crea una clase groovy de la entidad (&lt;nombreEntidad&gt;Controller.groovy) con los siguientes métodos, los cuales nos permite:</p>
<ul>
<li>List, ver un listado de la entidad.</li>
<li>Show,  mostrar el detalla de una entidad.</li>
<li>Create, crear la entidad.</li>
<li>Save, grabar una entidad por primera vez.</li>
<li>Edit, editar la entidad.</li>
<li>Update, grabar los cambios que realizamos en una entidad.</li>
<li>Delete, eliminar una entidad.</li>
</ul>
<p>Grails provee un template predefinido con el comportamiento que van a tener los ABMs y sus flujos de pantallas. Si se requiere que esto sea distinto (a nivel aplicación), una propuesta es <a title="Artifact and Scaffolding Templates" href="http://www.grails.org/Artifact+and+Scaffolding+Templates" target="_blank">cambiar esos templates</a>.</p>
<p>En lugar de eso, nuestra propuesta es crear unas pocas vistas y un controlador generales, que necesiten ser extendidos con un mínimo esfuerzo para cada nuevo ABM del sistema. Esto posibilita a su vez reunir el comportamiento común, y que sea fácil cambiarlo consistentemente a toda la aplicación.</p>
<p>El controlador mencionado, al cual nombramos ABMController, es una clase abstracta generada inicialmente a partir del template de controller de Grails, y que luego se fue generalizando para armar una jerarquía de controladores, que en principio sólo necesiten redefinir unos pocos y simples métodos abstractos. También se generaron otros métodos necesarios para todas las pantallas, fuera del estándar de Grails , como por ejemplo, exportar (nos permite a partir del uso de un <a href="http://grails.org/plugin/export">plugin</a>, exportar el contenido de la lista de la entidad a un documento .xls, pdf, entre otros). A continuación vemos el código principal de esta clase:</p>
<p>[groovy]<br />
abstract class ABMController implements GroovyObject {<br />
	static allowedMethods = [save: 'POST', update: 'POST', delete: 'POST']</p>
<p>	static final protected String LIST = &#8216;list&#8217;</p>
<p>	def exportService</p>
<p>	def excelExportService</p>
<p>	def filterPaneService</p>
<p>	def index() {<br />
		redirect(action: LIST, params: params)<br />
	}</p>
<p>	def list() {<br />
		if(!params.max) params.max = 10<br />
		if(!params.offset) params.offset = 0</p>
<p>		if(isExportacionRequerida()){<br />
			params.max = null</p>
<p>			if (params.filter) {<br />
				exportar(filterPaneService.filter(params, entidadClass))<br />
			} else {<br />
				exportar(entidadClass.findAll(params))<br />
			}<br />
		}<br />
		def parametros = [entidad: entidad, entidadClass: entidadClass, propiedades: propiedades]</p>
<p>		if (params.filter) {<br />
			parametros['listaEntidad'] = filterPaneService.filter( params, entidadClass )<br />
			parametros['cantEntidad'] = filterPaneService.count( params, entidadClass )<br />
			parametros['filtroParams'] = org.grails.plugin.filterpane.FilterPaneUtils.extractFilterParams(params)<br />
		} else {<br />
			parametros['listaEntidad'] = entidadClass.findAll(params)<br />
			parametros['cantEntidad'] = entidadClass.count()<br />
		}<br />
		beforeList(parametros['listaEntidad'])<br />
		renderList(parametros)<br />
	}</p>
<p>	/** Devuelve true si llega un request de exportacion de la tabla */<br />
	boolean isExportacionRequerida() {<br />
		params?.format &amp;&amp; params.format != &#8216;html&#8217;<br />
	}</p>
<p>	def exportar = { datosAExportar -&gt;<br />
		excelExportService.export(response, params, entidadClass, propiedades, entidad, datosAExportar)<br />
	}</p>
<p>	def create() {<br />
		beforeCreate()<br />
		def entidadInstance = entidadClass.newInstance(params)<br />
		renderCreate(entidadInstance)<br />
	}</p>
<p>	def edit(Long id) {<br />
		def entidadInstance = entidadClass.get(id)<br />
		if (!entidadInstance) {<br />
			setErrorMessage(&#8216;default.not.found.message&#8217;, id)<br />
			redirect(action: LIST, params: getRedirectParams())<br />
			return<br />
		}<br />
		beforeEdit()<br />
		renderEdit(entidadInstance)<br />
	}</p>
<p>	def save() {<br />
		def entidadInstance = entidadClass.newInstance(params)<br />
		beforeSave(entidadInstance)<br />
		if (!entidadInstance.save(flush: true)) {<br />
			renderCreate(entidadInstance)<br />
			return<br />
		}</p>
<p>		setInfoMessage(&#8216;default.created.message&#8217;, entidadInstance.id)<br />
		redirect(action: LIST, params: getRedirectParams())<br />
	}</p>
<p>	def update(Long id, Long version) {<br />
		def entidadInstance = entidadClass.get(id)<br />
		if (!entidadInstance) {<br />
			setErrorMessage(&#8216;default.not.found.message&#8217;, entidadInstance.id)<br />
			redirect(action: LIST, params: getRedirectParams())<br />
			return<br />
		}</p>
<p>		if (chequearConcurrencia(entidadInstance, version)) {<br />
			return<br />
		}</p>
<p>		entidadInstance.properties = params<br />
		beforeSave(entidadInstance)</p>
<p>		if (!entidadInstance.save(flush: true)) {<br />
			renderEdit(entidadInstance)<br />
			return<br />
		}</p>
<p>		setInfoMessage(&#8216;default.updated.message&#8217;, entidadInstance.id)<br />
		redirect(action: LIST, params: getRedirectParams())<br />
	}</p>
<p>	def delete(Long id) {<br />
		def entidadInstance = entidadClass.get(id)<br />
		if (!entidadInstance) {<br />
			setErrorMessage(&#8216;default.not.found.message&#8217;, id)<br />
			redirect(action: LIST, params: getRedirectParams())<br />
			return<br />
		}</p>
<p>		try {<br />
			entidadInstance.delete(flush: true)<br />
			setInfoMessage(&#8216;default.deleted.message&#8217;,id)<br />
			redirect(action: LIST, params: getRedirectParams())<br />
		}<br />
		catch (DataIntegrityViolationException e) {<br />
			setErrorMessage(&#8216;default.not.deleted.message&#8217;, id)<br />
			redirect(action: &#8216;edit&#8217;, id: id)<br />
		}<br />
	}<br />
	abstract protected List getPropiedades()</p>
<p>	abstract protected String getEntidad()</p>
<p>	abstract protected Class getEntidadClass()</p>
<p>	protected String getForm() {<br />
		&#8216;/forms/&#8217; + entidad<br />
	}</p>
<p>	private String getEntidadLabel() {<br />
		entidad + &#8216;.label&#8217;<br />
	}</p>
<p>	protected String getPlugin(){<br />
		&#8220;general&#8221;<br />
	}<br />
}<br />
[/groovy]</p>
<p>Para crear el ABM genérico definimos los métodos:</p>
<ul>
<li>comunes a todos los controller, como el list, create, save, edit, update y delete.</li>
<li>abstractos getPropiedades, getEntidad y getEntidadClass,</li>
<li>concretos getForm, getEntidadLabel y getPlugin</li>
</ul>
<p>Los controllers hijos que necesitan heredar dicha funcionalidad, deben definir ciertos métodos que son utilizados en la clase padre Por ende, debemos definir los métodos como</p>
<ul>
<li>getPropiedades: define los atributos de la clase entidad como string. Se envian al gsp para su utilización.</li>
<li>getEntidadClass(): es el .class utilizado para obtener todas las instancias de la entidad u obtener una única instancia enviada como parámetro desde el gsp, para su edición o eliminación.</li>
<li>getEntidad: string que se envía al gsp, para su utilización.</li>
<li>getPlugin (opcional) explicar cuando se debe usar.</li>
</ul>
<p>Luego, en nuestro caso, se generalizaron tres gsp:</p>
<ul>
<li>list.gsp</li>
<li>edit.gsp</li>
<li>create.gsp</li>
</ul>
<p>En el list.gsp, se definió para la cabecera un each que recorre las propiedades definidas en el getPropiedades:</p>
<p>[html]</p>
<p>&lt;thead&gt;<br />
	&lt;tr&gt;<br />
		&lt;g:each in=&#8221;${propiedades}&#8221; status=&#8221;i&#8221; var=&#8221;propiedad&#8221;&gt;<br />
			&lt;g:sortableColumn property=&#8221;${propiedad}&#8221;<br />
			title=&#8221;${message(code: entidad+&#8217;.'+propiedad+&#8217;.label&#8217;, default: propiedad)}&#8221; /&gt;<br />
		&lt;/g:each&gt;<br />
		&lt;g:set var=&#8221;headerColumna&#8221; value=&#8221;Eliminar&#8221; /&gt;<br />
		&lt;gna:hasProperty object=&#8221;${entidadClass}&#8221; property=&#8221;habilitado&#8221;&gt;<br />
			&lt;g:set var=&#8221;headerColumna&#8221; value=&#8221;Habilitado&#8221; /&gt;<br />
		&lt;/gna:hasProperty&gt;<br />
		&lt;th&gt;<br />
			${headerColumna}<br />
		&lt;/th&gt;<br />
	&lt;/tr&gt;<br />
&lt;/thead&gt;</p>
<p>[/html]</p>
<p>Tambien se creo el metodo hasProperty en el caso de que un columna se necesite para ciertas entidades que las posee. Esto incluye setear ciertas variables declaradas en nuestro gsp para modificar cualquier atributo de un elemento html.</p>
<p>[html]</p>
<p>&lt;gna:hasProperty object=&#8221;${entidadInstance}&#8221; property=&#8221;habilitado&#8221;&gt;<br />
	&lt;g:set var=&#8221;clase&#8221;<br />
	value=&#8221;${entidadInstance?.habilitado == false ? &#8216;disable&#8217; : (i % 2) == 0 ? &#8216;even&#8217; : &#8216;odd&#8217;}&#8221; /&gt;<br />
&lt;/gna:hasProperty&gt;</p>
<p>[/html]</p>
<p>Luego enviamos una lista con un nombre genérico, sin importar de qué tipo es, que van a ser cada una de las filas de la grilla.</p>
<p>[html]</p>
<p>&lt;g:each in=&#8221;${propiedades}&#8221; status=&#8221;s&#8221; var=&#8221;propiedad&#8221;&gt;<br />
	&lt;td&gt;<br />
		${fieldValue(bean: entidadInstance, field: propiedad)}<br />
	&lt;/td&gt;<br />
&lt;/g:each&gt;</p>
<p>[/html]</p>
<p>Cabe aclarar, que en el ABMController, al realizar el render genérico, se envían parámetros genéricos, que representa cada uno de los parámetros en manera general y no de manera particular a la entidad.</p>
<p>[groovy]</p>
<p>protected renderList(parametros) {<br />
	render(view: &#8216;/abm/list&#8217;, model: parametros)<br />
}</p>
<p>[/groovy]</p>
<p>En el create.gsp, cabe destacar, el uso del parámetro forms, el cual es enviado como parámetro desde el ABMController. El método que lo define, utiliza la entidad declarada como string en la clase hija, por lo tanto, el gsp definido debe ser nombrado con el nombre de la entidad. También debemos enviar el plugin como parámetro, en caso de que el formulario estén en un plugin distinto al controller. En el edit, la utilización de los parámetros, es muy similar al del create.</p>
<p>[groovy]</p>
<p>protected String getForm() {<br />
	&#8216;/forms/&#8217; + entidad<br />
}</p>
<p>[/groovy]</p>
<p>También se puede generalizar el seteo de la variable flash del controller para los mensajes de error o de otro tipo, por ejemplo, mensajes de información.</p>
<p>[groovy]</p>
<p>private setErrorMessage(String code, Long id) {<br />
	flash.message = message(code: code, args: getEntidadConIdMessageArgs(id))<br />
}</p>
<p>private setInfoMessage(String code, Long id) {<br />
	flash.info = message(code: code, args: getEntidadConIdMessageArgs(id))<br />
}</p>
<p>[/groovy]</p>
<p>Si tenemos algún comportamiento específico de un entidad en alguna de las acciones definidas en el ABMController, se puede redefinir el método que representa a la acción, en la clase hija. También se pueden agregar acciones que no afecten al comportamiento de las anteriores.</p>
<p>Dentro de cada método, se definieron los métodos abstractos beforeSave, beforeEdit, etc.Los mismos son redefinidos, en caso de ser necesario, en cada clase hija, principalmente para setear atributos o agregar cierta lógica, antes de realizar la acción que se requiere realizar.</p>
<p>Como conclusión, gracias al Scaffolding y a los templates que podemos modificar, Grails nos provee una fuerte herramienta para poder personalizar los ABMs. Nosotros lo que tratamos de hacer, fue dar un pasito mas y abstraernos de funcionalidades comunes en toda nuestra aplicación. Esto nos permitió crear ABMs en cuestión de minutos, solamente heredando y definiendo un solo .gsp.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/grails-abms-rapidos-y-sencillos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FluentMigrator para manejar versiones de DB</title>
		<link>http://blog.hexacta.com/hat/fluentmigrator-para-manejar-versiones-de-db/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fluentmigrator-para-manejar-versiones-de-db</link>
		<comments>http://blog.hexacta.com/hat/fluentmigrator-para-manejar-versiones-de-db/#comments</comments>
		<pubDate>Fri, 03 May 2013 18:15:36 +0000</pubDate>
		<dc:creator>mmunilla</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Base de datos]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=3145</guid>
		<description><![CDATA[Qué es y para qué sirve? Es una herramienta para hacer migraciones sobre una Base de Datos Relacional. Nos permite manejar el “versionado” de una Base de Datos para poder facilitar las tareas para hacerlo y no depender del trabajo manual de generar scripts con cambios incrementales, versionarlos, ponerlos en el orden indicado para ser corridos, y un largo listado de etcéteras. Esta herramienta nos provee de: Una API para definirlas Un ejecutable de línea de comandos para correrlas Y un DSL (Domain Specific Language) para declarar cada sentencia de la migración. Haciendo honor a su nombre, expone una interfaz fluida q nos permite fácilmente declarar estas sentencias de forma muy similar a cómo lo haríamos en SQL pero con [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/database.jpg"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/05/database-300x284.jpg" alt="" title="database" width="200" height="180" class="alignleft size-medium wp-image-3166" /></a><br />
<h1>Qué es y para qué sirve?</h1>
<p>Es una herramienta para hacer migraciones sobre una Base de Datos Relacional. Nos permite manejar el “versionado” de una Base de Datos para poder facilitar las tareas para hacerlo y no depender del trabajo manual de generar scripts con cambios incrementales, versionarlos, ponerlos en el orden indicado para ser corridos, y un largo listado de etcéteras.</p>
<p>Esta herramienta nos provee de:</p>
<ul>
<li>Una<strong> API</strong> para definirlas</li>
<li>Un <strong>ejecutable</strong> de línea de comandos para correrlas</li>
<li>Y un <strong>DSL</strong> (<em>Domain Specific Language</em>) para declarar cada sentencia de la migración. Haciendo honor a su nombre, expone una interfaz fluida q nos permite fácilmente declarar estas sentencias de forma muy similar a cómo lo haríamos en SQL pero con la ventaja que tenemos un chequeo estático de tipos.</li>
</ul>
<p>Está inspirado de rails: <a href="http://guides.rubyonrails.org/migrations.html" target="_blank">http://guides.rubyonrails.org/migrations.html</a><br />
<span id="more-3145"></span></p>
<h1>Cómo se instala?</h1>
<p>La instalación para Visual Studio es muy fácil.</p>
<p>Primeramente, puede instalarse desde el siguiente link de NuGet: <a href="http://visualstudiogallery.msdn.microsoft.com/en-us/27077b70-9dad-4c64-adcf-c7cf6bc9970c/file/37502/5/NuGet.Tools.signed.vsix">http://visualstudiogallery.msdn.microsoft.com/en-us/27077b70-9dad-4c64-adcf-c7cf6bc9970c/file/37502/5/NuGet.Tools.signed.vsix</a></p>
<p>Luego, para utilizarlo debemos crear un proyecto para nuestras migraciones. En este caso, corresponde que creemos un Class Library Project</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s11.jpg"><img class="alignnone size-medium wp-image-3147" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s11-300x208.jpg" alt="" width="300" height="208" /></a></p>
<p>Luego, desde la consola del package manager tipear:</p>
<ul>
<li><code>PM&gt; Install-Package FluentMigrator</code></li>
<li><code>PM&gt; Install-Package FluentMigrator.Tools -&gt; </code>para poder correr las migraciones desde la línea de comandos</li>
</ul>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s2.jpg"><img class="alignnone size-medium wp-image-3148" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s2-300x147.jpg" alt="" width="300" height="147" /></a></p>
<p>Y listo, ya estamos listos para empezar!</p>
<h1>Fluent Interface</h1>
<p>Como mencionamos escuetamente al principio de este post, FluentMigrator expone una interfaz fluida que permite declarar sentencias de forma muy similar a cómo lo haríamos en SQL.</p>
<p>Como por ej:</p>
<ul>
<li>Podemos crear tablas con un simple:<br />
<code>Create.Table("TableName")</code><br />
<code>.WithColumn("ColumnName").AsInt64().NotNullable().PrimaryKey().Identity();</code><br />
<code>.WithColumn("AnotherColumnName").AsString().NotNullable();</code></li>
<li>O podemos renombrar tablas con un simple:<br />
<code>Rename.Table("TableName").To("AnotherTableName");</code></li>
</ul>
<p>Para más ejemplos de posibles sentencias pueden dirigirse al siguiente link:<a href="https://github.com/schambers/fluentmigrator/wiki/Fluent-Interface" target="_blank">https://github.com/schambers/fluentmigrator/wiki/Fluent-Interface</a></p>
<h1>Cómo definir una migración?</h1>
<p>Esencialmente para definir una migración necesitamos de:</p>
<ul>
<li><span style="text-decoration: underline">Una clase que cuente con 2 métodos</span> : Up( ) and Down( ), y el número de versión de migración.<br />
Una vez que tenemos estos métodos definidos para cada migración, es que podremos “ir y venir” en las migraciones sin problemas desde cualquier punto.<br />
<em>Por supuesto, teniendo cuidado en dichas migraciones  la pérdida de datos. Es probable que necesitemos backpups de los mismos.</em></li>
<li><span style="text-decoration: underline">Un archivo de configuración</span> (App.config) que cuente con el connection string a la base.<br />
A decir verdad, este archivo de configuración no es estrictamente necesario. El connection string puede explicitarse por línea de comandos sin necesidad de ser incluido en un App.config</li>
</ul>
<p>A continuación les comparto mi clase y mi archivo de configuración de mi proyecto MyExample.</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s31.jpg"><img class="alignnone size-medium wp-image-3150" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s31-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s4.jpg"><img class="alignnone size-medium wp-image-3151" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s4-300x99.jpg" alt="" width="300" height="99" /></a></p>
<h1>Y a todo esto… cómo se corre esta cosa?</h1>
<p>Buena pregunta!</p>
<p>En una línea de comando escribimos:</p>
<p>&gt; <code>PathDelArchivo"Migrate.exe" -a PathDeLaDll -db NombreDelMotor -conn NameDelConnectionString</code></p>
<p>En mi caso de MyExample sería:</p>
<p><code>C:\Users\user\Documents\Visual Studio 2012\Projects\MyExample\packages\FluentMigrator.Tools.1.0.6.0\tools\x86\40&gt; Migrate.exe -a "<code>C:\Users\user\Documents\Visual Studio 2012\Projects\MyExample\</code>MyExample\bin\Debug\MyExample.dll" -db sqlserver2008 -conn "DataAccess.AppConnectionString"</code></p>
<p>Y el resultado es el siguiente:</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s5.jpg"><img class="alignnone size-medium wp-image-3153" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s5-300x274.jpg" alt="" width="300" height="274" /></a></p>
<p>Si vamos a la Base de Datos en cuestión para ver si efectivamente se realizaron los cambios correspondientes, veremos que:</p>
<ul>
<li>Se han creado las tablas correspondientes</li>
<li>Se han insertado los datos correspondientes</li>
</ul>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s6.jpg"><img class="alignnone size-medium wp-image-3154" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s6-261x300.jpg" alt="" width="261" height="300" /></a></p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s7.jpg"><img class="alignnone size-medium wp-image-3155" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/s7-300x183.jpg" alt="" width="300" height="183" /></a></p>
<h1>Problemas frecuentes</h1>
<p>Un problema con el que nos topamos es que en mucha de la información que hay en Internet, mencionan que es necesario escribir en la línea de comandos el <strong>nombre del archivo de configuración </strong> en lugar de decir: <strong>el nombre del connection string que pusimos en el archivo de configuración.</strong></p>
<p>Attenti con eso!</p>
<h1>Información extra</h1>
<p>FluentMigrator tiene algunas cosas interesantes que pude descubrir.</p>
<p>Vamos a mencionar 2 de ellas:</p>
<ul>
<li><strong>Profiles: </strong>Se usa para migraciones que aplican selectivamente. Por ej, se puede definir un Profile para Desarrollo y otro para Testing. Estos Profiles se corren si se especifican.</li>
<li><strong>Extensions: </strong>Cuenta con algunas extensions copadas. Para más información ver: <a href="https://github.com/schambers/fluentmigrator/blob/master/src/FluentMigrator.Example/FluentMigrator.Example/Migrations/MigrationExtensions.cs">https://github.com/schambers/fluentmigrator/blob/master/src/FluentMigrator.Example/FluentMigrator.Example/Migrations/MigrationExtensions.cs</a></li>
</ul>
<p>Esto ha sido una reseña de FluentMigrator. Más información: <a href="https://github.com/schambers/fluentmigrator">https://github.com/schambers/fluentmigrator</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/fluentmigrator-para-manejar-versiones-de-db/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 tips sobre jQuery Mobile</title>
		<link>http://blog.hexacta.com/hat/5-tips-sobre-jquery-mobile/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=5-tips-sobre-jquery-mobile</link>
		<comments>http://blog.hexacta.com/hat/5-tips-sobre-jquery-mobile/#comments</comments>
		<pubDate>Fri, 26 Apr 2013 15:40:07 +0000</pubDate>
		<dc:creator>emalvino</dc:creator>
				<category><![CDATA[Html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQueryMobile]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=3089</guid>
		<description><![CDATA[jQuery Mobile es un framework construido sobre HTML5, jQuery y jQuery.UI que nos provee widgets, themes, layouts y todo lo necesario para construir una aplicación web que funcione tanto en desktop como en dispositivos móviles. Si bien es muy fácil de empezar usar, a veces queremos hacer cosas mas rebuscadas que requieren investigar un poco mas. Vamos a ver 5 casos comunes y como se implementan con jQuery Mobile. 1 &#8211; &#8220;Quiero usar un slider, pero no quiero que aparezca el input con el valor&#8221; Cuando usamos agregamos un slider a nuestra aplicación lo hacemos de la siguiente manera: [html] Input slider: [/html] Y el resultado es el siguiente: Pero quizás no queremos tener el input con el valor numérico, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-mobile-logo.jpg"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-mobile-logo.jpg" alt="" title="jquery-mobile-logo" width="243" height="142" class="alignleft size-full wp-image-3090" /></a>jQuery Mobile es un framework construido sobre HTML5, jQuery y jQuery.UI que nos provee widgets, themes, layouts y todo lo necesario para construir una aplicación web que funcione tanto en desktop como en dispositivos móviles. Si bien es muy fácil de empezar usar, a veces queremos hacer cosas mas rebuscadas que requieren investigar un poco mas. Vamos a ver 5 casos comunes y como se implementan con jQuery Mobile.<br />
<span id="more-3089"></span></p>
<h3>1 &#8211; &#8220;Quiero usar un slider, pero no quiero que aparezca el input con el valor&#8221;</h3>
<p>Cuando usamos agregamos un slider a nuestra aplicación lo hacemos de la siguiente manera:</p>
<p>[html]<br />
<label for="slider-1">Input slider:</label></p>
<input type="range" name="slider-1" id="slider-1" value="60" min="0" max="100" />
[/html]</p>
<p>Y el resultado es el siguiente:<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-slider1.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-slider1.png" alt="" title="jquery slider1" width="467" height="88" class="aligncenter size-full wp-image-3091" /></a><br />
Pero quizás no queremos tener el input con el valor numérico, solamente queremos el slider. Para quitarlo tenemos que agregar <em>display:none</em> al <em>style</em> del input. De esa manera no se muestra más el input numérico:</p>
<p>[html]<br />
<label for="slider-1">Input slider:</label></p>
<input type="range" name="slider-1" id="slider-1" value="60" min="0" max="100" style="display:none"/>
[/html]<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-slider2.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-slider2.png" alt="" title="jquery slider2" width="409" height="73" class="aligncenter size-full wp-image-3092" /></a></p>
<h3>2 &#8211; &#8220;Agrego contenido dinámico a mi listview pero aparece sin formato&#8221;</h3>
<p>Quizás tenemos una lista vacía en nuestro HTML que llenamos dinámicamente con datos, como en el siguiente ejemplo:<br />
[html]</p>
<div data-role="page" id="resultados">
<div data-role="header">
<h1>Resultados</h1>
</p></div>
<div data-role="content">
<ul data-role="listview" id="lista"></ul>
</p></div>
</div>
<p>[/html]<br />
Y usamos un script como el siguiente:<br />
[javascript]<br />
$(&#8220;#resultados&#8221;).on(&#8220;pageshow&#8221;,function(){<br />
	$.ajax({<br />
		url: &#8220;http://someserver/resultados.json&#8221;,<br />
		success: function(data){<br />
			var lista = $(&#8220;#lista&#8221;);<br />
			$(data).each(function(i, resultado){<br />
				lista.append(&#8220;
<li>&#8221; + resultado + &#8220;</li>
<p>&#8220;);<br />
			});<br />
		}<br />
	});<br />
});<br />
[/javascript]<br />
Pero cuando lo ejecutamos obtenemos lo siguiente:<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-listview1.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-listview1.png" alt="" title="jquery listview1" class="aligncenter size-full wp-image-3095" /></a><br />
El problema es que cuando agregamos elementos a la lista, jQuery Mobile ya renderizo la página y sus componentes, entonces los nuevos componentes no tienen aplicados los estilos de jQuery Mobile.<br />
Para solucionar esto simplemente ejecutamos el metodo <em>listview(&#8220;refresh&#8221;)</em> sobre la lista, así se vuelve a renderizar la misma incluyendo los elementos que se agregaron:<br />
[javascript]<br />
$(&#8220;#resultados&#8221;).on(&#8220;pageshow&#8221;,function(){<br />
	$.ajax({<br />
		url: &#8220;http://someserver/resultados.json&#8221;,<br />
		success: function(data){<br />
			var lista = $(&#8220;#lista&#8221;);<br />
			$(data).each(function(i, resultado){<br />
				lista.append(&#8220;
<li>&#8221; + resultado + &#8220;</li>
<p>&#8220;);<br />
			});<br />
			lista.listview(&#8220;refresh&#8221;);<br />
		}<br />
	});<br />
});<br />
[/javascript]<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-listview2.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/jquery-listview2.png" alt="" title="jquery listview2" class="aligncenter size-full wp-image-3096" /></a></p>
<h3>3 &#8211; &#8220;Quiero que el header y/o el footer aparezcan en un extremo de la pantalla y no scrolleen&#8221;</h3>
<p>Por default el header y footer de una pagina están ubicados inmediatamente antes y después del content, con lo cual su posición depende del contenido del mismo y están sujetos al scroll si lo hubiere.<br />
Si en alguna de las 2 secciones tenemos contenido relevante quizás queramos que aparezcan fijos al principio y final de la pantalla y no dependan del scroll. Para eso usamos el atributo <em>data-positon=&#8221;fixed&#8221;</em> que cumple exactamente esa función. Ejemplo:<br />
[html]</p>
<div data-role="page">
<div data-role="header" data-position="fixed">
      <!-- Contenido del header -->
   </div>
<div data-role="content">
      <!-- Contenido del content -->
   </div>
<div data-role="footer" data-position="fixed">
      <!-- Contenido del footer -->
   </div>
</div>
<p>[/html]</p>
<h3>4 &#8211; &#8220;Quiero reutilizar un footer en varias paginas de mi aplicación&#8221;</h3>
<p>Actualmente jQuery Mobile no soporta reutilizar el footer o header en varias paginas. Pero podemos lograr el mismo efecto con un poco de código de jQuery.<br />
Primero tomamos el codigo del footer que vamos a reutilizar y lo anidamos en un div que no se muestre:<br />
[html]</p>
<div id="myFooter" style="display:none">
	<a href="#help" data-role="button" data-icon="info">Help</a><br />
	<a href="#home" data-role="button" data-icon="home">Home</a>
</div>
<p>[/html]</p>
<p>Luego en nuestras paginas creamos el footer pero lo dejamos vacío:<br />
[html]</p>
<div data-role="page" id="home">
<div data-role="header" data-position="fixed">Home</div>
<div data-role="content" id="myContent">Home content</div>
<div data-role="footer" class="ui-bar" data-position="fixed"></div>
</div>
<div data-role="page" id="help">
<div data-role="header" data-position="fixed"> Help</div>
<div data-role="content">Texto de ayuda</div>
<div data-role="footer" class="ui-bar" data-position="fixed"></div>
</div>
<p>[/html]<br />
Finalmente, cuando se crea cada pagina vamos a tomar el codigo del div oculto y lo vamos a copiar a los footers vacios, con el siguiente javascript:<br />
[javascript]<br />
$(document).on(&#8220;pagebeforecreate&#8221;, function(){<br />
	$(&#8220;div[data-role='footer']:empty&#8221;).parent().on(&#8220;pagecreate&#8221;,function(eventObject){<br />
		$(eventObject.target).children(&#8220;div[data-role='footer']&#8220;).html($(&#8220;#myFooter&#8221;).html());<br />
	});<br />
});<br />
[/javascript]<br />
Hay varias cosas para aclarar acá:</p>
<ul>
<li>El selector <em>div[data-role='footer']:empty</em> va a obtener todos los footers que estén vacíos</li>
<li>De esos footers vacíos obtenemos el padre, es decir la page, y le agregamos un handler que se va a ejecutar con el evento <em>pagecreate </em>de la página</li>
<li>El handler va a tomar el código de nuestro div oculto (<em>$(&#8220;#myFooter&#8221;).html()</em>) y lo va a copiar en el footer de la pagina cuando se crea (<em>$(eventObject.target).children(&#8220;div[data-role='footer']&#8220;).html( &#8230; );</em>)</li>
<li>Finalmente, esta registración del handler se va a hacer durante el evento <em>pagebeforecreate </em>del document, que se ejecuta antes del <em>pagecreate </em>de cada página</li>
</ul>
<h3>5 &#8211; &#8220;Me da un error cuando quiero navegar a otra pagina que esta en otro archivo html&#8221;</h3>
<p>No es un tema de jQuery Mobile, pero es común toparse con este error al navegar a otra página contenida en otro html:</p>
<blockquote><p>XMLHttpRequest cannot load file:///&#8230;.html. Origin null is not allowed by Access-Control-Allow-Origin.</p></blockquote>
<p>Básicamente es un feature de los browsers que, por seguridad, impiden obtener recursos de otro dominio distinto.<br />
Más detalles: <a href="http://www.w3.org/TR/cors/">http://www.w3.org/TR/cors/.</a><br />
Esto aplica a los requests por Ajax, como los que usa jQuery Mobile para la navegación entre páginas.<br />
La solución más simple es no abrir los archivos desde el filesystem y en vez usar un webserver (Apache, IIS, etc) y acceder a la página a traves del mismo desde una url.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/5-tips-sobre-jquery-mobile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FluentValidation, una pequeña librería de validaciones para .NET</title>
		<link>http://blog.hexacta.com/hat/fluentvalidation-una-pequena-libreria-de-validaciones-para-net/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fluentvalidation-una-pequena-libreria-de-validaciones-para-net</link>
		<comments>http://blog.hexacta.com/hat/fluentvalidation-una-pequena-libreria-de-validaciones-para-net/#comments</comments>
		<pubDate>Tue, 16 Apr 2013 15:52:06 +0000</pubDate>
		<dc:creator>Rodrigo Alfonso</dc:creator>
				<category><![CDATA[.Net]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=3028</guid>
		<description><![CDATA[Introducción ¿Cuántas veces hemos deseado que las annotations con las cuales decoramos nuestras entidades nos permitieran hacer cosas un poco más complejas que simplemente pedir que cierto atributo no esté vacío, o que tal otro cumpla cierta expresión regular? FluentValidation, que de acuerdo a su propia descripción es una pequeña librería para .NET que usa una interfaz fluída (Para más información sobre interfaces fluídas pueden ver el siguiente texto de Martin Fowler: http://www.martinfowler.com/bliki/FluentInterface.html) y expresiones lambda para construir reglas de validación para nuestros objetos de negocio, es precisamente la solución al problema planteado arriba. Suficiente introducción, vamos a empezar a mostrar un poco de esta librería. Cabe destacar que la misma está disponible a través de NuGet para facilitarnos un poco [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/fv1.png"><img class="alignleft size-full wp-image-3083" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/04/fv1.png" alt="" width="184" height="99" /></a></p>
<h2>Introducción</h2>
<div dir="ltr">¿Cuántas veces hemos deseado que las annotations con las cuales decoramos nuestras entidades nos permitieran hacer cosas un poco más complejas que simplemente pedir que cierto atributo no esté vacío, o que tal otro cumpla cierta expresión regular?</div>
<div dir="ltr"></div>
<div dir="ltr">FluentValidation, que de acuerdo a su propia descripción es una pequeña librería para .NET que usa una interfaz fluída (Para más información sobre interfaces fluídas pueden ver el siguiente texto de Martin Fowler: <a href="http://www.martinfowler.com/bliki/FluentInterface.html" target="_blank">http://www.martinfowler.com/bliki/FluentInterface.html</a>) y expresiones lambda para construir reglas de validación para nuestros objetos de negocio, es precisamente la solución al problema planteado arriba.</div>
<div dir="ltr"></div>
<p><span id="more-3028"></span></p>
<div dir="ltr">Suficiente introducción, vamos a empezar a mostrar un poco de esta librería. Cabe destacar que la misma está disponible a través de <a title="FluentValidation at NuGet" href="http://nuget.org/packages/FluentValidation" target="_blank">NuGet</a> para facilitarnos un poco referenciarla o también tenemos la opción de bajarla desde <a title="FluentValidation" href="http://fluentvalidation.codeplex.com" target="_blank">CodePlex</a>. En nuestro caso, vamos a referenciar la librería desde un simple proyecto MVC 4, usando Visual Studio 2012.</div>
<div dir="ltr"></div>
<h2>Integración con MVC</h2>
<div dir="ltr">FluentValidation puede ser fácilmente integrada con MVC 4. Una vez referenciada, MVC  va a usar FluentValidation para validar todos los objetos que sean pasados a una <em>action</em> de un <em>controller</em> de manera transparente para nosotros.</div>
<div dir="ltr">Para habilitar esta integración debemos referenciar FluentValidation.Mvc4 desde nuestro proyecto (como mencionamos antes, esto lo podemos lograr a través de varios caminos). Una vez instalado, necesitamos configurar el <em>FluentValidationModelValidatorProvider</em>:</div>
<pre>[csharp]
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    FluentValidationModelValidatorProvider.Configure();
}
[/csharp]</pre>
<div dir="ltr">
<h2>Creando nuestro primer Validator</h2>
<p>Antes de crear <em>validators</em> vamos a necesitar tener alguna entidad para validar.  En este caso, elegimos crear una entidad llamada <em>Contact</em>:</p>
<pre>[csharp]
[Validator(typeof(ContactValidator))]
public class Contact
{
    public int Id { get; set; }

    [DisplayName("First Name")]
    public string FirstName { get; set; }

    [DisplayName("Last Name")]
    public string LastName { get; set; }

    [DisplayName("Nick")]
    public string NickName { get; set; }

    [DisplayName("Email Address")]
    public string EmailAddress { get; set; }
}
[/csharp]</pre>
<p>Ahora si, para definir un conjunto de reglas de validación, construimos un validador específico para nuestra entidad <em>Contact</em> que hereda de <em>AbstractValidator&lt;Contact&gt;. </em>Las reglas de validación propiamente dichas las vamos a definir en el constructor de nuestro validador, de la siguiente manera:</p>
<pre>[csharp]
public class ContactValidator : AbstractValidator&lt;Contact&gt;
{
    public ContactValidator()
    {
        RuleFor(contact =&gt; contact.FirstName).NotNull();
        RuleFor(contact =&gt; contact.LastName).NotNull();
        RuleFor(contact =&gt; contact.NickName).NotNull();
        RuleFor(contact =&gt; contact.EmailAddress).EmailAddress();
    }
}
[/csharp]</pre>
</div>
<div dir="ltr">Y ahora vamos a probar nuestro progreso creando un contacto nuevo, convenientemente vamos a no llenar ningún campo del formulario para ver como saltan las validaciones:</div>
<div dir="ltr"></div>
<div dir="ltr">
<div id="attachment_3062" class="wp-caption aligncenter" style="width: 490px"><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Create.png"><img class="size-full wp-image-3062" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Create.png" alt="FluentValidation - Create Contact" width="480" height="570" /></a><p class="wp-caption-text">FluentValidation - Create Contact</p></div>
</div>
<div dir="ltr"></div>
<h2>Condicionales y Validadores</h2>
<p>Acá es donde se ve la parte más poderosa de este framework. En FluentValidation podemos definir condicionales sobre nuestras validaciones (por ejemplo: Validar que la fecha de nacimiento no sea nula sólo si el usuario marcó que es mayor de 18 años). Hacer algo así con el esquema de validación estándar de MVC 4 es algo imposible sin ensuciar mucho el código, ya que no está soportado como parte del framework. FluentValidation incorpora condicionales (when, unless) y varios validadores (NotNull, NotEmpty, Email, etc).</p>
<p>Digamos que introducimos en nuestro proyecto una nueva entidad, <em>Address</em>, y la asociamos a <em>Contact</em>, en el momento de validar una dirección nos va a interesar que la primera línea de la misma no sea nula sólo si la segunda línea tiene contenido.</p>
<pre>[csharp]
using Contacts.Models;
using FluentValidation;

namespace Contacts.Validators
{
    public class AddressValidator : AbstractValidator&lt;Address&gt;
    {
        public AddressValidator()
        {
            RuleFor(address =&gt; address.FirstLine).NotNull()
                .Unless(address =&gt; !string.IsNullOrEmpty(address.SecondLine));
            RuleFor(address =&gt; address.City).NotNull();
            RuleFor(address =&gt; address.SubnationalEntityId).NotNull();
        }
    }
}
[/csharp]</pre>
<div dir="ltr">Lamentablemente, MVC 4 no es lo suficientemente sofisticado como para poder transmitir estos condicionales al cliente, con lo cual esto no va a ser validado desde la UI usando <em>unobtrusive validation</em>. Habrá que esperar&#8230;</div>
<h2>Conclusión</h2>
<p>En esta (muy) breve introducción a FluentValidation hemos visto lo fácil que es generar validaciones complejas de manera muy prolija en nuestros proyectos. Espero que esto los motive a pasarse por el sector de documentación del proyecto en CodePlex y vean que lo que mostramos acá es sólo &#8220;la punta del iceberg&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/fluentvalidation-una-pequena-libreria-de-validaciones-para-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database Refactoring usando Liquibase</title>
		<link>http://blog.hexacta.com/hat/database-refactoring-usando-liquibase/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=database-refactoring-usando-liquibase</link>
		<comments>http://blog.hexacta.com/hat/database-refactoring-usando-liquibase/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 16:39:03 +0000</pubDate>
		<dc:creator>emalvino</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=3003</guid>
		<description><![CDATA[A medida que desarrollamos una aplicación suele ser inevitable en algún punto hacer refactoring del código. A su vez también es necesario poder compartir esos cambios con otras personas, versionarlos, poder resolver conflictos entre distintas versiones, etc. Para todo esto contamos con muchas herramientas que simplifican estas tareas y nos permiten concentrarnos en el desarrollo. Pero que pasa con la base de datos? Muchas veces esos cambios impactan en la estructura de la base de datos, por ejemplo al agregar o quitar atributos a persistir. Estas modificaciones a la base de datos tienen que estar a su vez asociadas a una versión específica del código para que la aplicación funcione. Y ademas suele haber varias instancias de la base de [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="" src="http://www.liquibase.org/_media/sql-database.jpg" title="DB refactoring" class="alignleft" width="225" height="133" />A medida que desarrollamos una aplicación suele ser inevitable en algún punto hacer refactoring del código. A su vez también es necesario poder compartir esos cambios con otras personas, versionarlos, poder resolver conflictos entre distintas versiones, etc.<br />
Para todo esto contamos con muchas herramientas que simplifican estas tareas y nos permiten concentrarnos en el desarrollo.</p>
<p>Pero que pasa con la base de datos? Muchas veces esos cambios impactan en la estructura de la base de datos, por ejemplo al agregar o quitar atributos a persistir. Estas modificaciones a la base de datos tienen que estar a su vez asociadas a una versión específica del código para que la aplicación funcione. Y ademas suele haber varias instancias de la base de datos (en distintos ambientes como desarrollo, test, producción, etc), en las cuales es necesario impactar los cambios al deployar una nueva versión del código.<br />
Todo esto implica mucho trabajo manual de generar scripts con cambios incrementales, secuenciarlos, versionarlos y, al deployar la aplicación en un nuevo ambiente, analizar que versión de la base de datos esta instalada y cuales son los cambios que deberían impactarse en la misma.<br />
Para simplificar esta problemática tenemos <strong>Liquibase</strong>.<br />
<span id="more-3003"></span></p>
<h1>Qué es Liquibase?</h1>
<p>Liquibase es una librería que nos permite llevar a cabo cada una de estas tareas. Para eso usa archivos XML llamados <strong>Changelogs </strong>que contienen los cambios a aplicar en la base de datos en una manera legible y <em>&#8220;human friendly&#8221;</em>. Sobre estos changelogs podemos ejecutar distintos comandos:</p>
<ul>
<li>Generate Changelog: Para generar un nuevo changelog a partir de una DB existente. Suele ser útil cuando queremos empezar a usar Liquibase en una aplicación que ya tiene una DB creada</li>
<li>Diff: Si bien lo normal sería agregar manualmente los cambios al changelog a medida que surgen, es posible generarlos a partir de un diff entre la DB donde queremos aplicarlos y otra DB de referencia con los cambios aplicados, o los mapeos de Hibernate de nuestra aplicación.</li>
<li>Update: Aplicar los cambios necesarios a una DB. Liquibase automáticamente evalua cuales son los cambios que es necesario aplicar y los ejecuta en secuencia.</li>
<li>Rollback: A veces los cambios que hacemos en la aplicación no suelen funcionar como esperábamos y necesitamos hacer un rollback de la aplicación deployando una versión anterior. Liquibase nos permite hacer lo mismo con los cambios en la base de datos, haciendo un rollback a una versión anterior.</li>
</ul>
<p>Para los últimos 2 comandos es posible generar un script SQL en vez de aplicar los cambios directamente en la DB, en caso de que queramos revisarlos primero.<br />
Ademas es posible ejecutar Liquibase de 3 formas:</p>
<ul>
<li>Desde linea de comandos</li>
<li>Como una tarea de Ant</li>
<li>Como un plugin de Maven</li>
</ul>
<h1>Como implementarlo?</h1>
<p>Vamos a ver un ejemplo del uso típico de Liquibase.</p>
<h2>Setup</h2>
<p>Descargamos Liquibase y al descomprimir el archivo obtenemos un jar y un bat para ejecutarlo. Normalmente agregamos el directorio al path del sistema para poder ejecutar los comandos desde cualquier directorio.<br />
Vamos a crear un directorio dentro de nuestra aplicación donde guardar los changelogs, y creamos el <em>changelog-master.xml</em> principal vacío:<br />
[xml]<br />
<?xml version="1.0" encoding="UTF-8"?><br />
<databaseChangeLog><br />
</databaseChangeLog><br />
[/xml]</p>
<h2>Changelog inicial</h2>
<p>Para esto usamos el comando <em>generateChangeLog</em>:<br />
<code><br />
liquibase --driver=org.postgresql.Driver --classpath=postgresql-9.1-901.jdbc4.jar --changeLogFile=changelog.xml --url="jdbc:postgresql://localhost:5432/db_test" --username=test --password=test generateChangeLog<br />
</code><br />
O para simplificar podemos guardar todos esos parámetros en un <em>liquibase.properties</em> en el directorio donde lo ejecutamos:<br />
<code><br />
driver=org.postgresql.Driver<br />
classpath=postgresql-9.1-901.jdbc4.jar<br />
changeLogFile=changelog-base.xml<br />
url=jdbc:postgresql://localhost:5432/db_test<br />
username=test<br />
password=test<br />
</code><br />
Y ejecutamos:<br />
<code><br />
liquibase generateChangeLog<br />
</code></p>
<p>Luego agregamos la referencia del changelog generado a nuestro <em>changelog-master.xml</em>:</p>
<p>[xml]<br />
<?xml version="1.0" encoding="UTF-8"?><br />
<databaseChangeLog ><br />
    <include file="changelog-base.xml"/><br />
</databaseChangeLog><br />
[/xml]</p>
<h2>Generando cambios en el esquema</h2>
<p>Si por ejemplo estamos desarrollando un requerimiento en el cual se agregan los atributos <em>fecha</em> y <em>estado </em>a la clase <em>Pedido </em>y borramos <em>edad </em>en la clase <em>Persona</em>, generaríamos un nuevo changelog con los siguientes datos:<br />
[xml]<br />
<?xml version="1.0" encoding="UTF-8"?><br />
<databaseChangeLog><br />
    <changeSet id="1" author="emalvino"><br />
        <comment>Agrego fecha y estado a pedido</comment><br />
        <addColumn tableName="pedido"></p>
<column name="fecha" type="date"/>
        </addColumn><br />
        <addColumn tableName="pedido"></p>
<column name="estado" type="integer"/>
        </addColumn><br />
    </changeSet></p>
<p>    <changeSet id="2" author="emalvino"><br />
        <comment>Elimino edad de persona</comment><br />
        <dropColumn tableName="person" columnName="edad"/><br />
    </changeSet><br />
</databaseChangeLog><br />
[/xml]</p>
<p>Y agregamos al referencia al <em>changelog-master.xml</em>:<br />
[xml]<br />
<?xml version="1.0" encoding="UTF-8"?><br />
<databaseChangeLog ><br />
    <include file="changelog-base.xml"/><br />
    <include file="changelog-cambio-pedido-y-persona.xml"/><br />
</databaseChangeLog><br />
[/xml]</p>
<p>Finalmente subiríamos todo al repositorio en un solo commit, junto al cambio en el código de la aplicación.</p>
<h2>Aplicando los cambios en otro ambiente</h2>
<p>Por ejemplo, si nuestra aplicación usa Maven, podemos agregar Liquibase como un plugin y hacerlo parte del proceso de deploy.<br />
Agregamos la configuración en nuestro <em>pom.xml</em>:<br />
[xml]</p>
<project>
    [...]<br />
    <build></p>
<plugins>
<plugin>
          <groupId>org.liquibase</groupId><br />
          <artifactId>liquibase-maven-plugin</artifactId><br />
          <version>2.0.1</version><br />
          <executions><br />
            <execution></p>
<phase>process-resources</phase>
              <configuration></p>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
              </configuration><br />
              <goals><br />
                <goal>update</goal><br />
              </goals><br />
            </execution><br />
          </executions>
        </plugin>
      </plugins>
    </build><br />
    [...]
  </project>
[/xml]</p>
<p>Y cuando ejecutamos <em>liquibase:update</em> se ejecuta el proceso que se conecta a la DB, evalúa cual es la versión del esquema que tiene y aplica los cambios necesarios según los changelogs que tenemos en nuestra aplicación.</p>
<h1>Otras cosas interesantes sobre los changelogs</h1>
<p>Hasta acá vimos un uso básico, pero podemos hacer cosas mas complejas con Liquibase.</p>
<h2>Preconditions</h2>
<p>Podemos definir condiciones para que se ejecute o no un changelog. Por ejemplo:<br />
[xml]</p>
<preConditions>
    <or><br />
      <dbms type="oracle" /><br />
      <and><br />
        <dbms type="mysql" /><br />
        <sqlCheck expectedResult="1">SELECT COUNT(1) FROM configuration WHERE url = &#8216;http://testurl&#8217;</sqlCheck><br />
      </and><br />
    </or>
 </preConditions>
[/xml]<br />
En este caso solo ejecutamos el changelog si la DB es oracle <strong>o</strong> si es mysql<strong> y</strong> tiene una fila en la tabla <em>configuration</em> en la cual <em>url</em> sea http://testurl.</p>
<h2>Ejecutar siempre un cambio</h2>
<p>Si bien Liquibase evalúa qué cambios aplicar según la versión del esquema de la DB, podemos definir que ejecute siempre algún changeset en particular:<br />
[xml]<br />
    <changeSet id="2" author="emalvino" runAlways="true"><br />
        <dropTable tableName="temporaryTable"/><br />
    </changeSet><br />
[/xml]<br />
En este caso al definir <em>runAlways=&#8221;true&#8221;</em> estaríamos borrando la tabla <em>temporaryTable </em>siempre, sin importar si este changeset ya se ejecuto en la DB actual.</p>
<h2>Rollbacks personalizados</h2>
<p>Es posible definir comportamientos específicos para el rollback de cada changeset. Por ejemplo:<br />
[xml]<br />
    <changeSet id="changeRollback" author="emalvino"><br />
        <createTable tableName="envios_argentina"></p>
<column name="id" type="int"/>
        </createTable><br />
        <rollback><br />
            <dropTable tableName="envios_argentina"/><br />
            <delete tableName="destinos"><br />
              <where>nombre=&#8221;Argentina&#8221;</where><br />
            </delete><br />
        </rollback><br />
    </changeSet><br />
[/xml]<br />
En este caso además de borrar la tabla creada, se borra una fila en otra tabla.</p>
<p>Más información: <a href="http://www.liquibase.org/" title="Liquibase">http://www.liquibase.org/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/database-refactoring-usando-liquibase/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Haciendo tu código más lindo con NDepend.</title>
		<link>http://blog.hexacta.com/hat/haciendo-tu-codigo-mas-lindo-con-ndepend/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=haciendo-tu-codigo-mas-lindo-con-ndepend</link>
		<comments>http://blog.hexacta.com/hat/haciendo-tu-codigo-mas-lindo-con-ndepend/#comments</comments>
		<pubDate>Tue, 05 Mar 2013 15:23:41 +0000</pubDate>
		<dc:creator>jbautista</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Visual Studio]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=2958</guid>
		<description><![CDATA[NDepend es una herramienta de Visual Studio para administrar código complejo .NET y lograr una mejor calidad del código. Con NDepend, la calidad del software se puede medir con métricas, visualizándola en gráficos y diagramas de árbol, y cumpliendo con normas/reglas estándares y personalizadas. La herramienta también realiza instantáneas de código, de comparación y validación de reglas arquitectónicas y de calidad. Se pueden escribir reglas definidas por el usuario, utilizando consultas LINQ. Esta posibilidad se denomina CQLinq. La herramienta también viene con un gran número de reglas predefinidas de código CQLinq. Dichas reglas de Código se pueden comprobar automáticamente en Visual Studio o durante la integración continua. En las primeras versiones se usaba como un complemento externo al Visual Studio, ahora, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image1.png"><img class="alignleft  wp-image-2965" title="Visual NDepend 4.0" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image1-296x300.png" alt="" width="160" height="162" /></a>NDepend es una herramienta de Visual Studio para administrar código complejo .NET y lograr una mejor calidad del código.</p>
<p>Con NDepend, la calidad del software se puede medir con métricas, visualizándola en gráficos y diagramas de árbol, y cumpliendo con normas/reglas estándares y personalizadas.</p>
<p>La herramienta también realiza instantáneas de código, de comparación y validación de reglas arquitectónicas y de calidad. Se pueden escribir reglas definidas por el usuario, utilizando consultas LINQ.</p>
<p>Esta posibilidad se denomina CQLinq. La herramienta también viene con un gran número de reglas predefinidas de código CQLinq.</p>
<p><span id="more-2958"></span></p>
<p>Dichas reglas de Código se pueden comprobar automáticamente en Visual Studio o durante la integración continua.</p>
<p>En las primeras versiones se usaba como un complemento externo al Visual Studio, ahora, la herramienta tiene un plugin completamente integrada al Visual Studio.</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image1.png"><img class="aligncenter size-full wp-image-2965" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image1.png" alt="" width="374" height="379" /></a></p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image2.png"><img class="aligncenter size-full wp-image-2966" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image2.png" alt="" width="628" height="285" /></a></p>
<p>Las principales características de NDepend son:</p>
<ul>
<li>Visualización de dependencia (usando gráficos de dependencia, y matriz de dependencia).</li>
</ul>
<div><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image3.png"><img class="aligncenter size-full wp-image-2967" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image3.png" alt="" width="545" height="245" /></a></div>
<div>
<ul>
<li>Métricas de software (NDepend actualmente soporta 82 métricas de código:. Cyclomatic complexity; Afferent and Efferent Coupling; Relational Cohesion; Google page rank of .NET types; Percentage of code covered by tests, etc.).</li>
</ul>
<div><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image4.png"><img class="aligncenter size-full wp-image-2968" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image4.png" alt="" width="572" height="260" /></a></div>
<div>
<ul>
<li>Regla de código declarativo sobre consulta LINQ (CQLinq).</li>
</ul>
<div><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image5.png"><img class="aligncenter size-full wp-image-2969" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image5.png" alt="" width="498" height="230" /></a></div>
<ul>
<li>Integración con CruiseControl y TeamCity.</li>
</ul>
<div><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image11.png"><img class="aligncenter size-medium wp-image-2985" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image11-300x151.png" alt="" width="300" height="151" /></a></div>
<div><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image12.png"><img class="aligncenter size-medium wp-image-2986" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image12-300x234.png" alt="" width="300" height="234" /></a></div>
<div><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image13.png"><img class="aligncenter size-medium wp-image-2987" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image13-300x106.png" alt="" width="300" height="106" /></a></div>
<div></div>
<ul>
<li>Restricciones opcionales de código en el código fuente con los atributos de CLI.</li>
<li>Comparación de versión de dos versiones del mismo asembly.</li>
</ul>
</div>
<div></div>
<div>
<p>Desde la versión 4 NDepend, la herramienta de consulta propone live code query y reglas de código a través de consultas LINQ. Esta es una de las innovaciones de NDepend. Por ejemplo:</p>
<p><strong>- La clase base no debe usar derivados:</strong></p>
<p><em>// Base class should not use derivatives</em><br />
<em> warnif count &gt; 0</em><br />
<em> from baseClass in JustMyCode.Types</em><br />
<em> where baseClass.IsClass &amp;&amp; baseClass.NbChildren &gt; 0</em><br />
<em> select new { baseClass, derivedClassesUsed }</em></p>
<p><strong>- Evite hacer complejos métodos aún más complejo (complejidad ciclomática del código fuente)</strong></p>
<p><em>//Avoid making complex methods even more complex (Source CC)</em><br />
<em> warnif count &gt; 0</em><br />
<em> from m in JustMyCode.Methods where</em><br />
<em> !m.IsAbstract &amp;&amp;</em><br />
<em> m.IsPresentInBothBuilds() &amp;&amp;</em><br />
<em> m.CodeWasChanged()</em><br />
<em> let oldCC = m.OlderVersion().CyclomaticComplexity</em><br />
<em> where oldCC &gt; 6 &amp;&amp; m.CyclomaticComplexity &gt; oldCC</em><br />
<em> select new { m,</em><br />
<em> oldCC,</em><br />
<em> newCC = m.CyclomaticComplexity,</em><br />
<em> oldLoc = m.OlderVersion().NbLinesOfCode,</em><br />
<em> newLoc = m.NbLinesOfCode,</em><br />
<em> }</em></p>
</div>
</div>
<p>&nbsp;</p>
<p>En el siguiente link, muestra los features que contiene la herramienta NDepend.</p>
<p><strong><em>http://www.ndepend.com/Features.aspx</em></strong></p>
<p>&nbsp;</p>
<p style="text-align: center;"><strong>¿Qué me dice el informe NDepend acerca de mi código? </strong></p>
<p><strong>Application Metric:</strong> Esta sección le da una idea de la topología de su aplicación.</p>
<p><strong>Assembly Metric:</strong> Esta sección le da una idea del tamaño de cada conjunto en su aplicación en términos de instrucciones #IL y otras métricas.</p>
<p><strong>VisualNDepend View:</strong>  En esta sección se ilustra el tamaño de sus asamblies, namespaces, types y methods en términos de instrucciones #IL . Se puede browsear por esta vista dinámica haciendo clic en el  Launch Visual NDepend en este icono de NDepend.Project UI.</p>
<p><strong>Assembly Abstracness vs. Instability:</strong> En esta sección se ilustra el principio Abstracness / Inestabilidad se explica en la sección Assembly Metric.</p>
<p><strong>Assembly Dependencies:</strong> Esta sección muestra todas las dependencias entre las asambleas de su aplicación en una tabla.</p>
<p><strong>Assembly Dependency Diagram:</strong> Esta sección muestra todas las dependencias entre las asambleas de su aplicación en un diagrama.</p>
<p><strong>Assembly build order:</strong> Esta sección ofrece uno de las posibles build order de los assemblies. Si existe un ciclo en el gráfico de dependencias de los assemblies, esta sección lo informa.</p>
<p><strong>NDepend information and warnings:</strong> Esta sección le da consejos acerca de su código:</p>
<p>Le avisa cuando un assembly depende de un assembly menos estable que el mismo.</p>
<p>Le advierte cuando la visibilidad de un tipo o de un miembro no es óptima (en el contexto de la aplicación analizada).</p>
<p>Le avisa cuando un tipo o un miembro no se utiliza (en el contexto de la aplicación analizada).</p>
<p><strong>CQLinq Queries and Rules:</strong> Esta sección recoge las reglas predeterminadas CQLinq que han sido violadas.</p>
<p><strong>Type Metrics:</strong> Esta sección resume métricas de tipo en una tabla.</p>
<p align="center"><strong>Ejemplo de uso de NDepend.</strong></p>
<p>Esta vista tiene muchas cosas que pueden explotarse, ya que la herramienta viene con un lenguaje de consultas, que te permite entre otras cosas, saber cuantos métodos de tipo string con mas de 50 lineas de código.</p>
<p>En la vista se puede observar por ejemplo, que las consultas por defecto que te muestra son, Restricciones de Calidad de Código, Restricciones de nombre (las cuales, se puede personalizar), Diseño, Performance, Código que nunca usas!, etc.</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image6.png"><img class="aligncenter size-full wp-image-2970" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image6.png" alt="" width="528" height="233" /></a></p>
<p>La herramienta te permite realizar tus propias consultas, como hemos mencionado anteriormente. En el siguiente ejemplo, se realiza una consulta sobre la cantidad de líneas de código de cada objeto.</p>
<p>Se pueden saber los métodos donde no tienen mucho comentario, como así también los métodos que son muy extensos. Se puede parametrizar la cantidad de líneas que pueden tener esos métodos para la consulta en NDepend.</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image7.png"><img class="aligncenter size-full wp-image-2971" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image7.png" alt="" width="528" height="233" /></a></p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image8.png"><img class="aligncenter size-full wp-image-2972" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image8.png" alt="" width="528" height="233" /></a></p>
<p>Si cliqueamos sobre la consulta, me muestra un resumen de la misma.</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image9.png"><img class="aligncenter size-full wp-image-2973" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image9.png" alt="" width="411" height="360" /></a></p>
<p>Si aun queremos mas detalle, cliqueamos sobre los objetos y nos muestra los datos que se ven en la siguiente imagen.</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image10.png"><img class="aligncenter size-full wp-image-2974" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/03/Image10.png" alt="" width="368" height="316" /></a></p>
<p><strong>Pros</strong></p>
<p>&nbsp;</p>
<ul>
<li>Extremadamente versátil y extensible, gracias a CQL.</li>
<li>Apunta a las áreas problemáticas en su código.</li>
<li>Introduce un nuevo lenguaje para la comunicación entre los desarrolladores.</li>
<li>Visual NDepend como una gran interfaz gráfica de usuario.</li>
<li>Útil conjunto de métricas para empezar, ampliable si es necesario.</li>
</ul>
<p>&nbsp;</p>
<p><strong>Contras</strong></p>
<ul>
<li>CQL carece de algunas características interesantes (posiblemente agregados, la comparación de las métricas)</li>
<li>NDepend.Console.exe tiene un conjunto limitado de parámetros.</li>
<li>El informe HTML se crea siempre, incluso en escenarios de CI, con los archivos XML habría sido suficiente.</li>
</ul>
<div></div>
<div>Referencias:</div>
<div>http://www.ndepend.com</div>
<div>http://www.ndepend.com/Features.aspx</div>
<div>http://www.codeproject.com/Articles/43486/Simplify-Code-Using-NDepend</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/haciendo-tu-codigo-mas-lindo-con-ndepend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatizando tareas con Gerrit y Jenkins &#8211; Parte 2</title>
		<link>http://blog.hexacta.com/hat/automatizando-tareas-con-gerrit-y-jenkins-parte-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=automatizando-tareas-con-gerrit-y-jenkins-parte-2</link>
		<comments>http://blog.hexacta.com/hat/automatizando-tareas-con-gerrit-y-jenkins-parte-2/#comments</comments>
		<pubDate>Fri, 22 Feb 2013 16:54:36 +0000</pubDate>
		<dc:creator>emalvino</dc:creator>
				<category><![CDATA[SCM]]></category>
		<category><![CDATA[Gerrit]]></category>
		<category><![CDATA[GiT]]></category>
		<category><![CDATA[Jenkins]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=2902</guid>
		<description><![CDATA[En el post anterior vimos una introduccion a Git, Gerrit y Jenkins y un ejemplo de como integrarlos para automatizar una tarea. En este post vamos a ver otros ejemplo más complejos: Ejecutar el build de un proyecto cuando se sube un cambio para code review, para saber si ese cambio rompe el build antes de hacer el review del mismo Deployar un proyecto y generar un branch con el código del mismo Code Review Descripción El proceso que vamos a implementar es el siguiente: El programador hace varios commits. Luego hace un push al repositorio remoto y el cambio queda pendiente para code review. Ante ese evento se dispara un build que obtiene ese cambio aún no aprobado. El [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/robots2.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/robots2.png" alt="" title="robots2" width="240" height="180" class="alignleft size-full wp-image-2903" /></a><br />
En el post anterior vimos una introduccion a Git, Gerrit y Jenkins y un ejemplo de como integrarlos para automatizar una tarea. En este post vamos a ver otros ejemplo más complejos:</p>
<ul>
<li>Ejecutar el build de un proyecto cuando se sube un cambio para code review, para saber si ese cambio rompe el build antes de hacer el review del mismo</li>
<li>Deployar un proyecto y generar un branch con el código del mismo</li>
</ul>
<p><span id="more-2902"></span></p>
<h1>Code Review</h1>
<h2>Descripción</h2>
<p>El proceso que vamos a implementar es el siguiente:<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/post-git-jenkins.png"><img class="aligncenter size-full wp-image-2866" title="post git jenkins" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/post-git-jenkins.png" alt="" width="550" height="388" /></a><br />
El programador hace varios commits. Luego hace un push al repositorio remoto y el cambio queda pendiente para code review.<br />
Ante ese evento se dispara un build que obtiene ese cambio aún no aprobado. El resultado del build exitoso o fallido es informado a Gerrit y queda registrado como Verified +1 o Verified -1.<br />
Cuando otro usuario ingresa a Gerrit para hacer el code review, ya tiene en el campo Verified la información para saber si el cambio compila o no. En caso afirmativo y que pase el code review, se hace el merge del cambio al master y queda disponible para el resto de los programadores.</p>
<h2>Configuración</h2>
<ol>
<li>Configuramos el trigger de gerrit para que dispare un nuevo build con cada cambio subido. Ponemos el nombre del proyecto y un path por si queremos filtrar algunos cambios en particular (en nuestro caso ponemos ** para todos los cambios). Y agregamos los eventos que queremos escuchar. En nuestro caso <em>Draft Published</em> (cuando se sube un cambio pendiente de code review) y <em>Patchset Created</em> (cuando se sube un patchset para corregir algo de un Draft ya creado). <a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-8.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-8.png" alt="" title="gerrit-jenkins-8" class="alignleft size-full wp-image-2919" width="500" height="360"/></a></li>
<li>Especificamos en la configuración del respositorio las variables <em>$GERRIT_REFSPEC</em> y <em>$GERRIT_BRANCH</em> para el refspec y el branch respectivamente. Esto hace que no baje el último cambio del master (por default), sino el cambio del branch que disparó el evento. <a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-9.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-9.png" alt="" title="gerrit-jenkins-9" width="500" height="199" class="alignleft size-full wp-image-2927" /></a></li>
</ol>
<p>De esta manera, cuando hacemos un push de un cambio nuevo jenkins notifica a gerrit si ese cambio esta verified o no segun el resultado del build:<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-7.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-7.png" alt="" title="gerrit-jenkins-7" class="alignleft size-full wp-image-2936" /></a></p>
<h1>Branch y Deploy</h1>
<h2>Descripción</h2>
<p>Este es el diagrama del proceso que vamos a automatizar:<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/post-git-jenkins-2.png"><img class="aligncenter size-full wp-image-2865" title="post git jenkins 2" src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/post-git-jenkins-2.png" alt="" width="550" height="340" /></a><br />
Periódicamente vamos a disparar un build en Jenkins que va a obtener el código actual del master de Git.<br />
Si el build es exitoso se van a hacer 3 cosas:</p>
<ul>
<li>Hacer un deploy del proyecto empaquetado en el servidor</li>
<li>Crear un branch con el codigo del release</li>
<li>Notificar al Project Manager por email del release exitoso</li>
</ul>
<p>Si el build falla se notifica al desarrollador por mail.</p>
<h2>Configuración</h2>
<h3>Email</h3>
<p>Para configurar el envío de mails agregamos un <em>Editable Email Notification</em> como <em>Post-build Action</em>, y agregamos distintos destinatarios segun el resultado del build:<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-12.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-12.png" alt="" title="gerrit-jenkins-12" width="550" height="468" class="alignleft size-full wp-image-2938" /></a><br />
Adicionalmente se pueden configurar el subject, el contenido del mail, los attachments, etc.</p>
<h3>Deploy</h3>
<p>Para hacer el deploy de un artifact agregamos la tarea <em>Deploy war/ear to a container</em> como <em>Post-build Action</em>.<br />
Configuramos la ubicación del archivo a deployar, el Context path (en caso de querer especificar uno distinto al default), el Application server a usar, la url y las credenciales a usar:<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-11.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-11.png" alt="" title="gerrit-jenkins-11" width="575" height="293" class="alignleft size-full wp-image-2941" /></a></p>
<h3>Branch</h3>
<p>Finalmente vamos a crear un branch con el código del build, agregando un <em>Git Publisher</em> como <em>Post-build Action</em>.<br />
Marcamos la opción <em>Publish Only If Build Succeeds</em>, para crear el branch solo si el build fue exitoso.<br />
Finalmente ingresamos los datos del branch a crear. En el nombre usamos la variable de entorno <em>$BUILD_ID</em> de Jenkins que contiene el timestamp de la fecha.<br />
Y en <em>Target remote name</em> el nombre del repositorio remoto (<em>origin </em>es el default, pero podríamos elegir otro si tenemos mas de 1 repositorio remoto).<br />
<a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-10.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-10.png" alt="" title="gerrit-jenkins-10" width="575" height="417" class="alignleft size-full wp-image-2943" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/automatizando-tareas-con-gerrit-y-jenkins-parte-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatizando tareas con Gerrit y Jenkins &#8211; Parte 1</title>
		<link>http://blog.hexacta.com/hat/automatizando-tareas-con-gerrit-y-jenkins-parte-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=automatizando-tareas-con-gerrit-y-jenkins-parte-1</link>
		<comments>http://blog.hexacta.com/hat/automatizando-tareas-con-gerrit-y-jenkins-parte-1/#comments</comments>
		<pubDate>Wed, 13 Feb 2013 17:04:44 +0000</pubDate>
		<dc:creator>emalvino</dc:creator>
				<category><![CDATA[SCM]]></category>
		<category><![CDATA[Gerrit]]></category>
		<category><![CDATA[GiT]]></category>
		<category><![CDATA[Jenkins]]></category>

		<guid isPermaLink="false">http://blog.hexacta.com/hat/?p=2864</guid>
		<description><![CDATA[En este post vamos a ver como integrar Git, Gerrit y Jenkins. Primero vamos a ver algunas características de estas herramientas y luego vamos a configurarlas paso a paso para automatizar algunas tareas típicas del desarrollo. Definiciones Git es un SCM desarrollado inicialmente por un tal Linus Torvalds, que a diferencia de CVS o SVN implementa el concepto de repositorios distribuidos. La idea es que cada integrante tiene un repositorio local en su PC y al menos 1 o más repositorios remotos a los cuales se suben cambios desde el repositorio local. Como consecuencia, aun cuando el repositorio remoto este offline, es posible seguir haciendo commits, branchs, merges, etc. al repositorio local y luego hacer un &#8220;push&#8221; de los cambios [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/robots.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/robots.png" alt="" title="robots" width="240" height="147" class="alignleft size-full wp-image-2894" /></a>En este post vamos a ver como integrar Git, Gerrit y Jenkins. Primero vamos a ver algunas características de estas herramientas y luego vamos a configurarlas paso a paso para automatizar algunas tareas típicas del desarrollo.</p>
<p><span id="more-2864"></span></p>
<h1>Definiciones</h1>
<p><strong>Git</strong> es un SCM desarrollado inicialmente por un tal Linus Torvalds, que a diferencia de CVS o SVN implementa el concepto de repositorios distribuidos. La idea es que cada integrante tiene un repositorio local en su PC y al menos 1 o más repositorios remotos a los cuales se suben cambios desde el repositorio local. Como consecuencia, aun cuando el repositorio remoto este offline, es posible seguir haciendo commits, branchs, merges, etc. al repositorio local y luego hacer un &#8220;push&#8221; de los cambios al repositorio remoto. Mas información: <a href="http://git-scm.com/">http://git-scm.com/</a></p>
<p><strong>Gerrit</strong> es una aplicación de code review y administración de repositorios Git desarrollada por Google. Permite hacer code reviews de cada commit antes de mergearlo al branch principal (master), pudiendo agregar comentarios en cada linea de código y notificar explícitamente a algún integrante en particular para que revise un cambio. Mas información: <a href="http://code.google.com/p/gerrit/">http://code.google.com/p/gerrit/</a></p>
<p><strong>Jenkins</strong> es un servidor de integración continua. Es open source y tiene un mecanismo de plugins muy completo, que permite agregar soporte a distintos SCM, herramientas de compilación, generación de reportes, publicación de resultados, triggers para distintos eventos, customización de la UI, etc.. Mas información: <a href="http://jenkins-ci.org/">http://jenkins-ci.org/</a></p>
<h1>Release Notes</h1>
<p>Vamos a configurar Jenkins y Gerrit para que genere un archivo de release notes detallando los cambios incluidos en el build de un proyecto y lo envíe por mail en la notificación del mismo.</p>
<ol>
<li>Creamos un nuevo job en Jenkins y configuramos la sección de <strong>Source Code Management</strong> con los datos del repositorio de Git de donde obtener y compilar el código del proyecto.
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-1.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-1.png" alt="" title="gerrit-jenkins-1" width="500" height="200" class="aligncenter size-full wp-image-2885" /></a></li>
<li>Configuramos la sección de <strong>Build Triggers</strong> para disparar el build periódicamente. En este ejemplo, lo vamos a disparar a través de un expresión cron todos los viernes a las 12:00 hs.
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-4.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-4.png" alt="" title="gerrit-jenkins-4" width="500" height="280" class="aligncenter size-full wp-image-2891" /></a></li>
<li>Agregamos un <strong>Build Step</strong> de tipo <strong>Shell Script</strong> al job de Jenkins, en el cual vamos a generar el archivo con los cambios introducidos en este build.<br />
Para eso hacemos uso del comando <strong>log</strong> de git, al cual por parámetro le pasamos que nos devuelva los detalles de los commits agregados a este proyecto desde la última semana (&#8211;since={1.week.ago}), y en formato <em>fecha &#8211; email_del_autor &#8211; mensaje_del_commit</em>.<br />
El output del comando lo redirigimos al archivo release_notes.txt, y como disponemos de un shell, aprovechamos para formatear cada linea usando sed. Básicamente buscamos los mensajes de commit que empiezan con &#8220;tfs &#8221; y lo reemplazamos por la url de TFS, para generar el link al issue y tener algo mas de trazabilidad.</p>
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-2.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-2.png" alt="" title="gerrit-jenkins-2" width="500" height="100" class="aligncenter size-full wp-image-2886" /></a></li>
<li>Finalmente agregamos como tarea de <strong>Post-Build</strong> el envío del mail con el resultado del build. Simplemente agregamos como attachment el archivo release_notes.txt.
<p><a href="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-3.png"><img src="http://blog.hexacta.com/hat/wp-content/uploads/2013/02/gerrit-jenkins-3.png" alt="" title="gerrit-jenkins-3" width="500" height="280" class="aligncenter size-full wp-image-2887" /></a></li>
</ol>
<p>Y al llegar el mail podemos ver el archivo generado:<br />
<xml><br />
Thu Feb 7 11:26:22 2013 -0300 &#8211; emalvino@hexacta.com &#8211; https://tfs.hexacta.com/tfs/web/wi.aspx?id=1133 &#8211; Bugfix del reporte de saldo<br />
Thu Feb 7 11:17:54 2013 -0300 &#8211; emalvino@hexacta.com &#8211; https://tfs.hexacta.com/tfs/web/wi.aspx?id=2345 &#8211; Validación del email del usuario<br />
Thu Feb 7 11:12:42 2013 -0300 &#8211; emalvino@hexacta.com &#8211; https://tfs.hexacta.com/tfs/web/wi.aspx?id=1234 &#8211; ABM de Usuario agregado<br />
Tue Feb 5 17:38:53 2013 -0300 &#8211; emalvino@hexacta.com &#8211; Commit inicial<br />
Tue Feb 5 17:27:15 2013 -0300 &#8211; emalvino@hexacta.com &#8211; Initial empty repository<br />
</xml></p>
<p>En el próximo post vamos a ver otros ejemplos de tareas automatizadas usando Jenkins, Git y Gerrit.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hexacta.com/hat/automatizando-tareas-con-gerrit-y-jenkins-parte-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
