<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1253253616658611146</id><updated>2012-02-16T11:25:17.981+01:00</updated><category term='Metodologías ágiles'/><category term='Libros'/><category term='Lean'/><category term='Bases de datos'/><category term='Calidad'/><category term='javascript'/><category term='XP'/><category term='Subversion'/><category term='Eficiencia personal'/><category term='Hibernate'/><category term='UML'/><category term='Ingeniería del software'/><category term='JBoss Drools'/><category term='Formación'/><category term='Node.js'/><category term='JBoss jBPM'/><category term='Utilidades Java'/><category term='General'/><category term='Pruebas'/><category term='Manuales'/><category term='Kanban'/><category term='Eclipse'/><category term='Scrum'/><category term='Apache Maven'/><category term='Control de versiones'/><category term='Software Craftmanship'/><category term='Spring'/><category term='ClearCase'/><category term='Integración continua'/><category term='Patrones de diseño'/><category term='Ñapas'/><title type='text'>Tratando de entenderlo</title><subtitle type='html'>Espacio de reflexión y exposición de ideas y dificultades encontradas en mi proceso de aprendizaje del desarrollo de proyectos software.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>70</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-1341916494420652207</id><published>2011-12-30T23:56:00.005+01:00</published><updated>2011-12-31T00:06:12.653+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Node.js'/><title type='text'>Empezando con Node.js</title><content type='html'>El pasado día 27 de diciembre estuve en la charla organizada por el grupo MadridJS sobre &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt; y Heroku. Acudí porque había leído algo sobre el tema y tenía curiosidad por saber de qué trataba realmente este proyecto. En la charla se dió una explicación inicial de lo que es y para qué sirve e incluso se vió algún ejemplo real, pero además se habló de algunos otros proyectos y tecnologías relacionadas con &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt;, como es el manejo de &lt;span style="font-weight:bold;"&gt;WebSockets&lt;/span&gt; con la librería &lt;span style="font-weight:bold;"&gt;Socket.IO&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;A partir de lo visto en dicha charla me ha picado la curiosidad y en lo últimos días he estado buscando información sobre &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt; para poder conocer algo más sobre este proyecto. &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt; lleva la programación en Javascript al lado del servidor. Es una plataforma que permite el desarrollo de servidores de alta concurrencia y que se ejecuta sobre la máquina de Javascript de Google V8. Se basa en el paradigma de programación orientada a eventos de entrada y salida de forma asíncrona.&lt;br /&gt;&lt;br /&gt;¿Y cuál es la principal ventaja de &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt;? Pues su rapidez y el menor número de recursos que consume. Un servidor de Node.js se ejecuta en un único hilo y no crea un nuevo proceso o un nuevo hilo por cada petición entrante, con el consumo de recursos que esto supone. Sin embargo, las operaciones en &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt; se ejecutan de forma no bloqueante en base a eventos, por lo que se pueden aprovechar los tiempos muertos de las operaciones de entrada/salida para servir otras peticiones y aumentar la rapidez. &lt;br /&gt;&lt;br /&gt;¿Que significa que las operaciones se ejecutan de forma no bloqueante y en base a eventos? Pues que todas las operaciones de entrada/salida se realizan de forma asíncrona. Cuando se llama a una operación de entrada/salida se le pasa una función &lt;span style="font-style:italic;"&gt;callback &lt;/span&gt;que será el manejador del evento de ejecución y  pasa a ejecutarse en segundo plano, continuando con la ejecución del programa. Cuando la operación de entrada/salida haya finalizado saltará el evento correspondiente y se llamará a la función &lt;span style="font-style:italic;"&gt;callback &lt;/span&gt;que lo maneja, que dispondrá de la información recuperada y podrá trabajar con ella.&lt;br /&gt;&lt;br /&gt;Además de los módulos que &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt; incorpora en su instalación, existen multitud de módulos adicionales que puedes ser usados, los cuales se pueden instalar a través de la herramienta de gestión de paquetes de &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt;: NPM (Node Package Manager). Dichos módulos permiten el acceso al sistema de archivos, bases de datos, ofrecen una implementación del patrón MVC... Dichos módulos están organizados según el estándar &lt;a href="http://wiki.commonjs.org/wiki/CommonJS"&gt;&lt;span style="font-weight:bold;"&gt;CommonJS&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;En vez de incluir aquí un ejemplo de cosecha propia, voy a remitir a quien quiera profundizar más a &lt;a href="http://www.nodebeginner.org"&gt;&lt;span style="font-style:italic;"&gt;“The Node Beginner Book”&lt;/span&gt;&lt;/a&gt;, un tutorial estupendo para iniciarse en &lt;span style="font-weight:bold;"&gt;Node.js&lt;/span&gt; y empezar a entender su forma de trabajar.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Otras referencias sobre Node.js:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://nodejs.org"&gt;Página oficial de Node.js&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nodejs.es"&gt;Node.js en español&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.rmunoz.net/introduccion-a-node-js.html"&gt;Introducción a Node.js de Rafa Muñoz&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.debugmodeon.com/articulo/introduccion-a-node-js"&gt;Introducción a Node.js en debugmodeon&lt;/a&gt;&lt;br /&gt;&lt;a href="http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb"&gt;Understanding Node.js&lt;/a&gt;&lt;br /&gt;&lt;a href="http://howtonode.org"&gt;How to Node&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop"&gt;Understanding the Node.js event loop&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.nodecloud.org"&gt;Colección de enlaces sobre Node.js&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-1341916494420652207?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/1341916494420652207/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/12/empezando-con-nodejs.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1341916494420652207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1341916494420652207'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/12/empezando-con-nodejs.html' title='Empezando con Node.js'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-4566430408798865025</id><published>2011-12-23T18:36:00.011+01:00</published><updated>2012-02-04T09:48:34.631+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>La evolución de JavaScript</title><content type='html'>En los últimos meses, y viendo la popularidad de &lt;span style="font-weight:bold;"&gt;JavaScript&lt;/span&gt; debido a fenómenos como &lt;span style="font-weight:bold;"&gt;HTML5&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;NodeJs&lt;/span&gt;, me he propuesto ponerme al día con &lt;span style="font-weight:bold;"&gt;JavaScript&lt;/span&gt;, ese lenguaje que normalmente utilizo para hacer validaciones en mis páginas HTML, pero que, en realidad, permite mucho más que eso.&lt;br /&gt;&lt;br /&gt;Lo cierto es que, debido al boom que está sufriendo este lenguaje, lo que más me está costando es saber cuál es el estado en que se encuentra y hacia donde se encamina. Por ello, sirva este post para recopilar las ideas que sobre ello he ido encontrando y para, a partir de él, seguir profundizando en el lenguaje y sus capacidades, tanto nuevas como antiguas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JavaScript&lt;/span&gt; surgió como un lenguaje de script en el navegador que apareció por primera vez dentro de &lt;span style="font-weight:bold;"&gt;Netscape Navigator 2&lt;/span&gt; allá por 1995, y que se basaba en el lenguaje &lt;span style="font-weight:bold;"&gt;CEnvi&lt;/span&gt; desarrollado anteriormente por &lt;span style="font-weight:bold;"&gt;Nombas&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Fue tal el éxito de &lt;span style="font-weight:bold;"&gt;JavaScrip&lt;/span&gt;t que &lt;span style="font-weight:bold;"&gt;Microsoft&lt;/span&gt; decidió incorporar su propia implementación de este lenguaje, llamada &lt;span style="font-weight:bold;"&gt;JScript&lt;/span&gt;, en la versión 3 de su navegador &lt;span style="font-weight:bold;"&gt;Internet Explorer&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Debido a los problemas que entrañaban las diferencias entre implementaciones, se envió la versión &lt;span style="font-weight:bold;"&gt;JavaScript 1.1&lt;/span&gt; como propuesta a &lt;span style="font-weight:bold;"&gt;ECMA&lt;/span&gt; para su estandarización, que culminó con el &lt;span style="font-weight:bold;"&gt;estándar ECMA-262&lt;/span&gt;. Este estándar dicta la base del lenguaje ECMAScript a través de su sintaxis, tipos, sentencias, palabras clave y reservadas, operadores y objetos, y sobre la cual se pueden construir distintas implementaciones. La versión &lt;span style="font-weight:bold;"&gt;JavaScript 1.3&lt;/span&gt; fue la primera implementación completa del estándar &lt;span style="font-weight:bold;"&gt;ECMAScript&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Actualmente, las implementaciones de &lt;span style="font-weight:bold;"&gt;JavaScript&lt;/span&gt; de los navegadores implementan la versión 3 del &lt;span style="font-weight:bold;"&gt;estándar ECMAScript&lt;/span&gt;, que data de 1999, y cuyas últimas mejoras han sido:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Soporte de expresiones regulares.&lt;/li&gt;&lt;li&gt;Nuevas sentencias de control.&lt;/li&gt;&lt;li&gt;Manejo de excepciones (bloque &lt;span style="font-style:italic;"&gt;try-catch&lt;/span&gt;).&lt;/li&gt;&lt;li&gt;Definición de errores más precisa.&lt;/li&gt;&lt;li&gt;Formateo de salidas numéricas de datos.&lt;/li&gt;&lt;li&gt;Manejo de &lt;span style="font-style:italic;"&gt;strings&lt;/span&gt; más avanzado.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Cuando en 2004 se empezó a trabajar en la evolución de JavaScript, surge la revolucionaria propuesta &lt;span style="font-weight:bold;"&gt;ECMAScript 4&lt;/span&gt;, que pretende convertir JavaScript en un nuevo lenguaje con nuevas reglas, principalmente introduciendo el tipado de variables y el concepto tradicional de clases e interfaces al estilo de lenguajes como &lt;span style="font-weight:bold;"&gt;Java&lt;/span&gt;. &lt;br /&gt;Debido a la revolución que estos cambios en &lt;span style="font-weight:bold;"&gt;JavaScript&lt;/span&gt; suponían, surge &lt;span style="font-weight:bold;"&gt;ECMAScript 3.1&lt;/span&gt; como contrapropuesta, que evita introducir nuevos conceptos  y añade en su lugar características adicionales al lenguaje.&lt;br /&gt;&lt;br /&gt;Finalmente se llegó a la decisión de enfocarse en la propuesta &lt;span style="font-weight:bold;"&gt;ECMAScript 3.1&lt;/span&gt;, que se ha cambiado de nombre, pasando a ser &lt;span style="font-weight:bold;"&gt;ECMAScript 5&lt;/span&gt;. &lt;span style="font-weight:bold;"&gt;ECMASCript 4&lt;/span&gt; ha quedado relegada al proyecto &lt;span style="font-weight:bold;"&gt;Harmony&lt;/span&gt;. &lt;span style="font-weight:bold;"&gt;Harmony&lt;/span&gt;, que a su vez parece que pasará a ser &lt;span style="font-weight:bold;"&gt;ECMAScript 6&lt;/span&gt;, pretende incorporar a posteriori en &lt;span style="font-weight:bold;"&gt;ECMAScript 5&lt;/span&gt; algunas de las mejoras propuestas inicialmente por &lt;span style="font-weight:bold;"&gt;ECMAScript 4&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Las características que se incluyen en &lt;span style="font-weight:bold;"&gt;ECMAScript5&lt;/span&gt; son las siguientes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Getters&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;setters&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Array extras&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;reductions&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Cambios en &lt;span style="font-style:italic;"&gt;Object&lt;/span&gt;:&lt;ul&gt;&lt;li&gt;Rediseño de los atributos internos de las propiedades.&lt;/li&gt;&lt;li&gt;Introducción de métodos estáticos de &lt;span style="font-style:italic;"&gt;Object&lt;/span&gt;, que permiten:&lt;ul&gt;&lt;li&gt;Acceder a la información del prototipo.&lt;/li&gt;&lt;li&gt;Manipular las propiedades de un objeto.&lt;/li&gt;&lt;li&gt;Crear objetos de forma dinámica.&lt;/li&gt;&lt;li&gt;Obtener los nombres de las propiedades.&lt;/li&gt;&lt;li&gt;Impedir que un objeto sea modificado.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Cambios a las funciones:&lt;ul&gt;&lt;li&gt;Soporte nativo del &lt;span style="font-style:italic;"&gt;function currying&lt;/span&gt; a través del método &lt;span style="font-style:italic;"&gt;bind&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Cambios en el objeto &lt;span style="font-style:italic;"&gt;Date&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Soporte nativo de &lt;span style="font-weight:bold;"&gt;JSON&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Modo de ejecución &lt;span style="font-style:italic;"&gt;strict&lt;/span&gt;, que define reglas de codificación más estrictas que el modo de ejecución estándar.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Los cambios que podrían ser introducidos en &lt;span style="font-weight:bold;"&gt;ECMAScript 6&lt;/span&gt; se mencionan en &lt;a href="http://www.youtube.com/watch?v=u4IdoBU1uKE"&gt;esta charla de Dave Herman&lt;/a&gt;, ingeniero de Mozilla Labs y representante del TC39:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Módulos.&lt;/li&gt;&lt;li&gt;Ámbito a nivel de bloque (sentencia &lt;span style="font-style:italic;"&gt;let&lt;/span&gt;).&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Generators&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Proxys&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Destructuring assignments&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Rest&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;default arguments&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Name object&lt;/span&gt;s.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Iterators&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Array comprehensions&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;String templates&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Hash tables&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;weak maps&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;También parece que se podría incluir:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Constantes.&lt;/li&gt;&lt;li&gt;Clases y herencia.&lt;/li&gt;&lt;li&gt;Tipos &lt;span style="font-style:italic;"&gt;Map&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;Set&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;StructType&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Algunos navegadores ya han ido incluyendo estas y otras mejoras del lenguaje, como se indica &lt;a href="http://en.wikipedia.org/wiki/JavaScript"&gt;en estos datos obtenidos de Wikipedia&lt;/a&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Javascript 1.5 (Firefox 1.0, IE 8-, Opera 6, Safari 5-, Chrome 10-)&lt;/span&gt;:&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;ECMAScript 3&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Constantes.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Getters&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;setters&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Javascript 1.6 (Firefox 1.5)&lt;/span&gt;:&lt;ul&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Array extras&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Array&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;String Generics&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Javascript 1.7 (Firefox 2.0)&lt;/span&gt;:&lt;ul&gt;&lt;li&gt;Ámbito a nivel de bloque.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Generators&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Iterators&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Array Comprehensions&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Destructuring assignments&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Javascript 1.8 (Firefox 3.0, Opera 11.50)&lt;/span&gt;:&lt;ul&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Expression closures&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Generator Expressions&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Array Reductions&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Javascript 1.8.1 (Firefox 3.5)&lt;/span&gt;:&lt;ul&gt;&lt;li&gt;Soporte nativo de &lt;span style="font-weight:bold;"&gt;JSON&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Javascript 1.8.2 (Firefox 3.6):&lt;ul&gt;&lt;li&gt;Actualizaciones menores.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;JavaScript 1.8.5 (Firefox 4, IE 9)&lt;/span&gt;:&lt;ul&gt;&lt;li&gt;1.8.2.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;ECMAScript 5&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;- &lt;a href="http://en.wikipedia.org/wiki/JavaScript"&gt;JavaScript en Wikipedia.&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://en.wikipedia.org/wiki/ECMAScript"&gt;ECMAScript en Wikipedia.&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://www.slideshare.net/ferrantes/ecmascript-5-10575898"&gt;Presentación sobre ECMAScript 5.&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://davidflanagan.com/Talks/es5/slides.html"&gt;ECMAScript 5: The Definitive Slides&lt;/a&gt;.&lt;br /&gt;-&lt;a href="http://java.ociweb.com/mark/other-presentations/ECMAScript5.pdf"&gt; Otra presentación sobre ECMAScript 5&lt;/a&gt;.&lt;br /&gt;- &lt;a href="http://www.youtube.com/watch?v=Kq4FpMe6cRs"&gt;Video: "Changes to JavaScript, Part 1"&lt;/a&gt;.&lt;br /&gt;- &lt;a href="http://www.youtube.com/watch?v=u4IdoBU1uKE"&gt;Video: "Dave Herman: The Future of JavaScript (ECMAScript 6)"&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=047022780X&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=047022780X&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=1118026691&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-4566430408798865025?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/4566430408798865025/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/12/la-evolucion-de-javascript.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4566430408798865025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4566430408798865025'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/12/la-evolucion-de-javascript.html' title='La evolución de JavaScript'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-5992744314417000843</id><published>2011-10-08T19:33:00.013+02:00</published><updated>2011-10-08T20:04:12.844+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache Maven'/><title type='text'>Compresión y comprobación de archivos javascript desde Maven</title><content type='html'>Estos últimos días he estado probando &lt;span style="font-weight:bold;"&gt;YUI Compressor Maven Mojo&lt;/span&gt; para la gestión de los archivos &lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt; de mis proyectos. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;YUI Compressor&lt;/span&gt; permite, en primer lugar, comprobar la corrección del código &lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt; mediante &lt;span style="font-weight:bold;"&gt;JSLint&lt;/span&gt;. En segundo lugar, permite comprimir y ofuscar los archivos &lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt;, de forma que se reduce su peso y se dificulta la introducción de ataques a través del código &lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Todo ello, a través de la siguiente configuración del &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint javascript"&gt;&amp;lt;pluginRepositories&amp;gt;&lt;br /&gt; &amp;lt;pluginRepository&amp;gt;&lt;br /&gt;  &amp;lt;name&amp;gt;oss.sonatype.org&amp;lt;/name&amp;gt;&lt;br /&gt;  &amp;lt;id&amp;gt;oss.sonatype.org&amp;lt;/id&amp;gt;&lt;br /&gt;  &amp;lt;url&amp;gt;http://oss.sonatype.org/content/groups/public&amp;lt;/url&amp;gt;&lt;br /&gt; &amp;lt;/pluginRepository&amp;gt;&lt;br /&gt;&amp;lt;/pluginRepositories&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;build&amp;gt;&lt;br /&gt; &amp;lt;plugins&amp;gt;&lt;br /&gt;  &amp;lt;plugin&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;net.alchim31.maven&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;yuicompressor-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;executions&amp;gt;&lt;br /&gt;    &amp;lt;execution&amp;gt;&lt;br /&gt;     &amp;lt;goals&amp;gt;&lt;br /&gt;      &amp;lt;goal&amp;gt;compress&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;goal&amp;gt;jslint&amp;lt;/goal&amp;gt;&lt;br /&gt;     &amp;lt;/goals&amp;gt;&lt;br /&gt;    &amp;lt;/execution&amp;gt;&lt;br /&gt;   &amp;lt;/executions&amp;gt;&lt;br /&gt;   &amp;lt;configuration&amp;gt;&lt;br /&gt;    &amp;lt;jswarn&amp;gt;true&amp;lt;/jswarn&amp;gt;&lt;br /&gt;    &amp;lt;failOnWarning&amp;gt;false&amp;lt;/failOnWarning&amp;gt;&lt;br /&gt;    &amp;lt;nomunge&amp;gt;false&amp;lt;/nomunge&amp;gt;    &lt;br /&gt;    &amp;lt;excludes&amp;gt;&lt;br /&gt;     &amp;lt;exclude&amp;gt;**/jquery.js&amp;lt;/exclude&amp;gt;&lt;br /&gt;    &amp;lt;/excludes&amp;gt;&lt;br /&gt;    &amp;lt;aggregations&amp;gt;&lt;br /&gt;     &amp;lt;aggregation&amp;gt;&lt;br /&gt;      &amp;lt;includes&amp;gt;&lt;br /&gt;       &amp;lt;include&amp;gt;**/*-min.js&amp;lt;/include&amp;gt;&lt;br /&gt;      &amp;lt;/includes&amp;gt;&lt;br /&gt;      &amp;lt;output&amp;gt;${project.build.directory}/${project.artifactId}-&lt;br /&gt;      ${project.version}/js/revistero.js&amp;lt;/output&amp;gt;&lt;br /&gt;     &amp;lt;/aggregation&amp;gt;&lt;br /&gt;    &amp;lt;aggregation&amp;gt;&lt;br /&gt;    &amp;lt;includes&amp;gt;&lt;br /&gt;     &amp;lt;include&amp;gt;**/*-min.css&amp;lt;/include&amp;gt;&lt;br /&gt;    &amp;lt;/includes&amp;gt;&lt;br /&gt;    &amp;lt;output&amp;gt;${project.build.directory}/${project.artifactId}-&lt;br /&gt;    ${project.version}/css/revistero.css&amp;lt;/output&amp;gt;&lt;br /&gt;    &amp;lt;/aggregation&amp;gt;&lt;br /&gt;   &amp;lt;/aggregations&amp;gt;&lt;br /&gt;  &amp;lt;/configuration&amp;gt;&lt;br /&gt; &amp;lt;/plugin&amp;gt;&lt;br /&gt;…&lt;br /&gt;&amp;lt;build&amp;gt;&lt;/pre&gt;&lt;br /&gt;La configuración de los atributos &lt;span style="font-style:italic;"&gt;jswarn&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;failonwarning&lt;/span&gt; hace que se realice la comprobación de los archivos &lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt; pero sin parar la ejecución en caso de error. El atributo &lt;span style="font-style:italic;"&gt;nomunge&lt;/span&gt; indica que se debe ofuscar el archivo ("munge": Modify Until Not Guessed Easily).&lt;br /&gt;&lt;br /&gt;Tanto la verificación como la compresión de los archivos se ejecutarán cada vez que se construya el proyecto mediante:&lt;br /&gt;&lt;pre class=”prettyprint”&gt;mvn package&lt;/pre&gt;&lt;br /&gt;O se despliegue con:&lt;br /&gt;&lt;pre class=”prettyprint”&gt;mvn jetty:run-war&lt;/pre&gt;&lt;br /&gt;Pero se pueden ejecutar de forma independiente. Para lanzar la compresión de los archivos &lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;css&lt;/span&gt; se ejecutará:&lt;br /&gt;&lt;pre class=”prettyprint”&gt;mvn net.alchim31.maven:yuicompressor-maven-plugin:compress&lt;/pre&gt;&lt;br /&gt;Y para realizar la verificación de los archivos &lt;span style="font-weight:bold;"&gt;javascript&lt;/span&gt;:&lt;br /&gt;&lt;pre class=”prettyprint”&gt;mvn net.alchim31.maven:yuicompressor-maven-plugin:jslint&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://alchim.sourceforge.net/yuicompressor-maven-plugin/usage_jslint.html"&gt;YUI Compressor Maven Mojo&lt;/a&gt;&lt;br /&gt;&lt;a href="http://amunizmartin.wordpress.com/2008/09/24/maven-yui-compressor-minimizando-el-tiempo-de-carga/"&gt;Minimizando el tiempo de carga: Maven YUI Compressor&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-5992744314417000843?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/5992744314417000843/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/10/compresion-y-comprobacion-de-archivos.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5992744314417000843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5992744314417000843'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/10/compresion-y-comprobacion-de-archivos.html' title='Compresión y comprobación de archivos javascript desde Maven'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-4324825761999022777</id><published>2011-08-31T12:20:00.011+02:00</published><updated>2011-10-25T12:15:40.262+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Craftmanship'/><title type='text'>Apprenticeship Patterns</title><content type='html'>La &lt;span style="font-weight:bold;"&gt;Artesanía del Software&lt;/span&gt; es un enfoque del desarrollo de software distinto de la &lt;span style="font-weight:bold;"&gt;Ingeniería de Software tradicional&lt;/span&gt;. Está más orientada hacia las relaciones entre desarrolladores y clientes en busca de valor para los proyectos, y también hacia las relaciones entre los propios desarrolladores, favoreciendo el traspaso del conocimiento.&lt;br /&gt;&lt;br /&gt;Este libro trata sobre el enfoque de la &lt;span style="font-weight:bold;"&gt;Artesanía del Software&lt;/span&gt; sobre el aprendizaje que debe realizar un desarrollador. Este aprendizaje no se limita sólo a la etapa inicial de formaciónsino que debe ser continuo a lo largo de toda la carrera profesional.&lt;br /&gt; &lt;br /&gt;Los autores (Dave H. Hoover y Adewale Osinheye) han recopilado una serie de patrones que pueden guiar este aprendizaje y que, a continuación, trataré de presentar. Dichos patrones se presentan por capítulos según su intencionalidad:&lt;br /&gt; &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Vaciando La Taza&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Cómo iniciarse en el aprendizaje desde una postura abierta y receptiva, eliminando los prejuicios.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Tu Primer Lenguaje&lt;/span&gt;: Conocer un primer lenguaje es lo que servirá como base para todo el aprendizaje posterior.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El Cinturón Blanco&lt;/span&gt;: Hay que ser humildes y receptivos, conscientes de que para aprender algo nuevo hay que desprenderse en parte de lo que sabíamos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Desata Tu Entusiasmo&lt;/span&gt;: El entusiasmo da energía a un aprendiz y a su equipo, por lo que es un valor que hay que fomentar.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Habilidades concretas&lt;/span&gt;: Una persona que está aprendiendo puede tener poco que ofrecer a un equipo de programadores expertos. Sin embargo, es necesario que pueda ofrecer algo para que se le acepte como un miembro más.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Expón Tu Ignorancia&lt;/span&gt;: Se debe hablar abiertamente de las carencias, y no engañar a nadie atribuyéndonos cualidades que no tenemos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Confronta Tu Ignorancia&lt;/span&gt;: Las carencias identificadas se deben combatir. Esto aumenta el conocimiento y permite identificar nuevas carencias.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El Profundo Abismo&lt;/span&gt;: En determinados momentos es necesario llevar a cabo tareas que están aparentemente más allá de nuestra capacidad para poder crecer.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Refúgiate En Tu Competencia&lt;/span&gt;: Para ganar confianza en caso de vernos superados se dedicar un rato a tareas que se dominan.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Caminando Por El Largo Camino&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El aprendizaje del desarrollo de software es un camino largo abarca toda la carrera profesional.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El Largo Camino&lt;/span&gt;: A lo largo de la carrera profesional la prioridad debe ser aumentar las habilidades, no en el beneficio económico ni el ascenso en la escala empresarial en sí mismo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Oficio Más Que Arte&lt;/span&gt;: Hay que ser consciente de que se están construyendo herramientas que deben aportar valor a los clientes.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Motivaciones Sostenibles&lt;/span&gt;: Para poder llegar al final del camino, se debe trabajar sin sacrificar de forma permanente ningún otro aspecto importante de la vida personal.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Alimenta Tu Pasión&lt;/span&gt;: Durante algunos periodos puede que el trabajo del día a día no sea suficientemente gratificante, y habrá que buscar algo que permita mantener la pasión por el aprendizaje, ya sea en el trabajo o fuera de él.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Dibuja Tu Propio Mapa&lt;/span&gt;: Somos los únicos responsables de nuestra trayectoria profesional. Si nuestra empresa o equipo actuales no son favorables al aprendizaje, tenemos en nuestra mano cambiar estas condiciones.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Usa Tu Título&lt;/span&gt;:  El título profesional es reflejo de la organización en la que nos encontramos. Un título que no refleja nuestra realidad es un síntoma de que debemos actuar para cambiar nuestra situación.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Permanece En Las Trincheras&lt;/span&gt;: Para aprender a desarrollar del software hay que mantenerse desarrollando, y no  dejarse seducir por ascensos profesionales que nos separen de él, llevándonos, por ejemplo hacia la gestión.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Un Camino Diferente&lt;/span&gt;: Se puede aprender a desarrollar siguiendo muchos caminos, por lo que no se debe menospreciar a quién ha elegido uno distinto.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Auto-Evaluación Precisa&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hay que saber reconocer nuestra situación respecto del entorno en que nos encontramos, para poder actuar si se da el peligro de estancamiento en el aprendizaje.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Sé El Peor&lt;/span&gt;: Ser el peor en un nuevo equipo permite aprender cosas a costa del esfuerzo que supone ponerse al día.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Encuentra Mentores&lt;/span&gt;: Conseguir que alguien con más conocimientos  nos supervise es la mejor manera de acelerar el aprendizaje.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Espíritus Afines&lt;/span&gt;: Gente con los mismos intereses nos ayudará a aprender, ofreciendo visiones alternativas, apoyo o nuevas oportunidades.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Juntar Los Codos&lt;/span&gt;: Aprender junto a alguien incentiva la comprensión y facilita la comunicación de aquello que  se da por supuesto pero que supone la diferencia.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Barrer El Suelo&lt;/span&gt;: Si se es el miembro de menor experiencia en un equipo  se deben aceptar las tareas menos llamativas para poder aspirar a tareas más complejas.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Aprendizaje Perpetuo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No se puede dejar de aprender porque la tecnología avanza y ofrece nuevas soluciones que debemos conocer en la medida de lo posible.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Expande Tu Ancho De Banda&lt;/span&gt;: Hay que abrirse a todas las fuentes de conocimiento disponibles (blogs, Twitter, listas de correo, grupos de usuarios, conferencias, libros, cursos…) para recibir información sobre aspectos distintos a nuestra experiencia.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Practica, Practica, Practica&lt;/span&gt;: Para poder aprender es útil practicar con ello en un entorno tolerante con los errores. Se puede practicar con ejercicios (katas) sólo o junto con otros desarrolladores (dojo). Una realimentación inmediata sobre los errores que podamos cometer es importante para poder corregirlos y aprender.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Juguetes Que se Pueden Romper&lt;/span&gt;: Se puede poner a prueba y aplicar lo aprendido construyendo sistemas con exigencias reales pero no críticos, tal vez para uso propio.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Usa La Fuente&lt;/span&gt;: Para reconocer buen código hay que haberlo visto antes. Leer código de otros permite entender la forma de desarrollar de otras personas y adquirir los mejores hábitos de ellas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Reflexiona Mientras Trabajas&lt;/span&gt;: Periódicamente se debe reflexionar sobre las prácticas usadas y analizar si se pueden mejorarlas o cambiars por otras mejores. Como equipo, esto puede traducirse en reuniones retrospectivas sobre la marcha del proyecto.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Guarda Lo Que Aprendes&lt;/span&gt;: Guardando constancia de cómo se ha resuelto un problema se ahorra tiempo en el futuro cuando se vuelva a presentar.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Comparte Lo Que Aprendes&lt;/span&gt;: Esto permite la comunicación con otros desarrolladores con los mismos problemas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Crea Ciclos de Realimentación&lt;/span&gt;: Sólo alguien distinto de nosotros puede evaluar de forma objetiva lo que estamos haciendo bien o mal.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Aprende Cómo Fallas&lt;/span&gt;: Identificar nuestros fallos permite afrontarlos o, si el esfuerzo fuese desmedido, aceptarlos y reconocer las tareas para las que no somos aptos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Construye Tu Currículo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La necesidad de seguir aprendiendo será continua. Estos nuevos conocimiento s irán definiendo nuestro propio currículo.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Lista de Lecturas&lt;/span&gt;: Existe una enorme cantidad de libros que pueden resultar interesantes. Mantener una lista de estos libros ayuda a priorizar y registrar lo que leemos y hacerla pública la deja abierta a sugerencias por parte de otras personas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Lee Constantemente&lt;/span&gt;: Leer de forma periódica permite adquirir un conocimiento aceptable de la tecnología y diferenciarse de la mayoría de quienes nos rodean.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Estudia Los Clásicos&lt;/span&gt;: Las referencias a clásicos del desarrollo del software son constantes y es importante leer estos libros para entender las referencias de otras personas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Excava Más Profundo&lt;/span&gt;: El conocimiento superficial de varias tareas no es suficiente. Habrá casos en que haya que profundizar en una herramienta o lenguaje concreto en busca de la solución a un problema.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Herramientas Familiares&lt;/span&gt;: Para que los proyectos puedan desarrollarse según lo estimado no se puede innovar siempre. Hay que mantener un conjunto de herramientas constantes en las que basarse.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Personalmente, este libro me parece muy inspirador y me ha dado un montón de ideas sobre cómo afrontar mi carrera como desarrollador de software, al verme reflejado en muchas de las situaciones que en él se describen. &lt;br /&gt;&lt;br /&gt;Los patrones que presenta, en ciertas ocasiones parecen sencillas e incluso evidentes. La complejidad está en saber combinarlos y aplicarlos en nuestro día a día. &lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0596518382&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0596518382&amp;ref=qf_sp_asin_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-4324825761999022777?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/4324825761999022777/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/08/apprenticeship-patterns.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4324825761999022777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4324825761999022777'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/08/apprenticeship-patterns.html' title='Apprenticeship Patterns'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-5959844962074642646</id><published>2011-06-13T15:36:00.013+02:00</published><updated>2011-10-26T08:33:15.040+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Apuntes de XP</title><content type='html'>Recientemente he estado leyendo el libro de &lt;span style="font-weight:bold;"&gt;Kent Beck "Extreme Programming Explained"&lt;/span&gt; y, lo que presento es este post, es el resumen que he hecho sobre el mismo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; es una metodología ligera para el desarrollo proyectos de software con requisitos variables o poco definidos. Pone énfasis en el código e introduce prácticas que permiten entregar el software a tiempo,  reducir el riesgo, mejorar la respuesta al cambio, aumentar la productividad y hacer más divertido el trabajo en grupo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;El problema del desarrollo de software&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El principal problema del desarrollo de software es el riesgo. &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; propone soluciones para luchar contra los distintos tipos de riesgo que pueden existir en un proyecto:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Las &lt;span style="font-weight:bold;"&gt;iteraciones cortas&lt;/span&gt; permiten planificar mejor y reaccionar a los cambios.&lt;/li&gt;&lt;li&gt;Desarrollar &lt;span style="font-weight:bold;"&gt;primero las tareas de mayor valor&lt;/span&gt; acelera el retorno de la inversión.&lt;/li&gt;&lt;li&gt;Asegurar la calidad introduciendo &lt;span style="font-weight:bold;"&gt;pruebas automáticas&lt;/span&gt; permite hacer modificaciones de forma segura.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Probar constantemente&lt;/span&gt; el sistema permite encontrar defectos más rápido.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Involucrar al cliente&lt;/span&gt; mejora la especificación del sistema y las expectativas sobre él.&lt;/li&gt;&lt;li&gt;Otorgar mayor &lt;span style="font-weight:bold;"&gt;responsabilidad y respeto al programador&lt;/span&gt; reduce su frustración. Promueve el espíritu de equipo y crea un mejor ambiente de trabajo.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;La Economía del Software&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Se debe obtener el mayor valor haciendo la mínima inversión para obtener beneficios de la forma más rápida e incrementar la vida del proyecto. &lt;br /&gt;&lt;br /&gt;Para ello, se estudian las distintas opciones de cada funcionalidad del proyecto (implementarla ya, descartarla o posponerla) y se calcula su valor según el beneficio original, el precio de la opción, el beneficio si se ejecuta la opción, el periodo de tiempo durante el que se puede ejecutar la opción y la certeza en el valor final. &lt;br /&gt;&lt;br /&gt;Las cuatro variables que permiten gestionar un proyecto son: coste, tiempo, calidad y alcance. El alcance es la variable más potente. &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; reduce el riesgo de retrasar el desarrollo de una funcionalidad y juega con el alcance centrándose en realizar aquello que está definido. Se puede modificar el alcance a medida que el proyecto avanza y el conocimiento sobre el producto deseado aumenta.&lt;br /&gt;&lt;br /&gt;Se asume que el coste que implica un cambio en el proyecto aumenta exponencialmente según avanza el proyecto. Sin embargo, combinando tecnología y buenas prácticas, se puede conseguir un aumento prácticamente lineal del coste del cambio. Esta es la premisa principal de &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt;, según la cual las decisiones se deben retrasar hasta obtener la mayor certeza. &lt;br /&gt;&lt;br /&gt;Para reducir el coste del cambio se debe usar un diseño simple, pruebas automáticas que puedan ejecutarse en cualquier momento y refactorización para modificar el diseño cuando sea necesario. Se pueden así realizar ajustes durante el desarrollo, de la misma manera que se realizan correcciones al volante cuando se conduce.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Valores, principios, actividades y prácticas de XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Los 4 valores que dirigen el proceso de XP son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Comunicación&lt;/span&gt;: la información debe fluir entre el equipo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Sencillez&lt;/span&gt;: hay que hacer las cosas de la forma más sencilla posible.&lt;/li&gt; &lt;li&gt;&lt;span style="font-weight:bold;"&gt;Realimentación&lt;/span&gt;: hay que conocer el estado del proyecto en todo momento.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Coraje&lt;/span&gt;: ser capaz de tomar decisiones difíciles cuando sea necesario.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Los valores anteriores inspiran los principios que guían a XP:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Realimentación rápida&lt;/span&gt;: acelerando es el aprendizaje.&lt;/li&gt;&lt;li&gt;Sencillez: resolver los problemas de forma sencilla.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cambio incremental&lt;/span&gt;: los cambios son más sencillos si se realizan poco a poco.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Abrazar el cambio&lt;/span&gt;: abierto a lo que depare el futuro.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Trabajo de calidad&lt;/span&gt;: si el trabajo no se hace bien, se pierde la motivación.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Enseñar a aprender&lt;/span&gt;: demostrar todo aquello sobre lo que no haya certeza.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Pequeña inversión inicial&lt;/span&gt;: manejando el alcance, no hacen falte grandes presupuestos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Jugar para ganar&lt;/span&gt;: la confianza en la propia capacidad ayuda al éxito del proyecto.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Experimentos concretos&lt;/span&gt;: probar cada decisión para asegurar que es correcta.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Comunicación abierta y honesta&lt;/span&gt;: hablar del proyecto de forma directa y sincera.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Trabajar con los instintos de las personas&lt;/span&gt;, no contra ellos: a la gente le gusta hacer un buen trabajo. Hay que ayudar a que esto ocurra.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Aceptar la responsabilidad&lt;/span&gt;: A nadie le gusta que le digan lo que tiene que hacer. Es preferible que cada persona lo elija, pero como miembro del equipo, también debe asumir la responsabilidad de hacer lo que el equipo estime necesario.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Adaptarse de forma local&lt;/span&gt;: decidir qué cosas funcionan mejor en cierto entorno.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Viajar ligero&lt;/span&gt;: mantener pocas cosas, que sean simples y de valor.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Medida honesta&lt;/span&gt;: usar medidas significativas que reflejen el estado del proyecto.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Las actividades principales del proceso de desarrollo en &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; son codificar, probar, escuchar y diseñar:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;El &lt;span style="font-weight:bold;"&gt;código&lt;/span&gt; sirve para plasmar ideas y aprender sobre ellas a través de la comunicación.&lt;/li&gt;&lt;li&gt;El código puede ser probado para ver si cumple con lo esperado. Las &lt;span style="font-weight:bold;"&gt;pruebas automáticas&lt;/span&gt; permiten realizar estas pruebas una y otra vez asegurando el funcionamiento del sistema.&lt;/li&gt;&lt;li&gt;Para implementar las pruebas, el desarrollador &lt;span style="font-weight:bold;"&gt;escucha al usuario&lt;/span&gt;, que dice cómo debe funcionar el sistema, y al propio sistema, que da realimentación sobre el sistema y sus problemas.&lt;/li&gt;&lt;li&gt;A medida que el conocimiento evoluciona y se amplían las funcionalidades &lt;span style="font-weight:bold;"&gt;se revisa el diseño&lt;/span&gt; del sistema para poder satisfacer las nuevas necesidades sin afectar a las anteriores. El diseño consiste en organizar el sistema de forma que los cambios lo afecten lo menos posible.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Las actividades anteriores se realizan mediante las siguientes prácticas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El Juego de la Planificación&lt;/span&gt;: en cada iteración los desarrolladores estiman las tareas y el cliente decide las prioridades, para seleccionar el conjunto de tareas a realizar.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Entregas cortas&lt;/span&gt;: entregar el mayor valor en  producción lo más rápidamente posible.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Metáfora&lt;/span&gt;: se utiliza una historia sobre el funcionamiento del sistema, que comparte todo el equipo, para describir el funcionamiento del sistema y guiar el desarrollo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Diseño simple&lt;/span&gt;: el sistema debe ser lo más simple posible en cada momento.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Pruebas&lt;/span&gt;: se crean pruebas unitarias y funcionales.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Refactorización&lt;/span&gt;: el sistema se reestructura constantemente, sin cambiar su comportamiento, para mejorar el diseño o la comunicación.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Programación en pareja&lt;/span&gt;: el código se escribe en pareja, aumentando la comunicación entre los miembros del equipo y otorgando realimentación inmediata.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Propiedad colectiva&lt;/span&gt;: cualquier miembro del equipo puede modificar el código.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Integración continua&lt;/span&gt;: el código se integra cada vez que se completa una tarea para mantenerlo estable.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Jornada de trabajo estable&lt;/span&gt;: XP supone un esfuerzo y se debe permitir el descanso necesario.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;span style="font-weight:bold;"&gt;Contacto directo con el cliente&lt;/span&gt;&lt;/span&gt;: el cliente debe estar disponible en todo momento para responder preguntas sobre el sistema.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Estándares de codificación&lt;/span&gt;: se programa en base a reglas de codificación que mejoran la comunicación.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;No son prácticas novedosas, sin embargo, al llevarlas a cabo de manera conjunta, unas se refuerzan a otras aumentando su potencia.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Gestión de proyectos en XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La gestión del proyecto no puede ser cosa de una sola persona, nadie tiene conocimiento total del sistema. &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; permite una estrategia de gestión descentralizada en la que el gestor sólo debe intervenir en situaciones que no se puedan resolver de forma distribuida.&lt;br /&gt;&lt;br /&gt;A la hora de gestionar un proyecto debe existir tanto un perfil administrativo como uno técnico. El perfil administrativo se encarga de que se realice el Juego de la Planificación, de recoger métricas sobre el seguimiento del proyecto y mostrárselas a los interesados. El perfil técnico hace de consejero (coach). No toma decisiones técnicas, sino que ayuda a los de demás a tomarlas y colabora con ellos en el desarrollo. También es el encargado de velar por la buena marcha del proceso de desarrollo.&lt;br /&gt;&lt;br /&gt;A la hora de realizar la planificación hay que separar las responsabilidades. Negocio decide el ámbito del proyecto y de las iteraciones, y las prioridades de las tareas. Desarrollo informa sobre las estimaciones de las funcionalidades y las alternativas técnicas. Desarrollo decide el proceso que va a seguir para el desarrollo y las prácticas que llevará a cabo. &lt;br /&gt;&lt;br /&gt;La planificación se basa en las estimaciones que los desarrolladores hacen sobre las tareas que el cliente ha priorizado. Sólo se debe planificar en detalle la iteración actual, pero se puede planificar a largo plazo con menor detalle el resto de las tareas. &lt;br /&gt;&lt;br /&gt;El objetivo de la planificación es el de maximizar el valor entregado al cliente en cada iteración. Para ello, el equipo de desarrollo deberá invertir lo mínimo posible poniendo el mayor valor en producción lo más rápidamente posible. &lt;br /&gt;&lt;br /&gt;La planificación se realiza en las siguientes fases:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Exploración&lt;/span&gt;: trata de descubrir lo que debe hacer el sistema. Se escriben historias que describen lo que debe realizar el sistema, se estiman y, si fuesen demasiado grandes, se dividen en historias más pequeñas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Compromiso&lt;/span&gt;: las historias se priorizan. A partir de la velocidad de desarrollo del equipo se elije el alcance del proyecto según el tiempo que se disponga.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Dirección&lt;/span&gt;: se realizan iteraciones de alcance restringido durante las que se pueden detectar nuevas historias que pueden ser incorporadas a la planificación. Se vuelve a estimar teniendo en cuenta la velocidad obtenida durante las iteraciones anteriores.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Desarrollo en XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Durante el desarrollo, las prácticas principales son la integración continua, la propiedad colectiva del código y la programación en parejas. &lt;br /&gt;&lt;br /&gt;La integración continua consiste en que los desarrolladores integren sus cambios cada pocas horas, manteniendo la corriente principal del desarrollo en sincronía. Gracias a las pruebas automáticas se verifica en todo momento que el sistema sigue funcionando, y gracias a la refactorización se transforma el sistema en elementos cada vez más pequeños e independientes, de forma que los cambios a realizar están mucho más localizados.&lt;br /&gt;&lt;br /&gt;La propiedad colectiva del código hace que cualquiera pueda modificar cualquier parte del código cuando lo necesite. Para ello es preciso atenerse a unas reglas de codificación comunes que faciliten la comprensión del código a todo el equipo.&lt;br /&gt;&lt;br /&gt;La programación en pareja obliga a programar, analizar, diseñar y probar de forma conjunta. Esto favorece la comunicación y el aprendizaje. Uno de los miembros se centra en programar, mientras que el otro piensa de una manera más estratégica. Hace que la gente se mantenga fiel a las prácticas de &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt;, puesto que hay cierta supervisión.&lt;br /&gt;&lt;br /&gt;La disposición del entorno de trabajo debe favorecer el trabajo en equipo. Es importante tener espacios comunes donde el equipo pueda reunirse a debatir o donde programar en pareja.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Diseño en XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; se procura tener en todo momento un diseño lo más simple posible. Se realiza una inversión inicial pequeña  para proporcionar valor rápidamente, haciendo cosas simples que permitan evolucionar el diseño fácilmente. &lt;br /&gt;&lt;br /&gt;El diseño comienza por el desarrollo de pruebas que verifiquen lo que tiene que hacer el sistema. Se irán desarrollando nuevas pruebas que verifiquen más requisitos. Si en el proceso se ve la posibilidad de simplificar lo ya hecho, hay que hacerlo. Así, la primera vez que nos encontremos con un problema, lo solucionaremos de la manera más rápida posible. Las siguientes veces, se trata de flexibilizar la solución para acomodarla a nuevas necesidades.&lt;br /&gt;&lt;br /&gt;Lo más simple posible es aquello que comunique su función, no contenga código duplicado y tenga el menor número de clases y métodos.&lt;br /&gt;&lt;br /&gt;En el diseño se pueden usar gráficos, pero hay que ser conscientes de que entrañan el riesgo de que la funcionalidad del sistema que definen pueden ser comprobada a través de ellos. Se pueden usar gráficos en los primeros pasos de un diseño y luego convertir el diseño a código para eliminar este riesgo lo antes posible.&lt;br /&gt;&lt;br /&gt;La arquitectura del sistema se expresa a través de una metáfora que permite hablar sobre el sistema. Para obtener esta arquitectura se recoge un conjunto básico de historias y se cambiará a medida que el conocimiento sobre el sistema aumente.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Pruebas en XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; propone realizar las pruebas a la vez que el desarrollo. Antes de codificar una funcionalidad se debe crear una prueba que valide su funcionamiento. Como las pruebas son automáticas se pueden ejecutar en cualquier momento y verificar que el sistema sigue funcionando.&lt;br /&gt;&lt;br /&gt;Las pruebas permiten aprender sobre el sistema. Son realizadas por los desarrolladores, pero también por los clientes, que escriben pruebas que verifican si el sistema cumple con el funcionamiento descrito en sus historias de usuario. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Comenzar con XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A introducir &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; en un nuevo entorno se debe hacer paso a paso, comenzando por aquello que suponga el mayor problema. Normalmente se empieza por las pruebas y la planificación. Es importante reorganizar el espacio de trabajo para favorecer la comunicación desde el primer instante.&lt;br /&gt;&lt;br /&gt;Hay que cambiar la estrategia en las siguientes áreas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Pruebas&lt;/span&gt;: las pruebas otorgan confianza en el código. Hay que ir introduciendo pruebas en el código existente a medida que sea necesario modificarlo por cualquier razón.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Diseño&lt;/span&gt;: XP provocará un aumento en la refactorización. No se debe realizar al mismo tiempo que se añade una nueva funcionalidad. Los objetivos de la refactorización deben ser identificados cuanto antes y ser abordados antes de avanzar en funcionalidades nuevas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Planificación&lt;/span&gt;: se debe educar al cliente en las nuevas reglas que guían la planificación y convencerle para que escriba historias de usuario.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Gestión&lt;/span&gt;: una de las partes más difíciles es el cambio de mentalidad sobre la gestión del equipo. El gestor debe de dejar de tomar las decisiones que son responsabilidad de los programadores. Los programadores deben asumir la responsabilidad de su trabajo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Desarrollo&lt;/span&gt;: se debe aprender a desarrollar en pareja y el entorno debe facilitarlo.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ciclo de vida del proyecto en XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El ciclo de vida de &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; trata de adelantar cuanto lo máximo posible la puesta en producción de valor para el cliente, aunque sólo sea una parte de la funcionalidad. A partir de ahí, se irá incrementando el valor en las siguientes iteraciones.&lt;br /&gt;&lt;br /&gt;En una primera fase de &lt;span style="font-weight:bold;"&gt;exploración&lt;/span&gt; se debe analizar la viabilidad del proyecto y estudiar su utilidad y si tenemos las capacidades necesarias para llevarlo adelante. Esta fase termina en el momento en que existen suficientes historias de usuaria para una puesta en producción.&lt;br /&gt;&lt;br /&gt;En esta fase se explora la arquitectura del sistema a través de varias alternativas. Se exploran las tecnologías a usar para conocer sus límites y rendimiento. El cliente también debe aprender en esta etapa a escribir historias de usuario. Para ello debe recibir realimentación por parte de los desarrolladores hasta llegar al nivel adecuado.&lt;br /&gt;&lt;br /&gt;En la fase de &lt;span style="font-weight:bold;"&gt;planificación&lt;/span&gt; se recogen las historias más valiosas que puedan servir para una primera puesta en producción y se trata de estimar la fecha. A partir de este punto se realizan varias iteraciones. En la primera iteración se tratará de asentar la arquitectura del proyecto y en las subsecuentes iteraciones se irán incluyendo las historias de usuario seleccionadas.&lt;br /&gt;&lt;br /&gt;Posteriormente se pasará &lt;span style="font-weight:bold;"&gt;producción&lt;/span&gt;, para lo cual puede ser necesario hacer pruebas de rendimiento del sistema y refinarlo en base a los resultados.&lt;br /&gt;&lt;br /&gt;A partir de este momento el proyecto está en la fase de &lt;span style="font-weight:bold;"&gt;mantenimiento&lt;/span&gt;, que es el estado natural de un proyecto en XP. En esta fase se incorpora nueva funcionalidad manteniendo la existente, manejando las altas y bajas en el equipo.&lt;br /&gt;&lt;br /&gt;Cada nueva versión necesitará de una fase de exploración que puede implicar la refactorización de parte del sistema. También hay que responder a los problemas que puedan surgir en el funcionamiento normal del sistema, lo que puede disminuir la velocidad del equipo para aportar nueva funcionalidad. &lt;br /&gt;&lt;br /&gt;El día en que el cliente ni tiene nuevas historias es el momento en que se debe redactar el funcionamiento del sistema para la posteridad. Este es el &lt;span style="font-weight:bold;"&gt;fin del proyecto&lt;/span&gt;. También se puede llegar al fin del proyecto porque éste no reporte la rentabilidad esperada.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Roles en XP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En un equipo XP existen los siguientes roles:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Programador&lt;/span&gt;: programa y comunica sobre lo que hace. Debe buscar la sencillez del sistema. Es miembro de un equipo que le ayuda a mejorar.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cliente&lt;/span&gt;: decide lo que debe hacer el sistema en función de la información de que dispone y la que le da el avance del proyecto. También se encarga de escribir las historias que debe cumplir el sistema y crea pruebas para comprobarlo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Probador (tester)&lt;/span&gt;: ayuda al cliente a escribir y ejecutar las pruebas funcionales. Puede ser un programador.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Rastreador (tracker)&lt;/span&gt;: recoge las estimaciones, verifica su cumplimiento e informa al equipo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Consejero (coach)&lt;/span&gt;: vela por el cumplimiento del proceso. Su trabajo disminuye a medida que el equipo madura y se hace responsable del proceso.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Consultor&lt;/span&gt;: aporta conocimiento técnico al equipo en un determinado momento, pero no resuelve el problema por ellos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Jefe&lt;/span&gt;: responde a las necesidades del equipo para la realización el proyecto. Debe pedir explicaciones al equipo sobre su forma de trabajar y, si algo no tiene sentido, hacerlo saber para que el equipo lo corrija.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Observaciones generales&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; es necesario realizar moderadamente bien el conjunto de todas las prácticas para empezar a obtener resultados notables. Esto es porque las prácticas se apoyan unas en otras y es esta conjunción lo que asegura el buen funcionamiento de &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Las prácticas de &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; son simples, pero es difícil realizarlas de forma conjunta. Cuando hay problemas, se tiende a relajar la aplicación de las prácticas más exigentes y el proceso se desequilibra si no se corrige rápidamente. También se requiere humildad y coraje para reconocer lo que uno no sabe y preguntar por ello. Hay que estar dispuesto a colaborar.&lt;br /&gt;&lt;br /&gt;En ciertas condiciones hay que descartar &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt;, como cuando tratamos con equipos grandes, clientes desconfiados o tecnología que no soporta el cambio. Estos casos dificultan o imposibilitan la aplicación de algunas de las prácticas de &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt;, desestabilizando el proceso de desarrollo.&lt;br /&gt;&lt;br /&gt;Esto último es muy importante, puesto que por más que nos gusten las ideas que XP propone, puede ser contraproducente adoptar &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; a ciegas en determinados entornos en los que pueden llevar al caos. Sin embargo, aunque introducir el conjunto de prácticas de &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; no sea una buena opción, algunas de ellas son recomendables en sí mismas en el desarrollo de software, como la integración continua (hasta cierto grado), el uso de estándares de codificación y las pruebas auto&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Extreme Programming Explained&lt;/span&gt; (Kent Beck)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0321278658&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0321278658&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-5959844962074642646?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/5959844962074642646/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/06/apuntes-de-xp.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5959844962074642646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5959844962074642646'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/06/apuntes-de-xp.html' title='Apuntes de XP'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-4524854302576631115</id><published>2011-03-18T13:57:00.009+01:00</published><updated>2011-10-25T12:13:19.721+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>The Mythical Man-Month</title><content type='html'>Este libro, un clásico de referencia sobre la ingeniería del software, es una colección de ensayos en los que el autor, Frederick P. Brooks, expone sus experiencias como gestor en un gran proyecto de desarrollo.&lt;br /&gt;&lt;br /&gt;Aunque se trata de un libro de hace más de 30 años, que refleja experiencias de un proyecto realizado 20 años atrás, este libro sigue resultando valioso. En lugar de centrarse en los ya obsoletos problemas técnicos del proyecto,  se centra en los problemas organizacionales de los mismos, y en cómo gestionar a las personas involucradas en ellos.&lt;br /&gt;&lt;br /&gt;A continuación, haré un resumen de cada uno de los capítulos que forman parte de este libro:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;1. El pozo de alquitrán&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Los proyectos de software con como un pozo de alquitrán, en el cual uno se adentra sin darse cuenta y, cuando comienzan los problemas, luchar contra ellos sólo hace que uno se hunda más. &lt;br /&gt;&lt;br /&gt;No hay razón aparente para la dificultad de los proyectos, sino un cúmulo factores.  Para conocer la naturaleza de este problema es necesario identificar la finalidad de la programación y las satisfacciones y dificultades que entraña. &lt;br /&gt;&lt;br /&gt;Existen distintos productos de software en función su usuario final que requiere más o menos diseño, integración o pruebas, e implican diferentes grados de esfuerzo. Un producto que vaya ser usado por otros supone el triple de esfuerzo que un programa de uso privado. Un programa que va a ser usado dentro un sistema supone el triple de esfuerzo que uno que va a ser usado de forma independiente. Estas implicaciones son independientes entre sí, por lo que un producto de software que va a ser usado por sistema cuesta nueve veces más esfuerzo que un programa independiente de uso privado. &lt;br /&gt;&lt;br /&gt;La programación proporciona la satisfacción de crear cosas complicadas que sean de utilidad para los demás. Es algo tan maleable que permite hacer casi cualquier cosa. Sin embargo, se sufre la necesidad de perfección y el estar trabajando con objetivos impuestos por otros.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;2. El mito del mes-persona&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La principal causa de fracaso de los proyectos de software es la desviación respecto a la planificación estimada. Esto se debe al optimismo a la hora de estimar por parte de los programadores, que no tienen en cuenta que las ideas iniciales pueden ser incompletas e incluso erróneas. Además se carece de datos fiables sobre las estimaciones, lo que hace difícil justificar estimaciones que vayan en contra de los intereses del gestor o del propio cliente.&lt;br /&gt;&lt;br /&gt;A la hora de estimar, se suele caer en el error de creer que personas y meses son intercambiables.  Se olvida que al añadir más personas a una tarea se incrementa el esfuerzo total necesario debido a la necesidad de reorganizar las tareas, de formar a los nuevos miembros y al aumento de la intercomunicación.&lt;br /&gt;&lt;br /&gt;La ley de Brooks dice que: “Añadir gente a un proyecto retrasado lo retrasa más”.&lt;br /&gt;&lt;br /&gt;Como regla general, Brooks propone repartir el tiempo de un proyecto de la siguiente forma: 1/3 para diseño, 1/6 para la codificación, 1/4 para las pruebas de componentes y 1/4  para las pruebas de sistema. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;3. El equipo de cirujía&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Los buenos programadores son mucho más productivos que los malos. Además, los equipos, cuanto más pequeños sean menos los problemas de intercomunicación tendrán. &lt;br /&gt;&lt;br /&gt;Hay que favorecer el trabajo de los buenos programadores simplificando la comunicación dentro del equipo.&lt;br /&gt;&lt;br /&gt;Los equipos pequeños son demasiado lentos para realizar grandes sistemas y, por otra parte, un equipo de mucha gente es costoso, lento e ineficiente, y produce sistemas que no están conceptualmente integrados.&lt;br /&gt;&lt;br /&gt;Una solución es tener un equipo organizado en torno a un programador jefe a quien da apoyo, de la misma manera que un equipo de cirugía. De esta forma se logra mantener la integridad de un producto de un número reducido de mentes con la ayuda de unos cuantos colaboradores, reduciendo la comunicación de forma radical.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;4. Aristocracia, democracia, y diseño de sistemas&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La consideración más importante en el diseño de un sistema es preservar la integridad conceptual.  La integridad conceptual otorga mayor facilidad de uso, y permite construir y probar el sistema más rápidamente. &lt;br /&gt;Para lograrla, el diseño debe ser fruto de una sola mente o de un grupo reducido de mentes que están de acuerdo. La separación entre arquitectura e implementación es la forma de conseguir esta integridad conceptual en sistemas grandes.&lt;br /&gt;&lt;br /&gt;Alguien debe controlar los conceptos fijando la arquitectura, pero ello mejora la creatividad en la implementación, puesto que permite enfocar el esfuerzo. &lt;br /&gt;&lt;br /&gt;De cualquier manera, arquitectura (requisitos), implementación (diseño) y realización (programación) pueden discurrir en paralelo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;5. El efecto del segundo sistema&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Una buena comunicación puede dar al arquitecto una lectura adecuada de los costes y al constructor confianza en el diseño, sin difuminar la clara división de responsabilidades entre ellos.&lt;br /&gt;&lt;br /&gt;Para que el arquitecto pueda influir con éxito en la implementación debe tener en cuenta que:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Es el constructor quien tiene la responsabilidad de la implementación. El arquitecto solo sugiere.&lt;/li&gt;&lt;li&gt;El arquitecto debe ser capaz de sugerir una forma de implementar lo que especifica, pero debe estar preparado para aceptar cualquier otra forma igualmente válida.&lt;/li&gt;&lt;li&gt;Debe escuchar las sugerencias del constructor para mejorar la propia arquitectura.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;El segundo sistema es el más peligroso, porque se tiende a sobrediseñarlo. Asignar a priori valores de memoria y tiempo para cada función ayuda a detectar el sobrediseño durante la implementación.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;6. Pasar la Palabra&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A la hora de redactar el diseño de un sistema, por grande que sea, es mejor que lo hagan pocas personas (preferiblemente una) para que el resultado sea consistente.&lt;br /&gt;&lt;br /&gt;Se necesita tanto una descripción formal que aporte precisión como una descripción en prosa que aporte claridad. Una de ellas debe ser la de referencia y la otra servir como apoyo. Utilizar una implementación como definición es una fuente de problemas.&lt;br /&gt;&lt;br /&gt;Es importante registrar y publicar todas las consultas de los desarrolladores a los arquitectos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;7. ¿Por qué cayó la Torre de Babel?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Si no hay comunicación cada uno hace sus propias suposiciones, provocando retrasos, desajuste funcional y errores en el sistema. Los equipos de deben comunicar de todas las formas posibles, tanto informal como formalmente.&lt;br /&gt;&lt;br /&gt;Se debe especificar cuanto antes el conjunto de documentos a través de los cuales se producirá la comunicación formal en el proyecto. Esta documentación debe estar al alcance de cualquier miembro del equipo. Se debe actualizar constantemente y resaltar los cambios realizados respecto a la última versión.&lt;br /&gt;&lt;br /&gt;Sin embargo, Parnas propone que nadie debe ver las interioridades de ninguna otra parte que no sea aquella en la que se está trabajando. Sólo se deben publicar las interfaces.&lt;br /&gt;&lt;br /&gt;La organización debe encargarse de reducir la cantidad de comunicación y coordinación necesaria, mediante la división de tareas y la especialización en las funciones.&lt;br /&gt;&lt;br /&gt;En cada proyecto se deben establecer dos roles, el productor y el arquitecto o director técnico, que requieren de distintas habilidades. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;8. Apuntando para disparar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No se puede estimar el esfuerzo total de un proyecto estimando el tiempo de codificación y extrapolándolo a las demás tareas. &lt;br /&gt;&lt;br /&gt;Tampoco sirve extrapolar la construcción de pequeños sistemas a proyectos de sistemas. El incremento en el esfuerzo es una potencia del tamaño del proyecto. &lt;br /&gt;&lt;br /&gt;Hay estudios que dicen que los programadores sólo dedican el 50% de su tiempo a la programación y el resto a otras tareas. &lt;br /&gt;&lt;br /&gt;Otros estudios sobre la productividad indican que ésta se mantiene constante en términos de secuencias elementales. La productividad se incrementa por 5 cuando se pasa a usar un lenguaje de alto nivel.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;9. 10 libras en una bolsa de 5&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Además del tiempo de ejecución, el espacio de memoria que ocupa un programa es su coste principal. Se deben establecer límites de tamaño en cada función para que los costes no se disparen.&lt;br /&gt;&lt;br /&gt;Durante la implementación, los arquitectos deben velar por la continuidad de la integridad del sistema.&lt;br /&gt;&lt;br /&gt;Para poder hacer un buen balance entre tiempo y espacio, el equipo debe estar entrenado en las peculiaridades del lenguaje de programación y de la máquina que se están usando.&lt;br /&gt;&lt;br /&gt;Todo proyecto de programación necesita una librería de componentes estándar.&lt;br /&gt;&lt;br /&gt;Los programas sencillos y rápidos son resultado de la innovación estrategia más que de una buena táctica. Esto se puede lograr a través  del uso de un nuevo algoritmo o de rehacer la representación de los datos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;10. La hipótesis documental&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Sólo unos pocos de todos los documentos del proyecto son el eje sobre el que gira toda la gestión del proyecto: objetivos, manual, calendario, presupuesto, diagrama de organización y situación física de los miembros del equipo. &lt;br /&gt;&lt;br /&gt;El gestor debe formalizar este conjunto de documentos. Mantener estos documentos proporciona un mecanismo de vigilancia y alarma.&lt;br /&gt;&lt;br /&gt;El gestor debe encargarse de que todo el mundo vaya en la misma dirección a través de la comunicación, y no tomando todas las decisiones. Solo una pequeña parte de las tareas del gestor están relacionadas con información que está fuera de su mente.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;11. Planea deshacerte de uno&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Cuando se pasa de un entorno protegido a uno de producción es necesario un paso intermedio de prueba. Al probar el primer sistema construido se suele comprobar que éste es demasiado lento, grande o difícil de usar, y que debe ser rediseñado.&lt;br /&gt;&lt;br /&gt;Este rediseño se puede hacer de golpe o pieza a pieza, pero habrá que hacerlo de todas formas. Si se entrega el primer sistema, esto será en detrimento del usuario y del desarrollador que lo debe mantener. Por tanto, debe incluirse en la planificación el rediseño de la primera solución. &lt;br /&gt;&lt;br /&gt;Las necesidades del cliente y la percepción de las mismas cambiarán a medida que avanza el proyecto. La maleabilidad del software hace que los requerimientos no dejen de cambiar porque los cambios se presuponen fáciles. Algunos de estos cambios son válidos y hay que estar preparados para poder afrontarlos. Las técnicas que nos permiten hacer esto son conocidas pero no son usadas.&lt;br /&gt;&lt;br /&gt;Los esfuerzos de los desarrolladores son tentativas de satisfacer los requisitos, sujetos a modificaciones y, por tanto, hace que sean reacios a documentarlos.&lt;br /&gt;&lt;br /&gt;Para acomodar una organización al cambio los miembros de los equipos de ben ser intercambiables y reubicables, tanto en la parte de gestión como en la técnica. Una posible solución es la propuesta organizar el equipo en torno a un programador jefe.&lt;br /&gt;&lt;br /&gt;El mantenimiento del software consiste principalmente en reparar defectos de diseño, añadir nuevas funcionalidades y adaptarse a los cambios en el entorno o la configuración. El coste de mantenimiento de un programa es aproximadamente el 40% del coste de su desarrollo.&lt;br /&gt;&lt;br /&gt;El número de errores encontrados aumenta con el número de usuarios. El número de errores a lo largo de la vida de un proyecto primero aumenta y luego se estabiliza. &lt;br /&gt;Al corregir un error existe una alta probabilidad de introducir otros, por los que se debe disponer de casos de prueba que aseguren que esto no se produce. &lt;br /&gt;&lt;br /&gt;Durante la vida de un proyecto el número de módulos se incrementa de forma lineal, pero el número de módulos afectados por las modificaciones se incrementa de forma exponencial. Toda corrección tiende a romper la estructura e incrementa la entropía y el desorden del sistema. Inevitablemente, se llegará a un punto donde la mejor solución es el rediseño.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;12. Herramientas precisas&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Todo proyecto necesita herramientas personalizadas, por lo que el gestor debe establecer la filosofía para establecer los recursos necesarios para su construcción.&lt;br /&gt;&lt;br /&gt;Es necesario instrumentalizar las máquinas sobre las que se va probar para poder extraer resultados de ellas. A la hora de probar en la máquina es mejor repartir periodos separados de tiempo para los distintos miembros.&lt;br /&gt;&lt;br /&gt;La documentación voluminosa introduce mayor complejidad al proyecto. &lt;br /&gt;&lt;br /&gt;Se debe construir de forma temprana un simulador de rendimiento que analice el programa desde fuera, y hay que prestar atención a lo que dice.&lt;br /&gt;&lt;br /&gt;Las mejores herramientas que existen actualmente (1975) son los lenguajes de alto nivel (aumentan el rendimiento y facilitan la depuración) y la programación interactiva (reduce el tiempo de respuesta en la depuración).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;13. El todo y las partes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Una buena arquitectura hace que un sistema sea más fácil de usar, más fácil de construir y que tenga menos errores. Antes de empezar la construcción se debe entregar las especificaciones al grupo de test, que debe comprobar si está completa y es clara.&lt;br /&gt;&lt;br /&gt;Diseñar de lo general a lo específico refinando la especificación paso a paso reduce los errores y permite volver atrás cuando sea necesario. Hay que usar una notación de tan alto nivel como sea posible en cada paso.&lt;br /&gt;&lt;br /&gt;La programación estructurada es el diseño de programas formados por un conjunto reducido de estructuras de control.&lt;br /&gt;&lt;br /&gt;Se demuestra que en la primera interacción de depuración se un progreso hace tres veces mayor que en las subsecuentes. La depuración de un sistema siempre lleva más tiempo de lo planeado.&lt;br /&gt;&lt;br /&gt;Se debe empezar la depuración sólo cuando las piezas parezcan funcionar, en vez  de adelantarlo a cuando se hayan detectado errores pero sigan sin ser corregidos. &lt;br /&gt;&lt;br /&gt;Merece la pena construir código de apoyo para la depuración, que puede llegar a ser el 50% del código a depurar.&lt;br /&gt;&lt;br /&gt;Durante la depuración se deben añadir los componentes de uno en uno. Es mejor introducir grandes cambio de forma poco frecuente porque esto introduce menos inestabilidad. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;14. Vislumbrando una catástrofe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Los proyectos se retrasan día a día. Esto es difícil de reconocer, de prevenir y de arreglar. Para poder controlar un proyecto es necesario tener un calendario con hitos concretos y bien definidos y fechas identificables.&lt;br /&gt;&lt;br /&gt;Diversos estudios han demostrado que las estimaciones no suelen variar hasta el arranque del proyecto, posteriormente se van reduciendo las sobreestimaciones  y, tres semanas antes del fin estimado del proyecto, lo que cambian son las infraestimaciones.&lt;br /&gt;&lt;br /&gt;La planificación de ruta crítica permite identificar que desviaciones son las que realmente importan. Se debe identificar esta ruta crítica lo antes posible.&lt;br /&gt;&lt;br /&gt;Todo jefe necesita ser alertado de las excepcionen que precisen de acciones correctoras y que se muestre el estado del proyecto para su conocimiento. Esto es difícil puesto que los subordinados temen la intromisión del jefe en sus responsabilidades. Se debe disponer de técnicas de revisión que ofrezcan el estado del proyecto a todo el mundo. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;15. La otra cara&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La documentación para el usuario es tan importante como el propio producto. Es importante también para el autor como memoria de lo que se ha hecho.&lt;br /&gt;&lt;br /&gt;Por regla general no se entrega una buena documentación porque no se ha instruido a los desarrolladores en cómo hacerlo de forma efectiva y económica.&lt;br /&gt;&lt;br /&gt;La documentación crítica para el usuario se debe establecer antes de la construcción ya que contiene decisiones de planificación básica.&lt;br /&gt;&lt;br /&gt;A nivel de documentación interna, para mantener la documentación actualizada es necesario incorporarla junto con el código fuente. Se debe explicar por qué las cosas son como son, no solamente cómo están hechas. Los lenguajes de alto nivel permiten técnicas de auto-documentación dentro del propio código.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;16. No hay balas de plata – Esencia y accidente&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El autor compara el desarrollo de software con los hombres-lobo, gente normal que se convierte de repente en algo fuera de control que solo pueden ser eliminados con una bala de plata. Sin embargo, no existen balas de plata para el software que den una mejora de un orden de magnitud en su desarrollo, aunque existen innovaciones que de forma conjunta sí pueden ofrecer esta mejora.&lt;br /&gt;&lt;br /&gt;La construcción de software implica tareas complejas, acomodar sus estructuras conceptuales, y tareas accidentales, representarlas en lenguajes de programación. &lt;br /&gt;&lt;br /&gt;Las dificultades esenciales del desarrollo de software son la complejidad, conformidad, variabilidad e invisibilidad a la hora de acomodar las complejas estructuras conceptuales que implica.&lt;br /&gt;&lt;br /&gt;El desarrollo de software también implica tareas accidentales, que son la representación en lenguajes de programación.&lt;br /&gt;&lt;br /&gt;Las mejoras de los últimos tiempos han estado enfocadas en solucionar las dificultades accidentales a través de:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Lenguajes de alto nivel.&lt;/li&gt;&lt;li&gt;Tiempo de ejecución compartido.&lt;/li&gt;&lt;li&gt;Entornos de programación unificados.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Sin embargo, la mayor parte del tiempo se dedica a acomodar estructuras conceptuales abstractas de gran complejidad y, por tanto, es esta tarea esencial la que se debe atacar. Se han propuesto las siguientes formas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Avances en lenguajes de alto nivel.&lt;/li&gt;&lt;li&gt;Programación orientada a objetos.&lt;/li&gt;&lt;li&gt;Inteligencia artificial.&lt;/li&gt;&lt;li&gt;Sistemas expertos.&lt;/li&gt;&lt;li&gt;Programación automática.&lt;/li&gt;&lt;li&gt;Programación gráfica.&lt;/li&gt;&lt;li&gt;Verificación de programas.&lt;/li&gt;&lt;li&gt;Entornos y herramientas de trabajo.&lt;/li&gt;&lt;li&gt;Estaciones de trabajo.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Estas alternativas, aunque introducen mejoras, no han alcanzado los niveles esperados. Es necesario atacar la esencia del software elevando el nivel de abstracción que implica su desarrollo. Los avances más prometedores en este sentido son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Comprar en lugar de desarrollar.&lt;/li&gt;&lt;li&gt;Refinado de requisitos y prototipado rápido.&lt;/li&gt;&lt;li&gt;Desarrollo incremental.&lt;/li&gt;&lt;li&gt;Encontrar y educar a los mejores diseñadores.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;17. “No hay balas de plata” revisado&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En este capítulo el autor rebate las críticas recibidas al artículo presentado en el capítulo anterior “No hay balas de plata”.  Sobre todo aquellas que van contra el principal argumento del mismo (que no hay ningún avance en el mundo del software que pueda dar por sí solo una mejora de n orden de magnitud), para presentar la propia bala de plata de cada investigador de turno.&lt;br /&gt;&lt;br /&gt;El autor se reafirma en la idea de que la complejidad es la mayor dificultad inherente al software, aunque la mayor parte de esta complejidad se suele deber a problemas de organización de la propia realidad que se intenta modelar. Esta complejidad se puede atacar aumentando el nivel de abstracción de los elementos utilizados y manteniendo en todo momento sistemas que funcionen y que incorporen nuevas funcionalidades de forma incremental.&lt;br /&gt;&lt;br /&gt;Se introduce el enfoque a la calidad, que aumentaría de la productividad reduciendo el tiempo dedicado a la corrección de errores. &lt;br /&gt;&lt;br /&gt;La productividad también aumenta con mejores equipos y herramientas de trabajo y el uso de la programación orientada a objetos (que promueve la modularidad, la encapsulación, la herencia y el tipado de datos).  Aunque se lamenta de la poca introducción de la orientación a objetos y la reutilización.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;18. Proposiciones de “El mito del mes-persona”&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Este capítulo muestra una recopilación de las afirmaciones expuestas en el libro a modo de resumen.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;19. “El mito del mes-persona” 20 años después&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Este capítulo es una revisión del libro hecha tras 20 años por el propio autor. En ella expone los argumentos que mantiene tras este tiempo y aquellos en los que ha cambiado de opinión.&lt;br /&gt;&lt;br /&gt;El autor mantiene que la integridad conceptual es el factor más importante para la facilidad de uso de un sistema. Esta integridad conceptual suele lograrse cuando el producto ha sido diseñado por una única persona, pero este enfoque no es productivo para grandes sistemas que sufren presiones competitivas.&lt;br /&gt;&lt;br /&gt;En estos entornos es necesario tener un arquitecto (o un grupo de ellos organizados de forma jerárquica) que se encargue de la integridad conceptual de todos los aspectos del producto percibibles por el usuario. Además sus tareas estarán separadas de la implementación.&lt;br /&gt;&lt;br /&gt;Otro peligro que se recalca en el desarrollo de sistemas es el de cargarlos de funcionalidades de mínimo valor que compliquen el diseño y el uso de los mismos. Se debe ser consciente de quienes son los usuarios y ponderar las nuevas capacidades que se introducen en función del mayor valor ofrecido al mayor número de usuarios.&lt;br /&gt;&lt;br /&gt;En lo que sí cambia de opinión es en el consejo de que el primer sistema implementado deba ser desechado. Esto era una consecuencia de la aplicación del desarrollo en cascada, que asume que los pasos del proyecto avanzan uno a continuación de otro, y supone que todos se realizan de forma correcta. El sistema se construye de una sola vez y se asume que todos los errores se introducen en la implementación.&lt;br /&gt;&lt;br /&gt;Un modelo de desarrollo incremental permitiría el refinamiento progresivo del sistema. Se puede construir un sistema inicial de funcionalidad limitada y, a partir del cual hacer crecer el sistema introduciendo nuevas funcionalidades. De esta forma se pueden adelantar las pruebas del sistema y se puede entregar un sistema que funciona cuando sea necesario, aunque de funcionalidad reducida.&lt;br /&gt;&lt;br /&gt;En cuanto al ocultamiento de información que Parnas proponía y del que el autor desconfiaba, éste se retracta y asume que los programadores son más efectivos si no están expuestos a las interioridades de módulos que no son de su propiedad.&lt;br /&gt;&lt;br /&gt;El avance en el desarrollo del software se producirá al aumentar el nivel de abstracción de los elementos que se utilizan. En este sentido se han dado los siguientes pasos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;La definición del ocultamiento de información de los módulos hecha por Parnas.&lt;/li&gt;&lt;li&gt;La aparición de los tipos de dato abstractos de los que pueden derivar otros objetos.&lt;/li&gt;&lt;li&gt; La programación orientada a objetos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;El hecho de disponer de clases diseñadas y probadas para ser reutilizadas es lo que permitiría elevar dicho nivel de abstracción.&lt;br /&gt;&lt;br /&gt;La Ley de Brooks (añadir más gente a un proyecto retrasado lo retrasa más) ha sido refinada gracias a varios estudios, aunque se mantiene como una buena aproximación a la realidad. En realidad, añadir más gente a un proyecto retrasado aumenta su coste, pero no siempre lo retrasa.&lt;br /&gt;&lt;br /&gt;Otra idea que se ha reforzado durante este tiempo es la importancia de las personas que forman parte de los proyectos, y cómo los factores humanos deben ser tomados en consideración. Es importante dar responsabilidades a la gente y no centralizar todo en una única entidad, puesto que esto fomenta la creatividad.&lt;br /&gt;&lt;br /&gt;Se hace eco del avance en el campo de la informática y de la explosión del número de ordenadores. Esto ha cambiado la forma de desarrollar el software y creado una nueva industria, los programas empaquetados.&lt;br /&gt;&lt;br /&gt;Respecto al futuro de la ingeniería del software, presume que, a través del conocimiento, será capaz de lidiar en el futuro podrá con la complejidad del comportamiento humano y los aspectos no lineales que introduce.&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201835959&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201835959&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-4524854302576631115?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/4524854302576631115/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/03/mythical-man-month.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4524854302576631115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4524854302576631115'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/03/mythical-man-month.html' title='The Mythical Man-Month'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-8832031045817559761</id><published>2011-01-05T12:33:00.017+01:00</published><updated>2011-10-25T12:14:36.260+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Calidad'/><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Clean Code</title><content type='html'>Durante los últimos meses he estado leyendo y releyendo el libro &lt;span style="font-weight:bold;"&gt;“Clean Code: A Handbook of Agile Software Craftmanship”&lt;/span&gt; de &lt;span style="font-weight:bold;"&gt;Robert Martin&lt;/span&gt;. En este libro, el autor trata por qué hemos de escribir código limpio y cómo hacerlo.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_WQMxntNMWT0/TSRbBBi43LI/AAAAAAAALCw/Ub0vyDHg54Y/s1600/CleanCode.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 301px; height: 400px;" src="http://3.bp.blogspot.com/_WQMxntNMWT0/TSRbBBi43LI/AAAAAAAALCw/Ub0vyDHg54Y/s400/CleanCode.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5558667913234799794" /&gt;&lt;/a&gt;&lt;br /&gt;Código Limpio. Este tema es algo que me interesa particularmente en estos momentos. Cuando eres un desarrollador con responsabilidades puntuales dentro de un proyecto y sin relevancia ninguna en cuanto a las decisiones que toma el arquitecto de turno, lo único importante es quitarte el muerto de encima cuanto antes para evitar las típicas preguntas de: ¿Cómo vamos (¿Vamos? Pero si lo estoy haciendo sólo yo…)? ¿En qué estado está esta tarea? ¿Qué pongo en el Project, 80%, 90%...? ¿Podemos hacer la entrega ya?&lt;br /&gt;&lt;br /&gt;Sin embargo, cuando tienes cierto grado de responsabilidad sobre un proyecto y te interesa que su evolución no se complique es importante hacer entender a los miembros del equipo que la responsabilidad de cada uno va más allá de quitarse el muerto de encima, sino que cada uno debe hacer lo mejor  que pueda por tener un código lo más comprensible posible. Al código comprensible es a lo que &lt;span style="font-weight:bold;"&gt;Robert Martin&lt;/span&gt; llama código limpio.&lt;br /&gt;&lt;br /&gt;Este libro está dividido en tres partes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;En una primera parte, se explica qué es el código limpio y cómo llegar a él.&lt;/li&gt;&lt;li&gt;La segunda parte son ejemplos más complejos de refactorización de código en busca de código más limpio.&lt;/li&gt;&lt;li&gt;La tercera parte es una recopilación de pistas que ayudan a encontrar código que no está todo lo bien que debería estar y que debería ser refactorizado.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;En este resumen del libro me voy a centrar en la primera parte de él, puesto que la segunda y la tercera parte son bastante directas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 1 - NOMBRES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La lectura del código es la actividad a la que se dedica más tiempo, incluso para escribir nuevo código hay que leer lo que ya hay escrito. Un mal código puede llegar a arruinar un proyecto, dificultando las modificaciones y alargando los plazos de entrega. El único responsable de ello es el programador que no se toma en serio su trabajo y no es profesional. &lt;br /&gt;&lt;br /&gt;Para evitar estas situaciones se debe hacer un código limpio, pero, ¿qué es código limpio?. Según varios autores conocidos, las características del código limpio son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Fácil de leer, expresivo y sencillo.&lt;/li&gt;&lt;li&gt;Probado mediante tests automáticos.&lt;/li&gt;&lt;li&gt;Hace una única cosa.&lt;/li&gt;&lt;li&gt;No existe duplicidad en él.&lt;/li&gt;&lt;li&gt;Utiliza el menor número de elementos posibles.&lt;/li&gt;&lt;li&gt;Realiza abstracciones de elementos similares.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Para conseguir un código limpio se debe prestar atención a cada uno de los elementos que componen un sistema a nivel de código: variables, funciones, clases, comentarios, tests y el propio sistema. Además existen una serie de aspectos, como son la diferenciación entre objetos y estructuras de datos, el comportamiento en los límites del sistema, el manejo de errores y la concurrencia que afectan directamente al código y a su comprensión. Capítulo a capítulo se va analizando cómo mejorar  en cada uno de estos elementos&lt;br /&gt;&lt;br /&gt;Tembién  habla de la regla del Boy Scout “&lt;span style="font-style:italic;"&gt;Hay que dejar el código mejor de cómo lo encontraste&lt;/span&gt;”. Esto va en la línea de la mejora continua del código y de la imposibilidad de hacerlo perfecto a la primera.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 2 - NOMBRES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Un buen nombre da mucha más información que cualquier otra cosa&lt;/span&gt;. Para conseguir buenos nombres hay que usar nombres descriptivos y claros. Deben ser legibles y evitar codificaciones complejas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 3 - FUNCIONES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Una buena función es aquella de la que se puede inferir su comportamiento de un solo vistazo&lt;/span&gt;. Para ello deben ser cortas, hacer una única cosa y mantenerse dentro del mismo nivel de abstracción.&lt;br /&gt;&lt;br /&gt;Es importante usar buenos nombres y reducir al mínimo el número de argumentos. Pero lo principal es eliminar toda la duplicidad.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 4 - COMENTARIOS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Los comentarios no pueden maquillar el mal código&lt;/span&gt;. La necesidad de comentarios para aclarar algo es síntoma de que hay código mal escrito que debería ser rediseñado. Es preferible expresarse mediante el propio código.&lt;br /&gt;&lt;br /&gt;Hay situaciones en las que los comentarios son apropiados, como cuando tratan de:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Aspectos legales del código.&lt;/li&gt;&lt;li&gt;Advertir de consecuencias.&lt;/li&gt;&lt;li&gt;Comentarios TODO.&lt;/li&gt;&lt;li&gt;Remarcar la importancia de algo.&lt;/li&gt;&lt;li&gt;Javadocs en APIs públicas.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Sin embargo, en el resto de los casos pueden llevar a confusión y deberían ser evitados.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 5 - FORMATEO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El formateo afecta directamente a la legibilidad del código. &lt;span style="font-weight:bold;"&gt;El código se lee de arriba abajo y de izquierda a derecha&lt;/span&gt;. Los espacios verticales y horizontales permiten separar ideas y conceptos distintos.&lt;br /&gt;&lt;br /&gt;Se debe mantener un estilo uniforme, y para ello se debe consensuar con todo el equipo las reglas de formateo. &lt;span style="font-weight:bold;"&gt;Las reglas elegidas no son tan importantes como el hecho de que todo el mundo se atenga a ellas.&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 6 - OBJETOS Y ESTRUCTURAS DE DATOS.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No todo se puede solucionar usando sólo objetos o sólo estructuras de datos. &lt;span style="font-weight:bold;"&gt;Hay que aprender a diferenciar en qué situaciones son más convenientes unos u otros&lt;/span&gt;. Los objetos esconden sus datos y exponen funciones que permiten manipularlos, mientras que las estructuras de datos exponen datos pero no tiene funciones que operen sobre ellos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 7 - MANEJO DE ERRORES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El código de manejo de errores oculta la verdadera funcionalidad del código. &lt;span style="font-weight:bold;"&gt;Hay que mantenerlo lo más separado posible de la lógica de negocio&lt;/span&gt; para no dificultar la comprensión de ésta última. &lt;br /&gt;&lt;br /&gt;Para no complicar el manejo de errores hay que escribir los bloques &lt;span style="font-style:italic;"&gt;try-catch-finally&lt;/span&gt; en primer lugar permite identificar los puntos del programa en los cuáles se puede producir una excepción. Se deben usar excepciones en lugar de códigos de retorno. Las excepciones deben proporcionar suficiente información sobre el error y el momento en que se ha producido. Además, las excepciones no comprobadas son menos invasivas a nivel de código.&lt;br /&gt;&lt;br /&gt;También se debe evitar pasar &lt;span style="font-style:italic;"&gt;null&lt;/span&gt; como parámetro de una llamada a un método o devolverlo como valor de retorno. Esto introduce complejidad adicional debido a las comprobaciones necesarias.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 8 - FRONTERAS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Los sistemas dependen de paquetes de terceros o de componentes desarrollados por otros equipos. &lt;span style="font-weight:bold;"&gt;Hay que definir de forma clara la frontera entre el código y el exterior&lt;/span&gt; para poder acomodar de forma sencilla los futuros cambios, minimizando las partes de nuestro código que dependan de elementos externos.&lt;br /&gt;&lt;br /&gt;Los tests ayudan a experimentar con el código externo viendo cómo puede cubrir nuestras necesidades. También permiten comprobar que las nuevas versiones de la librería siguen cumpliendo con nuestras necesidades.&lt;br /&gt;&lt;br /&gt;Encapsular el conocimiento adquerido a través de los tests en un interfaz entre nuestro sistema y el código de terceros permite localizar en ún único punto las modificaciones debidas a posibles cambios en código que está fuera de nuestro control.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 9 - TESTS UNITARIOS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En &lt;span style="font-weight:bold;"&gt;TDD&lt;/span&gt; los tests de seben escribir en primer lugar. Las 3 reglas de &lt;span style="font-weight:bold;"&gt;TDD&lt;/span&gt; son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;No se debe escribir código de producción hast que no se tenga un test unitario que falle.&lt;/li&gt;&lt;li&gt;No se debe  escribir más de un test unitario que lo necesario para que éste falle.&lt;/li&gt;&lt;li&gt;No se debe escribir más código de producción uqe el necesario para que pase un tests unitario que fallaba.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;Se debe dar la misma importancia al código de test que al de producción. Los tests permiten que el código de producción se pueda modificar sin temor a introducir nuevos errores, asegurando su mantenibilidad. &lt;br /&gt;&lt;br /&gt;El número de assert por cada test debe ser lo más bajo posible. Se debe testear un único concepto en cada test, lo que permite ir aclarando los distintos conceptos progresivamente, mejorando el conocimiento sobre el código.&lt;br /&gt;&lt;br /&gt;Las reglas &lt;span style="font-weight:bold;"&gt;FIRST&lt;/span&gt; sobre el código de test son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Fast&lt;/span&gt;: Se deben ejecutar rápido y muy a menudo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Independent&lt;/span&gt;: Las condiciones de un test no deben depender de un test anterior.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Repeteable&lt;/span&gt;: Se deben poder ejecutar en cualquier entorno.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Self-Validating&lt;/span&gt;: El propio test debe decir si se cumple o no, no debe hacer falta realizar comprobaciones posteriores al test.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Timely&lt;/span&gt;: Los tests se deben escribir en el momento adecuado, que es justo ante de escribir el código de producción, lo que permite escribir código fácilmente testeable.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 10 – CLASES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Las clases se deben organizar situando en primer lugar las constantes públicas, después las variables estáticas privadas, variables de instancia privadas y, a continuación, los métodos. Los métodos privados se encuentran junto a los métodos públicos que los usan.&lt;br /&gt;&lt;br /&gt;Se debe mantener la encapsulación de las clases. Las clases deben ser pequeñas y con un número reducido de responsabilidades. Se consigue una alta cohesión si todos los métodos de una clase hacen uso de todas sus variables privadas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Las nuevas funcionalidades se deben de introducir extendiendo el sistema, no modificando el código existente&lt;/span&gt;. Las clases concretas contienen detalles de implementación y las clases abstractas expresan conceptos. La dependencia en clases concretas es un riesgo en caso de cambio. Según el principio de inversión de dependencia las clases deben depender de abstracciones.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 11 – SISTEMAS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Es importante reconocer y separar las distintas responsabilidades de un sistema.&lt;br /&gt;&lt;br /&gt;En primer lugar, se deben separar el proceso de construcción de un sistema de su uso. El proceso de construcción se encarga de crear y conectar entre sí los objetos necesarios para la ejecución de la aplicación. Se debe modularizar y separar de la lógica de ejecución, permitiendo una estrategia independiente para resolver las dependencias de la aplicación.&lt;br /&gt;&lt;br /&gt;La inyección de dependencias permite que los objetos sólo se encarguen únicamente de la lógica de negocio. Un elemento contenedor se encarga de inyectar las dependencias de cada objeto de forma externa.&lt;br /&gt;&lt;br /&gt;No se puede construir sistemas de forma correcta a la primera hay que ir implementando las historias de que se dispone, y después refactorizar  y expandir el sistema para seguir implementando nuevas historias. &lt;span style="font-weight:bold;"&gt;TDD&lt;/span&gt;, refactorización y código limpio permiten esto a nivel de código.&lt;br /&gt;&lt;br /&gt;A nivel de sistema, es difícil crecer de sistemas simples a sistemas complejos debido a las dependencias en la arquitectura que se usa. Para evitar estos problemas, se deben separar las distintos responsabilidades de un sistema. Para lograr esta separación se pueden usar &lt;span style="font-weight:bold;"&gt;proxys&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;frameworks AOP Java puros&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;aspectos AspectJ&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Se debe construir la lógica de la aplicación en base a POJOs a través de tests, e ir  evolucionando de lo simple a lo complicado, interconectando los distintos aspectos necesarios. &lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 12 – EMERGENCIA&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Las siguientes 4 reglas dadas por &lt;span style="font-weight:bold;"&gt;Kent Beck&lt;/span&gt; permiten crear buenos diseños según se trabaja en ellos, conocer nuestro sistema y aplicar buenos principios de diseño:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Ejecutar todos los tests&lt;/span&gt;: Los tests verifican que el sistema se comporta según lo esperado. Al construir un sistema testeable se intenta que las clases sean simples y tengan un único propósito, y se trata de reducir el acoplamiento.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Eliminar la duplicación&lt;/span&gt;: La duplicación implica trabajo adicional, más riesgo y mayor complejidad.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Expresar la intención del programador&lt;/span&gt;:  Usar un código lo más expresivo posible facilita el mantenimiento. Se deben escoger buenos nombres, funciones y clases pequeñas y tests bien escritos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Minimizar el número de clases y métodos&lt;/span&gt;:  Siguiendo las recomendaciones anteriores uno se puede exceder creando demasiadas clases pequeñas. Hay que tener cuidado y mantener un número reducido de clases.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;Durante la refactorización de puede aplicar todo nuestro conocimiento para mejorar el diseño: aumentar la cohesión, reducir el acoplamiento, separar responsabilidades, reducir funciones y clase, escoger nombres mejores, etc. &lt;br /&gt;&lt;br /&gt;Se dedicar tiempo a estas tareas después hacer que el software funcione. No se debe  pasar a la siguiente tarea sin repasar lo hecho. &lt;span style="font-weight:bold;"&gt;Es imposible conseguir un código limpio a la primera, hay que repasarlo una y otra vez para conseguir mejorarlo progresivamente.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Capítulo 13 – CONCURRENCIA&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La concurrencia es otro de los aspectos que pueden estar presentes en el código. Permite desacoplar lo que que ocurre de cuándo ocurre, y mejorar tanto el rendimiento como la estructura de una aplicación.&lt;br /&gt;&lt;br /&gt;Desde el punta de vista estructural se puede percibir la aplicación como un grupo de computadoras colaborando entre sí, haciendo el sistema más fácil de entender y permitiendo separar las responsabilidades. La concurrencia permite mejorar los tiempos de respuesta y la eficiencia de una aplicación.&lt;br /&gt;&lt;br /&gt;Se deben tener en cuenta las siguientes ideas sobre la concurrencia:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Introduce cierta sobrecarga.&lt;/li&gt;&lt;li&gt;Es compleja de manejar.&lt;/li&gt;&lt;li&gt;Los errores causados por ella son difícilmente reproducibles&lt;/li&gt;&lt;li&gt;Normalmente requiere cambios en el diseño.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;El problema de la concurrencia es que los distintos hilos de una aplicación pueden entrelazarse siguiendo múltiples flujos de ejecución, lo que puede provocar problemas inesperados en situaciones normales.&lt;br /&gt;&lt;br /&gt;Para defendernos de los problemas de concurrencia es importante que cada clase tenga una única responsabilidad,seperando la gestión de hilos se del resto del código. Hay que conocer las librerías que manejas y entender los distintos modelos de ejecución. Las secciones sincronizadas lo más pequeñas posibles.&lt;br /&gt;&lt;br /&gt;Ejecutar pruebas de forma frecuente es la mejor manera de encontrar los posibles errores en el código. Sin embargo, es difícil hacer tests cuando hay concurrencia. Se deben tratar los fallos espúreos como posibles problemas de concurrencia e instrumentar el código para forzar la aparición de errores.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CONCLUSIONES FINALES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Todas estas buenas prácticas sobre cómo escribir código limpio se deben ejecitar de forma constante para adquirir buenos hábitos y ser  capaces de hacerlo de forma natural&lt;/span&gt;. Siguiendo estas prácticas el autor nos promete conseguir un código con el que será mas fácil trabajar y hará mucho menos frustrante nuestro día a día.&lt;br /&gt;&lt;br /&gt;Una idea que se repite en varios puntos del libro es que &lt;span style="font-weight:bold;"&gt;debemos de ser capaces de exprimir las capacidades de nuestro entorno de trabajo&lt;/span&gt;. Conocer nuestro entorno de trabajo nos puede simplificar enormemente nuestro trabajo, puesto que puede realizar por nosotros un montón de actividades de forma automática y nos ofrece una serie de ayudas que nos pueden ayudar en el día a día haciendo innecesarias algunas convenciones que sólo sirven para complicar el código.&lt;br /&gt;&lt;br /&gt;Otra cosa que me ha gustado de este libro es la bibliografía en que se basa. No es excesivamente grande, pero me ha servido para sacar unas buenas recomendaciones sobre otros libros a leer:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Agile Software Development: Principles, Patterns and Practices, Robert Martin.&lt;/li&gt;&lt;li&gt;Implementation Patterns, Kent Beck.&lt;/li&gt;&lt;li&gt;Test Driven Development, Kent Beck.&lt;/li&gt;&lt;li&gt;Extreme Programming Explained: Embrace Change, Kent Beck.&lt;/li&gt;&lt;li&gt;Refactoring: Improving the Design of Existing Code, Martin Fowler et al..&lt;/li&gt;&lt;li&gt;Design Patterns: Elements or Reusable Object Oriented Software, Gamma et al..&lt;/li&gt;&lt;li&gt;The Pragmatic Programmer, Andrew Hunt, Dave Thomas.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0132350882&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0132350882&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-8832031045817559761?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/8832031045817559761/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/01/clean-code.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/8832031045817559761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/8832031045817559761'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2011/01/clean-code.html' title='Clean Code'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_WQMxntNMWT0/TSRbBBi43LI/AAAAAAAALCw/Ub0vyDHg54Y/s72-c/CleanCode.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-6672358470271269113</id><published>2010-11-17T16:46:00.007+01:00</published><updated>2010-11-17T16:59:15.550+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eficiencia personal'/><title type='text'>La Técnica Pomodoro</title><content type='html'>En una profesión como es la informática, nuestro mayor aliado se convierte también en nuestro mayor enemigo. Nos pasamos horas programando delante del ordenador, y éste no es sólo nuestra herramienta de trabajo, sino también una tentación constante para la distracción.&lt;br /&gt;&lt;br /&gt;Cuando uno trabaja en un tarea necesita estar centrado en ella para poder realizarla de la mejor manera posible. Esto no se consigue si interrumpimos la ejecución de dicha tarea cada dos por tres porque nos ha llegado un correo o se nos acaba de ocurrir qué mirar en Internet. &lt;br /&gt;&lt;br /&gt;Tampoco es bueno realizar una tarea de forma ininterrumpida durante horas, puesto que la concentración del ser humano disminuye a medida que pasa el tiempo. Por ello, parece ser mejor intercalar periodos de esfuerzo relativamente cortos con pequeños descansos que sirvan a nuestra mente para asimilar el conocimiento que hemos adquirido, descansar y permitirnos afrontar el siguiente esfuerzo con energía.&lt;br /&gt;&lt;br /&gt;La &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt;, desarrollada por Francesco Cirillo, trabaja en esta línea de forma que aprendamos a manejar los esfuerzos personales de una forma que nos permita centrarnos en lo que estamos haciendo, llegar a establecernos un ritmo de trabajo constante y sostenible, estructurar las actividades a realizar de forma incremental y hacernos capaces de realizar planificaciones razonables sobre ellas.&lt;br /&gt;&lt;br /&gt;Implementar la &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt; es sencillo, puesto que las herramientas que se necesitan son muy básicas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Un reloj.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Una hoja dónde registrar las actividades a realizar en el día. Existirá en ella una sección donde registrar actividades urgentes que no estaban planificadas y hayan ido apareciendo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Una hoja de registro de las actividades pendientes.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Una hoja donde se muestre información de análisi de los datos registrados.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;También se pueden usar herramientas más elaboradas como hojas de cálculo o aplicaciones con bases de datos. Sin embargo, se recomienda usar el método más simple posible para que las herramientas no supongan un impedimento a la técnica en sí.&lt;br /&gt;&lt;br /&gt;La &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt; tiene los siguientes objetivos, que se pueden ir logrando de forma recursiva mediante su aplicación:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Primer objetivo: Descubrir cuánto esfuerzo requiere una actividad&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Éste es el primer objetivo de la &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt;. El esfuerzo se mide en periodos de 30 minutos llamados pomodoros: 25 minutos de actividad  y 5 de descanso.&lt;br /&gt;&lt;br /&gt;Una vez priorizadas las tareas a realizar en el día de hoy, extraídas de la hoja de actividades pendientes, se comienzan a realizar respetando los tiempos del pomodoro. Cada vez que se cumple uno de estos periodos se registra en la hoja de actividades del día, junto a la actividad que se estaba ejecutando.&lt;br /&gt;&lt;br /&gt;Se deben respetar los periodos de esfuerzo de 25 minutos, no pueden durar menos ni más. Si no se llegan a cumplir los 25 minutos realizando la tarea, este intervalo no se considera válido. Si se cumplen los 25 minutos se debe parar y descansar durante 5 minutos. Tras cada 4 pomodoros se debe parar durante un rato más largo de unos 30 minutos.&lt;br /&gt;&lt;br /&gt;Al final del día podemos evaluar el número de pomodoros que nos ha llevado realizar cada actividad y, por tanto, el esfuerzo invertido.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Segundo objetivo: Reducir el número de interrupciones&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El mayor problema para la ejecución efectiva de un pomodoro son las interrupciones. Por ello, se deben establecer estrategias para eliminar tanto las interrupciones externas cómo las internas.&lt;br /&gt;&lt;br /&gt;Las interrupciones internas son las provocadas por nosotros mismos y por la falta de capacidad para concentrarnos. Debemos hacer visible el número de éste tipo de interrupciones y hacer lo posible por reducirlo.&lt;br /&gt;&lt;br /&gt;Para ello, cada vez que tengamos la tentación de interrumpir la tarea que estamos realizando para hacer otra cosa, se marca la tarea con un apóstrofe (‘) y se añade una nueva en la lista de actividades urgentes o en la hoja de actividades pendientes, según su urgencia, para que sea realizada posteriormente. Tras esto, debemos volver a la tarea que estamos realizando.&lt;br /&gt;&lt;br /&gt;Las interrupciones externas son las provocadas por otra gente. Debemos conseguir que ocurran cuando nosotros queramos, dentro de lo posible. Si alguien viene a pedirnos que hagamos algo, debemos tratar de posponerlo para después si es posible.&lt;br /&gt;&lt;br /&gt;Para registrar estas interrupciones, se pone un guión en la actividad que estemos realizando (-) y se añade una nueva tarea en la lista de actividades urgentes o en la hoja de actividades pendientes, según su urgencia, para que sea realizada posteriormente. Tras esto, debemos volver a la tarea que estamos realizando.&lt;br /&gt;&lt;br /&gt;Una vez que sabemos qué interrupciones sufrimos, se pueden buscar estrategias para reducirlas al mínimo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Tercer objetivo: Estimar el esfuerzo necesario para realizar una actividad&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Con la experiencia acumulada hasta el momento debemos tratar de estimar el esfuerzo que requiere una actividad, de forma que podamos usar estas estimaciones para planificar nuestro trabajo diario.&lt;br /&gt;&lt;br /&gt;La estimación de una tarea no debe ser mayor de unos 7 pomodoros. Hay que mantener tareas no desmasiado grandes puesto que las tareas pequeñas facilitan su estimación. Tampoco debemos tener tareas con estimaciones inferiores a un pomodoro. Para lograr esto debemos agrupar o dividir tareas según sea necesario.&lt;br /&gt;&lt;br /&gt;Una vez estimadas las tareas, si vemos que durante la ejecución llegamos al número de pomodoros estimados sin haberla terminado, debemos hacer una segunda estimación del esfuerzo restante y, si fuese necesario una tercera. Si hacen falta menos pomodoros de los estimados continuamos normalmente.&lt;br /&gt;&lt;br /&gt;Al final del día, a la hora de registrar lo que ha pasado, debemos resaltar las diferencias entre las estimaciones y la realidad. El objetivo en posteriores pomodoros será tratar de reducir las terceras y las segundas estimaciones y, por último, tratar de acertar en la primera estimación. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Cuarto objetivo: Aumentar la efectividad del pomodoro&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En este punto, y con la experiencia adquirida, podemos decidir organizar la estructura del pomodoro de la forma que más nos convenga. Puede ser interesante utilizar los primeros minutos de un pomodoro para repasar todo lo hecho hasta el momento, y los últimos 5 para repasar lo hecho en éste pomodoro.&lt;br /&gt;&lt;br /&gt;También se pueden organizar los grupos de 4 pomodoros reservando alguno de los pomodoros para tareas específicas.&lt;br /&gt; &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Quinto objetivo: Definir una agenda&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El hecho de establecer uan agenda permite definir límites respecto a las tareas a realizar. Esto permite separar el tiempo de trabajo y el tiempo libre, entendiendo el tiempo libre como algo necesario y beneficioso para que la persona vuelva a reemprender las tareas productivas con energía y concentración.&lt;br /&gt;&lt;br /&gt;Una agenda también permite comparar los resultados obtenidos y comprobar si se ajustan a lo esperado para, en caso de lo contrario, poder tomar medidas correctoras. El hecho de registrar el número de pomodoros que finalizamos cada día permite organizar nuestra agenda en función de ello, sin caer en planes demasiado optimistas que se alejen de la realidad del día a día.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Impresiones personales&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No he hecho más que empezar a utilizar esta técnica y este post no es más que una forma de reforzar lo aprendido, puesto que he utilizado la &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt; para gestionar mi tiempo durante el estudio y redacción de dicho artículo.&lt;br /&gt;&lt;br /&gt;Sin embargo, durante este poco tiempo he percibido las siguientes impresiones al respecto:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;La motivación de usarla era tratar de reducir las interrupciones. El fijarme periodos de trabajo sin interrupciones no demasiado largos me ha permitido limitar las visitas a Twitter, Facebook, Gmail… a los tiempos entre pomodoros, cuando hasta hace poco era algo que hacía continuamente casi de forma compulsiva mientras realizaba otras tareas.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Por otra parte, en otras ocasiones me he autoexpuesto a periodos excesivamente largos de trabajo continuado, lo cual me ha llegado a producir agotamiento y dificultad para concentrarme en las horas finales de la jornada laboral. El hecho de parar sistemáticamente cada cierto tiempo para descansar o, por lo menos, separar lo ojos de la pantalla, me está resultando beneficioso y me permite mantenerme con energía hasta el final de la jornada.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;La sensación de aburrimiento o monotonía ha disminuído, aunque esto no puedo decir con seguridad si es por el uso de la propia &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt; o por el hecho de estar inmerso en un nuevo tema de estudio interesante. Esto ya lo iré viendo durante los próximos días.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;La &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt; me obliga a mantener un registro de las tareas que he realizado durante el día, lo cual me permite saber en qué he invertido realmente el tiempo y cuánto he malgastado. Esto me está permitiendo organizarme mejor para aprovechar el tiempo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;El conocer el esfuerzo de las tareas realizadas me permite hacer estimaciones más realistas sobre las tareas a desarrollar. Sé a qué me puedo comprometer y evito la frustración por no llegar a alcanzar los compromisos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;También debo decir que es la primera vez que estoy usando una de estas técnicas de gestión personal del tiempo, puesto que parece que la &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt; no es la única. No puedo decir si es mejor o peor que otras, pero sí parece que el uso de una ayuda a la eficiencia personal.&lt;br /&gt;&lt;br /&gt;Para terminar, recomendo que si estáis interesados os leáis el libro de Francesco Cirillo donde explica la &lt;span style="font-weight:bold;"&gt;Técnica Pomodoro&lt;/span&gt;, &lt;a href="http://www.pomodorotechnique.com/products.html#pomodoropdf"&gt;disponible gratuitamente en PDF&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Recursos&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.pomodorotechnique.com/"&gt;The Pomodoro Technique&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/T%C3%A9cnica_Pomodoro"&gt;La Técnica Pomodoro en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://thinkwasabi.com/2010/03/aumenta-concentracion-tecnica-pomodoro/"&gt;Aumenta tu concentración con la Técnica Pomodoro&lt;/a&gt;&lt;br /&gt;&lt;a href=" http://sixservix.com/blog/david/2009/11/26/la-tecnica-pomodoro/"&gt;La técnica Pomodoro&lt;/a&gt;&lt;br /&gt;&lt;a href=" http://sixservix.com/blog/david/2010/07/13/no-sabes-nada-de-la-tecnica-pomodoro/"&gt;No sabes nada de la Técnica Pomodoro&lt;/a&gt;&lt;br /&gt;&lt;a href="http://sixservix.com/blog/david/2010/07/20/tecnica-pomodoro-extrema/"&gt;Técnica Pomodoro extrema&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-6672358470271269113?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/6672358470271269113/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/11/la-tecnica-pomodoro.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6672358470271269113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6672358470271269113'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/11/la-tecnica-pomodoro.html' title='La Técnica Pomodoro'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-1680349827392299129</id><published>2010-11-03T11:46:00.005+01:00</published><updated>2011-10-26T09:37:01.223+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Strategy</title><content type='html'>Este patrón permite que el algoritmo a ejecutarse se seleccione en tiempo de ejecución. Este algoritmo proporciona una familia de algoritmos, encapsula cada uno dentro de un objeto y los hace intercambiables. Esto permite que el algoritmo a ejecutarse varíe en función del cliente que lo use.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;¿Qué ventajas proporciona el uso de éste patrón?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En primer lugar, es mucho más fácil comprender cada uno de los distintos comportamientos si su implementación está encapsulada en distintas clases, y no entrelazada en un único método. Esto permite de forma simple añadir nuevos comportamientos, y elminar o modificar los existentes.  &lt;br /&gt;&lt;br /&gt;En los casos en que existan varios objetos cuyo comportamiento sea parcticamente el mismo, esto se puede reducir a una única clase que haga uso de distintas estrategias. Esto reduce el uso de subclases y, por tanto, el acoplamiento entre ellas &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;¿Cómo se implementa este patrón?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Las posibles estrategias se ejecutan dentro de un objeto de contexto que se encarga de recuperar la estrategia apropiada para el cliente. Cada una de las estrategias implementa una interfaz que define la firma del método de la estrategia.&lt;br /&gt;&lt;br /&gt;Vamo a ver un ejemplo que permita aclarar esto. Por ejemplo, en un banco existen distintos tipos de cuentas, para las cuáles se siguen distintos algoritmos a la hora de calcular sus rendimientos anuales. Un objeto encargado de calcular los rendimientos de las cuentas (en este ejemplo, éste sería el objeto de contexto) podría utilizar distintas estrategias para calcular el rendimiento de cada tipo de cuenta.&lt;br /&gt;&lt;br /&gt;El siguiente diagrama representa el ejemplo anterior:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/TNE9s55zh_I/AAAAAAAALCI/vTE1JxzPUjE/s1600/DC_Strategy.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 190px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/TNE9s55zh_I/AAAAAAAALCI/vTE1JxzPUjE/s400/DC_Strategy.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5535273258681862130" /&gt;&lt;/a&gt;&lt;br /&gt;Si ahora se quisiese incluir un nuevo tipo de cuenta, por ejemplo una Cuenta Vivienda, simplemente habría que crear una nueva estrategia que implemente el algoritmo de cálculo de rendimiento y hacer que el objeto &lt;span style="font-style:italic;"&gt;CalculadoraRendimiento&lt;/span&gt; relacione este tipo de cuenta con la estrategia adecuada.&lt;br /&gt;&lt;br /&gt;De esta manera, se ha desacoplado el cálculo del rendimiento específico de cada tipo de cuenta, separando cada uno en una clase haciéndolos más claros de entender y más fácilmente modificables.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;Strategy Pattern en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.exciton.cs.rice.edu/javaresources/designpatterns/strategypattern.htm"&gt;The Strategy Design Pattern&lt;/a&gt;&lt;br /&gt;&lt;a href=" http://patronesdediseno.blogspot.com/2009/05/patron-strategy.html"&gt;Patrón Strategy&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-1680349827392299129?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/1680349827392299129/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/11/patrones-de-diseno-strategy.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1680349827392299129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1680349827392299129'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/11/patrones-de-diseno-strategy.html' title='Patrones de diseño: Strategy'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_WQMxntNMWT0/TNE9s55zh_I/AAAAAAAALCI/vTE1JxzPUjE/s72-c/DC_Strategy.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-883927560208974110</id><published>2010-10-28T16:27:00.007+02:00</published><updated>2011-10-26T09:37:16.100+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Template Method</title><content type='html'>Estre &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; define el funcionamiento general de un algoritmo en una operación de una clase, delegando en otras clases, a través de herencia o dependencia entre clases, la implementación específica de cada uno de sus pasos. Permite que estas clases redefinan ciertos pasos del algoritmo sin cambiar su comportamiento general, adaptandose cada una de ellas a una necesidad específica.&lt;br /&gt;&lt;br /&gt;Una implementación clásica de este patrón es la que aparece en el libro &lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612"&gt;“Design Patterns” del GOF&lt;/a&gt;, que presenta una clase abstracta en la que se define el comportamiento general de una operación en un método concreto que llama a su vez a otros métodos abstractos en los que se definen comportamientos más específicos. Distintas subclases pueden heredar de esta clase y especificar comportamientos diferentes para los métodos abstractos, permitiendo varias implementaciones que se puedan ajustar a cada necesidad.&lt;br /&gt;&lt;br /&gt;El siguiente diagrama UML presenta un ejemplo basado en esta forma de  implementación del &lt;span style="font-weight:bold;"&gt;patrón Template Method&lt;/span&gt;: &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_WQMxntNMWT0/TMmIh2dMmWI/AAAAAAAALB4/7ZwWvxw8InU/s1600/DC_TemplateMedianteHerencia.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 322px;" src="http://3.bp.blogspot.com/_WQMxntNMWT0/TMmIh2dMmWI/AAAAAAAALB4/7ZwWvxw8InU/s400/DC_TemplateMedianteHerencia.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5533103732336400738" /&gt;&lt;/a&gt; &lt;br /&gt;En él, una clase &lt;span style="font-style:italic;"&gt;Juego&lt;/span&gt; define en su método &lt;span style="font-style:italic;"&gt;jugar()&lt;/span&gt; el comportamiento general de cualquier juego, el juego comienza y cada uno de los jugadores va haciendo su jugada hasta que se cumple una condición que da fin al juego y se muestra el resultado. Estas operaciones se indican mediante métodos abstractos que deben ser implementados por cada juego específico de forma apropiada, como pueden ser el &lt;span style="font-style:italic;"&gt;Parchis&lt;/span&gt; o el &lt;span style="font-style:italic;"&gt;Ajedrez&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Sin embargo, al ser la herencia la forma de acoplamiento más fuerte que existe entre clases, en busca de una mayor flexibilidad se propone una implementación alternativa basada en la dependencia entre clases en lugar de la herencia.&lt;br /&gt;&lt;br /&gt;El siguiente diagrama muestra un ejemplo de implementación del &lt;span style="font-weight:bold;"&gt;patrón Template Method&lt;/span&gt; usando la dependencia entre clases:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/TMmIwAySnmI/AAAAAAAALCA/_ujlrnsKQHo/s1600/DC_TemplateMedianteDependencia.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 247px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/TMmIwAySnmI/AAAAAAAALCA/_ujlrnsKQHo/s400/DC_TemplateMedianteDependencia.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5533103975627398754" /&gt;&lt;/a&gt;&lt;br /&gt;En él se muestra una clase plantilla &lt;span style="font-style:italic;"&gt;JuegoTemplate&lt;/span&gt; con un método &lt;span style="font-style:italic;"&gt;jugar()&lt;/span&gt; que define el comportamiento general de cualquier juego. Igual que antes, el juego comienza y cada uno de los jugadores va haciendo su jugada hasta que se cumple una condición que da fin al juego y se muestra el resultado. Estas operaciones son llevadas a cabo por una instancia de una clase que implementa la interfaz Juego, interfaz que especifica los métodosque deben ser implementados por cada juego específico. Las clases &lt;span style="font-style:italic;"&gt;Parchis&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;Ajedrez&lt;/span&gt; implementan la interfaz Juego y definen el comportamiento específico de estos juegos.&lt;br /&gt;&lt;br /&gt;Esta forma de implementar el &lt;span style="font-weight:bold;"&gt;patrón Template Method&lt;/span&gt; es el usado en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; para proporcionar, por ejemplo, soporte en el acceso a &lt;span style="font-weight:bold;"&gt;JDBC&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;, a través de sus plantillas &lt;span style="font-style:italic;"&gt;JDBCTemplate&lt;/span&gt; o &lt;span style="font-style:italic;"&gt;HibernateTemplate&lt;/span&gt;, que usan una instancia de una clase que implementa la interfaz &lt;span style="font-style:italic;"&gt;DataSource&lt;/span&gt; y que encapsula el comportamiento específico de acceso a una fuente de datos.&lt;br /&gt; &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612"&gt;Design Patterns (Erich Gamma, Richard Helm, Ralph Johnson, Hohn Vlissides)&lt;/a&gt;&lt;br /&gt;&lt;a href=" http://en.wikipedia.org/wiki/Template_method_pattern"&gt;Patrón Template Method en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://weblogs.javahispano.org/rdiegoc/date/20051207"&gt;Implementacion de pattern Template utilizando composición e inyección&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/TemplatePattern.htm"&gt;The Template Design Pattern&lt;/a&gt;&lt;br /&gt;&lt;a href="http://patronesdediseno.blogspot.com/2009/05/patron-template-method.html"&gt;Patrón Template Method&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-883927560208974110?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/883927560208974110/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/10/patrones-de-diseno-template-method.html#comment-form' title='10 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/883927560208974110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/883927560208974110'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/10/patrones-de-diseno-template-method.html' title='Patrones de diseño: Template Method'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_WQMxntNMWT0/TMmIh2dMmWI/AAAAAAAALB4/7ZwWvxw8InU/s72-c/DC_TemplateMedianteHerencia.jpg' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-5969321598638602779</id><published>2010-09-28T15:00:00.010+02:00</published><updated>2011-10-06T14:27:17.623+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ñapas'/><category scheme='http://www.blogger.com/atom/ns#' term='Calidad'/><title type='text'>Error extraño en Sonar con JFreeChart y Novell SecureLogin</title><content type='html'>Durante algún tiempo no he podido visualizar los gráficos de las estadísticas generados en &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; a través de &lt;span style="font-weight:bold;"&gt;JFreeChart&lt;/span&gt; en mi equipo del trabajo.&lt;br /&gt;&lt;br /&gt;Revisando los logs de &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; encontré las siguientes trazas:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2010.09.23 11:57:21 ERROR org.mortbay.log  Error for /chart&lt;br /&gt;java.lang.NoClassDefFoundError: &lt;br /&gt; Could not initialize class org.jfree.chart.JFreeChart&lt;br /&gt;...&lt;br /&gt;2010.09.23 11:57:21 ERROR org.mortbay.log  Error for /chart&lt;br /&gt;java.lang.UnsatisfiedLinkError: &lt;br /&gt; no sljava in java.library.path&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Al parecer, el error es debido a que no encontraba la librería &lt;span style="font-style:italic;"&gt;sljava.dll&lt;/span&gt; en la ruta descrita por la propiedad &lt;span style="font-style:italic;"&gt;java.library.path&lt;/span&gt;, definida en el archivo &lt;span style="font-style:italic;"&gt;wrapper.conf&lt;/span&gt; de la configuración de &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Esta librería es una librería de &lt;span style="font-weight:bold;"&gt;Novell SecureLogin&lt;/span&gt;, que tengo configurado en mi equipo y parace que es la instalación de este producto lo que provoca el error.&lt;br /&gt;&lt;br /&gt;La solución ha sido tan sencilla como llevar la librería &lt;span style="font-style:italic;"&gt;sljava.dll&lt;/span&gt; a la ruta de &lt;span style="font-style:italic;"&gt;java.library.path&lt;/span&gt;. Ahora bien, ni idea de qué está pasando...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-5969321598638602779?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/5969321598638602779/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/09/error-extrano-con-jfreechart-y-novell.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5969321598638602779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5969321598638602779'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/09/error-extrano-con-jfreechart-y-novell.html' title='Error extraño en Sonar con JFreeChart y Novell SecureLogin'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-2839963535743613855</id><published>2010-08-31T12:59:00.010+02:00</published><updated>2011-10-26T09:38:04.095+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Proxy</title><content type='html'>Según la &lt;a href="http://es.wikipedia.org/wiki/Proxy_%28patr%C3%B3n_de_dise%C3%B1o%29"&gt;Wikipedia&lt;/a&gt;, el &lt;span style="font-weight:bold;"&gt;patrón Proxy&lt;/span&gt; se utiliza como intermediario para acceder a un objeto, permitiendo controlar el acceso a él. &lt;br /&gt;&lt;br /&gt;Este patrón es ampliamente utilizado en frameworks cómo Hibernate o Spring AOP, permitiendo capturar las llamadas a objetos POJO y permitiendo insertar en ellas capacidades de persistencia para el caso de Hibernate, u otro tipo de aspectos como gestión de seguridad o transacciones para Spring AOP. &lt;br /&gt;&lt;br /&gt;A continuación mostramos el diagrama de clases del &lt;span style="font-weight:bold;"&gt;patrón Proxy&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_WQMxntNMWT0/TNgGaP0QdoI/AAAAAAAALCQ/Dao6oOrGdQU/s1600/Proxy.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 375px; height: 215px;" src="http://3.bp.blogspot.com/_WQMxntNMWT0/TNgGaP0QdoI/AAAAAAAALCQ/Dao6oOrGdQU/s400/Proxy.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5537182789844104834" /&gt;&lt;/a&gt;&lt;br /&gt;En este patrón se identifica una interfaz &lt;span style="font-style:italic;"&gt;Subject&lt;/span&gt;, un objeto &lt;span style="font-style:italic;"&gt;RealSubject&lt;/span&gt; que es el objeto al que se accede a través del &lt;span style="font-style:italic;"&gt;Proxy&lt;/span&gt;. El objeto &lt;span style="font-style:italic;"&gt;Proxy&lt;/span&gt; mantiene una referencia al objeto &lt;span style="font-style:italic;"&gt;RealSubject&lt;/span&gt; y controla el acceso a sus métodos, intruciendo las capacidades adicionales que fuesen necesarias. Tanto la clase &lt;span style="font-style:italic;"&gt;RealSubject&lt;/span&gt; como la clase &lt;span style="font-style:italic;"&gt;Proxy&lt;/span&gt; implementan la interfaz &lt;span style="font-style:italic;"&gt;Subject&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;En Java es fácil crear &lt;span style="font-weight:bold;"&gt;proxies dinámicos&lt;/span&gt; en tiempo de ejecución a partir de la clase &lt;span style="font-style:italic;"&gt;java.lang.reflect.Proxy&lt;/span&gt;. Veámoslo a través de un ejemplo.&lt;br /&gt;&lt;br /&gt;Creamos una interfaz:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.proxy;&lt;br /&gt;&lt;br /&gt;public interface Lector {&lt;br /&gt; public void leer();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Ahora creamos una implementación para esta interfaz:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.proxy;&lt;br /&gt;&lt;br /&gt;public class LectorImpl implements Lector {&lt;br /&gt;&lt;br /&gt; public void leer(){&lt;br /&gt;  System.out.println("Estamos leyendo...");&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;En este momento, creamos el proxy para la clase&lt;span style="font-style:italic;"&gt; LectorImpl&lt;/span&gt;: &lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.proxy;&lt;br /&gt;&lt;br /&gt;import java.lang.reflect.InvocationTargetException;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;&lt;br /&gt;public class LectorProxy &lt;br /&gt; implements java.lang.reflect.InvocationHandler {&lt;br /&gt;&lt;br /&gt; private Object obj;&lt;br /&gt;  &lt;br /&gt; public static Object newInstance(Object obj) {&lt;br /&gt;  return java.lang.reflect.Proxy.newProxyInstance(&lt;br /&gt;   obj.getClass().getClassLoader(),&lt;br /&gt;   obj.getClass().getInterfaces(),&lt;br /&gt;   new LectorProxy(obj));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private LectorProxy(Object obj) {&lt;br /&gt;  this.obj = obj;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Object invoke(&lt;br /&gt;  Object proxy, &lt;br /&gt;  Method m, &lt;br /&gt;  Object[] args) throws Throwable {&lt;br /&gt;  Object result;&lt;br /&gt;  try {&lt;br /&gt;   System.out.println(&lt;br /&gt;    "Antes de llamar al metodo " + m.getName());&lt;br /&gt;   result = m.invoke(obj, args);&lt;br /&gt;  } catch (InvocationTargetException e) {&lt;br /&gt;   throw e.getTargetException();&lt;br /&gt;  } catch (Exception e) {&lt;br /&gt;   throw new RuntimeException(e.getMessage());&lt;br /&gt;  } finally {&lt;br /&gt;   System.out.println(&lt;br /&gt;    "Despues de llamar al metodo " + m.getName());&lt;br /&gt;  }&lt;br /&gt;  return result;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Esta clase, que usa el &lt;span style="font-weight:bold;"&gt;patrón singleton&lt;/span&gt;, crea dinámicamente un proxy para la instancia de la clase que se pasa a su método newInstance() gracias a las capacidades de la clase &lt;span style="font-style:italic;"&gt;java.lang.reflect.Proxy&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;El método &lt;span style="font-style:italic;"&gt;invoke()&lt;/span&gt; de esta clase captura las invocaciones a este proxy y las redirige al objeto &lt;span style="font-style:italic;"&gt;LectorImpl&lt;/span&gt; en lugar del que actúa, añadiéndolo funcionalidad adicional, que en este caso consiste en mostrar mensajes antes y después del método invocado.&lt;br /&gt;&lt;br /&gt;Ahora podemos crear una instancia de este proxy y acceder a los métodos de la interfaz &lt;span style="font-style:italic;"&gt;Lector&lt;/span&gt; que implementa:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.proxy;&lt;br /&gt;&lt;br /&gt;public class PruebaLector {&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  Lector lector = (Lector)LectorProxy.newInstance(&lt;br /&gt;   new LectorImpl());&lt;br /&gt;  lector.leer();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Si ejecutamos la prueba, obtenemos la siguiente salida por la consola:&lt;br /&gt;&lt;pre class="prettyprint txt"&gt;Antes de llamar al metodo leer&lt;br /&gt;Estamos leyendo...&lt;br /&gt;Despues de llamar al metodo leer&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vemos que la llamada al método &lt;span style="font-style:italic;"&gt;leer()&lt;/span&gt; gestionada por el proxy ha sido adornada con los dos mensajes adicionales. &lt;br /&gt;&lt;br /&gt;A pesar de la sencillez de este ejemplo, el uso de &lt;span style="font-weight:bold;"&gt;proxies dinámicos&lt;/span&gt; permite la ejecución de tareas avanzadas en frameworks de gran complejidad como Hibernate o Spring AOP. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Proxy_%28patr%C3%B3n_de_dise%C3%B1o%29"&gt;Patrón de diseño Proxy en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.answers.yahoo.com/question/index?qid=20080826163112AAPQKTC"&gt;¿Cuál es el problema que resuelve el patrón de diseño Proxy?&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=PatronProxy"&gt;Patrón de diseño Proxy en Adictos al Trabajo&lt;/a&gt;&lt;br /&gt;&lt;a href="http://download-llnw.oracle.com/javase/1.3/docs/guide/reflection/proxy.html"&gt;Dynamic Proxy Classes&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-2839963535743613855?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/2839963535743613855/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/08/patrones-de-diseno-proxy.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2839963535743613855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2839963535743613855'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/08/patrones-de-diseno-proxy.html' title='Patrones de diseño: Proxy'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_WQMxntNMWT0/TNgGaP0QdoI/AAAAAAAALCQ/Dao6oOrGdQU/s72-c/Proxy.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-2843322625433352094</id><published>2010-07-28T13:55:00.004+02:00</published><updated>2010-08-31T13:41:09.248+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><category scheme='http://www.blogger.com/atom/ns#' term='Kanban'/><category scheme='http://www.blogger.com/atom/ns#' term='Scrum'/><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Kanban y Scrum – Obteniendo lo mejor de ambos</title><content type='html'>Tras un mes de vacaciones, volvemos a la carga con el blog. Voy a empezar por un libro cortito cuya lectura ya tenía en mente antes de ir de vacaciones y que continúa el tema de las &lt;span style="font-weight:bold;"&gt;metodologías ágiles&lt;/span&gt;, haciendo una introducción a &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt; en este caso. &lt;br /&gt;&lt;br /&gt;Este libro es la traducción al castellano, realizada por el equipo de contenidos de &lt;a href="http://www.agile-spain.com"&gt;Agile Spain&lt;/a&gt; del libro de Henrik Kniberg y Mattias Skarin &lt;span style="font-style:italic;"&gt;“Kanban vs Scrum – a practical guide”&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;En el prólogo de este libro, David Anderson expone que la idea principal de &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt; consiste en limitar el trabajo en progreso (&lt;span style="font-style:italic;"&gt;WIP – Work In Progress&lt;/span&gt;), utilizando tarjetas (&lt;span style="font-style:italic;"&gt;kanban&lt;/span&gt;) como indicadores de que nuevos bloques pueden ser incorporados en un paso del flujo de trabajo. Está basado en las ideas extraídas del sistema de producción de Toyota (&lt;span style="font-style:italic;"&gt;TPS – Toyota Production System&lt;/span&gt;) y se engloba dentro de las metodologías ligeras (&lt;span style="font-style:italic;"&gt;Lean&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;También comenta que &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt; introduce una aproximación a la gestión del cambio. Se comienza a hacer Kanban comprendiendo el flijo de trabajo actual y estableciendo límites para el trabajo en curso en cada una de sus fases. El trabajo es arrastrado (&lt;span style="font-style:italic;"&gt;pull&lt;/span&gt;) a través del sistema a partir de señales &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt;. Mostrando este avance del trabajo en un panel se hacen visibles las deficiencias en el proceso y permite su mejora y adaptación continua.&lt;br /&gt;&lt;br /&gt;El propósito de este libro es introducirnos a lo que es &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt;, comparándolo con &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt;, y a cómo pueden ser útiles en nuestro entorno. Para ello, el libro se divide en dos partes, en la primera parte Henrik Kniberg compara &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt; y en la segunda parte Mattias Skarin presenta un ejemplo práctico de aplicación de Kanban.&lt;br /&gt;&lt;br /&gt;Como he dicho, en la primera parte, más teórica, se comparan &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt; a través de los siguientes capítulos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Bueno, pero, al fin y al cabo, ¿qué son Scrum y Kanban?&lt;/span&gt;: En este capítulo se resume de forma breve lo que es cada una de estas dos metodologías. Ya conocemos Scrum, así que sólo me detendré en las ideas principales de Kanban: visualizar el flujo de trabajo, limitar el WIP y medir el tiempo de ciclo para hacer que sea lo más pequeño y predecible posible.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Entonces, ¿cómo se relacionan Scrum y Kanban entre sí?&lt;/span&gt;: Scrum y Kanban son herramientas de proceso que porporcionan ciertas restricciones y directrices. Ambos son métodos ligeros menos restrictivos que los métodos tradicionales y muy adaptables, siendo Scrum algo más restrictivo que Kanban. Estas herramientas no son excluyentes y se pueden mezclar entre sí y con otras herramientas como algunas de las ideas de XP.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Scrum prescribe roles&lt;/span&gt;: Mientras que Scrum prescribe los roles de dueño del producto, equipo y Scrum Master, Kanban no establece ningún rol. Pero existe libertad para añadir los roles que se consideren necesarios.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Scrum prescribe iteraciones de tiempo fijo&lt;/span&gt;: Scrum está basado en iteraciones de tiempo fijo que determinan la cadencia del proyecto. En una iteración se combinan las actividades de planificación, mejora del proceso y entrega. En Kanaban no existen iteraciones, por lo que estas actividades se pueden realizar siguiendo cualquier estrategia.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Kanban limita el WIP por estado en flujo de trabajo, Scrum limita el WIP por iteración&lt;/span&gt;: Kanban limita el número de elementos al mismo tiempo en un estado del flujo de trabajo. En Scrum, el límite es el número de elementos en la pila del producto.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Ambos son empíricos&lt;/span&gt;: En Scrum y Kanban el proceso se puede controlar de forma indirecta a través de parámatros como el número de componentes del equipo, el límite de trabajo en curso, la existencia de iteraciones… Son empíricos en el sentido de que se espera que experimentes con el proceso y lo adaptes a tu entorno. A este proceso de mejora se le denomina “kaizen” en terminología Lean, y se trata de buscar una realimentación sobre el proceso que de información sobre cómo mejorarlo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Scrum se resiste a los cambios durante la iteración&lt;/span&gt;: Scrum no permite modificar la pila del sprint durante el mismo, permitiendo al equipo mantenerse enfocado durante un periodo de tiempo suficiente. Kanban, en cambio, permite cambiar los elementos en la entrada del flujo de trabajo siempre que se respete el límte del WIP establecido.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El tablero sprint se limpia entre iteraciones&lt;/span&gt;: En Scrum, cuando finaliza un sprint, el tablero se limpia y todos los elementos son eliminados. En Kanban, el tablero no se limpia, los elementos simplemente van avanzando a través de las columnas.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Scrum prescribe equipos multifuncionales&lt;/span&gt;: En Scrum, el tablero pertenece a un equipo, y un equipo tiene todo el conocimiento necesario para llevar a cabo una iteración. En Kanban el tablero está relacionado con un flujo de trabajo y puede pertenecer a varios equipos de distintas funcionalidades.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Los elementos de la pila de producto deben caber en un sprint&lt;/span&gt;: En Scrum, si un problema es demasiado grande para caber en un sprint, éste se descompone. En Kanban, aunque es interesante tener elementos pequeños que minimicen el tiempo de entrega, no es obligatorio que estos se ajusten a un intervalo de tiempo específico.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Scrum prescribe la estimación y la velocidad&lt;/span&gt;: En Scrum los equipos estiman el tamaño relativo de cada elemento al que se comprometen, y sumando el tamaño de cada elemento se obtiene la velocidad. En Kanban no es necesario estimar, pero algunos equipos lo hacen para poder garantizar el tiempo de entrega promedio.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Ambos permiten trabajar en múltiples productos simultáneamente&lt;/span&gt;: En Scrum, la pila de producto podría completarse con elementos de varios proyectos. Esto mismo, se puede hacer también en Kanban.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Ambos son Lean y Ágiles&lt;/span&gt;: Ambos son sistemas de optimización “pull”, basados en procesos de optimización continuos y que priorizan la respuesta al cambio frente al seguimiento de un plan, entre otras características.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Diferencias menores&lt;/span&gt;: diferencias menos relevantes entre Scrum y Kanban son que Scrum prescribe una pila de producto priorizada, establece reuniones diarias y utiliza gráficos burndown. En Kanban se utilizan diagramas de flujo acumulativo que representan como el WIP afecta al plazode entrega.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El tablero Scrum vs. El tablero Kanban – un ejemplo menos trivial&lt;/span&gt;: En este apartado se muestran casos de utilización de un tablero Kanban en distintas situaciones. También se dan directrices sobre cómo aplicar los límites Kanban.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Resumen de Scrum vs. Kanban&lt;/span&gt;: En este apartado se resumen los parecidos y las diferencias entre ambos vistos en los capítulos anteriores.&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;La segunda parte es un ejemplo de cómo poner &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt; en práctica. Con ello, el libro es una introducción estupenda a &lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt;, sobre todo para aquellos que ya han visto algo de &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt; y que se preguntan cuál es la diferencia entre ambas herramientas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://blog.crisp.se/henrikkniberg/2009/04/03/1238795520000.html"&gt;Blog de Henrik Kniberg&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.presionblogosferica.com/2010/01/28/kanban-vs-scrum-en-castellano/"&gt;Página web de Navegapolis&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-2843322625433352094?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/2843322625433352094/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/07/kanban-y-scrum-obteniendo-lo-mejor-de.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2843322625433352094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2843322625433352094'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/07/kanban-y-scrum-obteniendo-lo-mejor-de.html' title='Kanban y Scrum – Obteniendo lo mejor de ambos'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-9068566728358887990</id><published>2010-06-17T10:31:00.004+02:00</published><updated>2010-08-31T13:42:13.488+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><category scheme='http://www.blogger.com/atom/ns#' term='Scrum'/><title type='text'>Conceptos principales de Scrum</title><content type='html'>Basándome en lo explicado en el libro de &lt;span style="font-weight:bold;"&gt;Henrik Kniberg&lt;/span&gt; &lt;a href="http://tratandodeentenderlo.blogspot.com/2010/06/scrum-y-xp-desde-las-trincheras.html"&gt;“Scrum y XP desde las trincheras”&lt;/a&gt;, en este post lo que pretendo es recopilar y explicar brevemente los conceptos principales en los que se basa &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Vamos a separar por un lado las personas implicadas en un proyecto que sigue esta metodología y, por otro lado, los productos y tareas que hay que completar durante el proceso que &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt; propone.&lt;br /&gt;&lt;br /&gt;En primer lugar las &lt;span style="font-weight:bold;"&gt;personas&lt;/span&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El cliente&lt;/span&gt;: Es la persona que solicita un proyecto de cara a satisfacer una necesidad propia o de su negocio.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El propietario del producto (Product Owner)&lt;/span&gt;: Es la persona que hace de intermediario entre el cliente (no técnico) y el equipo y tiene capacidad de decisión sobre los requisitos a implementar.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El equipo&lt;/span&gt;: Es el personal técnico que se encargará de la realización del proyecto.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El Scrum Master&lt;/span&gt;: Es la persona conocedora del proceso Scrum que se encarga de orientar al equipo y al propietario del producto para que sigan el proceso determinado por Scrum. Si las personas involucradas en el proyecto ya conocen Scrum su labor puede no ser necesaria.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Y, en segundo lugar, los &lt;span style="font-weight:bold;"&gt;productos y tareas&lt;/span&gt; necesarias:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;La pila de producto&lt;/span&gt;: Es una lista priorizada de requisitos o “historias” del cliente escritos usando su propia terminología, de forma no técnica.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Reunión de planificación del sprint&lt;/span&gt;: En esta reunión el equipo y el propietario del producto negocian sobre el alcance de cada sprint en base a las estimaciones y a la importancia de cada una de las historias de la pila del producto.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;La pila de sprint&lt;/span&gt;: El la lista de historias sacadas de la pila del producto que conforman el alcance del sprint actual.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Reunión diaria de scrum&lt;/span&gt;: En esta reunión el equipo discute los problemas que se va encontrando a medida que el producto avanza y revisa sus estimaciones para poder llevar el seguimiento del avance del proyecto.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Demostración&lt;/span&gt;: Como colofón a cada sprint se debe presentar una demostración de aquello que se ha implementado, de cara a obtener retroalimentación sobre el proyecto por parte de los interesados que permita encaminar futuros sprints.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Retrospectiva&lt;/span&gt;: Al final de cada sprint se lleva a cabo una reunión que permite revisar qué se ha hecho bien y mal durante el sprint con el objetivo de mejorar el proceso.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Para terminar, resumiré de forma breve el &lt;span style="font-weight:bold;"&gt;proceso&lt;/span&gt; que define &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;En primer lugar, el &lt;span style="font-weight:bold;"&gt;propietario del producto&lt;/span&gt; construye la &lt;span style="font-weight:bold;"&gt;pila del producto&lt;/span&gt; con las historias de usuario o requisitos del proyecto. La &lt;span style="font-weight:bold;"&gt;pila del producto&lt;/span&gt; no es algo invariable, será modificada a medida que avanza el proyecto y se clarifican los requisitos.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Antes de cada &lt;span style="font-weight:bold;"&gt;sprint&lt;/span&gt;, iteración de aproximadamente 3 o 4 semanas, el &lt;span style="font-weight:bold;"&gt;equipo&lt;/span&gt; y el &lt;span style="font-weight:bold;"&gt;propietario del producto&lt;/span&gt; se reunen para decidir que historias de la &lt;span style="font-weight:bold;"&gt;pila del producto&lt;/span&gt; se van a implementar en él. Estas historias a implementar forman la &lt;span style="font-weight:bold;"&gt;pila del sprint&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Durante el &lt;span style="font-weight:bold;"&gt;sprint&lt;/span&gt;, el &lt;span style="font-weight:bold;"&gt;equipo&lt;/span&gt; tendrá una &lt;span style="font-weight:bold;"&gt;reunión diaria de sprint&lt;/span&gt;, en la que se actualiza la evolución del proyecto y se tratan de resolver posibles problemas.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Al final del &lt;span style="font-weight:bold;"&gt;sprint&lt;/span&gt;, se lleva a cabo la &lt;span style="font-weight:bold;"&gt;demostración&lt;/span&gt;, en la que se exponen las nuevas funcionalidades implementadas durante el sprint.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Antes de comenzar un nuevo &lt;span style="font-weight:bold;"&gt;sprin&lt;/span&gt;t, se lleva a cabo una &lt;span style="font-weight:bold;"&gt;retrospectiva&lt;/span&gt; que permite identificar posibles mejoras en la forma de trabajar.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/TBndyOK6v7I/AAAAAAAAK-o/ymf1iyGi17M/s1600/scrum.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 500px; height: 300px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/TBndyOK6v7I/AAAAAAAAK-o/ymf1iyGi17M/s320/scrum.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5483657876167376818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://weblogs.javahispano.org/artesanodeprimera/entry/aplicando_scrum_y_xp_el"&gt;Aplicando Scrum y XP&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.gravitar.biz/index.php/bi/metodologias-agiles-intro/"&gt;Metodologías ágiles&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.proyectosagiles.org/que-es-scrum"&gt;Qué es Scrum&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-9068566728358887990?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/9068566728358887990/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/conceptos-principales-de-scrum.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/9068566728358887990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/9068566728358887990'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/conceptos-principales-de-scrum.html' title='Conceptos principales de Scrum'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_WQMxntNMWT0/TBndyOK6v7I/AAAAAAAAK-o/ymf1iyGi17M/s72-c/scrum.bmp' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-572412483917418526</id><published>2010-06-15T18:01:00.007+02:00</published><updated>2010-08-31T13:46:00.243+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><category scheme='http://www.blogger.com/atom/ns#' term='Scrum'/><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Scrum y XP desde las trincheras</title><content type='html'>Aunque ya lo he leído hace algún tiempo, ahora mismo siento la necesidad de releer el libro de &lt;span style="font-weight:bold;"&gt;Henrik Kniberg&lt;/span&gt; &lt;span style="font-style:italic;"&gt;“Scrum &amp; XP from the trenches”&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;“Scrum y XP desde las trincheras”&lt;/span&gt; en su traducción al español ) en busca de ideas que aplicar para tratar de incorporarlas en las nuevos proyectos que voy a comenzar.&lt;br /&gt;&lt;br /&gt;En este libro, disponible para su descarga gratuita, &lt;span style="font-weight:bold;"&gt;Henrik Kniberg&lt;/span&gt; cuenta sus propias experiencias durante la implantación de &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt; en la empresa en la que estaba trabajando. En él expone sus ideas acerca de cómo usar la &lt;span style="font-weight:bold;"&gt;metodología de desarrollo ágil Scrum&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;El libro, con prólogos por parte de &lt;span style="font-weight:bold;"&gt;Jeff Sutherland&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;Mike Cohn&lt;/span&gt;, consta de los siguientes capítulos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Introducción&lt;/span&gt;: Según el propio creador de Scrum, Ken Schwaber, Scrum no es una metodología, sino un marco de trabajo y, por tanto, no dice exactamente qué es lo que hay que hacer. Sin embargo, en este libro, Henrik Kniberg sí que dice qué es exactamente lo que él hace para aplicar Scrum. A pesar de ello, previene de que Scrum es una metodología que debe adaptarse a la situación específica de cada proyecto.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo hacemos las pilas de producto&lt;/span&gt;: La pila de producto es una lista priorizada de requisitos o “historias” del cliente escritos usando su propia terminología, de forma no técnica.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo nos preparamos para la planificación de sprint&lt;/span&gt;: El propietario de la pila de producto debe tener ésta ya preparada para cuando se va a planificar un sprint. El propietario debe comprender todas las historias de usuario y asignarlas una importancia.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo hacemos la planificación de sprint&lt;/span&gt;: La reunión de planificación de sprint es la actividad más crítica de Scrum. La meta de esta reunión es definir un objetivo, la lista de miembros del equipo implicados, la lista de tareas que se desarrollarán, una fecha de demostración y un lugar y hora para la reunión de scrum diaria. En ellas, el propietario de producto y el equipo negocian sobre el alcance de cada sprint en base a las estimaciones y a la importancia de cada una de las historias.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo comunicamos los sprints&lt;/span&gt;: Es necesario informar a todo el mundo de qué está ocurriendo en cada sprint. Para ello, después de la reunión de planificación del sprint se debe redactar una hoja de información del sprint que recoja los objetivos que se han definido. Esta hoja debe publicarse para todo el mundo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo hacemos las pilas de sprint&lt;/span&gt;: Después de la reunío de planificación de sprint y antes de la primera reunión de scrum diaria, el Scrum master debe crear la pila de sprint. La pila de sprint es la lista de tareas que se realizan durante el sprint, con gráficos de avance de estas tareas (burndown). La forma más efectiva de mostrar la pila de sprint es mediante un tablón en la pared.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo distribuímos la sala del equipo&lt;/span&gt;: Las discusiones más interesantes tienen lugar de forma espontánea delante de una pizarra donse se puedan pintar diagramas o gráficos de diseño. Los miembros del equipo se pueden reunir en frente de esta pizarra y discutir sobre el diseño en cualquier momento. También es importante que los miembros del equipo se sienten junto para fomentar la comunicación entre ellos. El propietario del producto no debe estar sentado con el equipo para que no sienta la tentación de medrar en los detalles, pero debe sí estar accesible para el equipo por si surge alguna duda y hay que preguntarle. El resto de la gente no debe interferir para nada con el equipo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo hacemos los scrums diarios&lt;/span&gt;: El mejor sitio para el scrum diario es delante del tablón con la pila de scrum. Durante la reunión, que no debe durar mucho más de 15 minutos, se debe actualizar el tablón con los avances que el equipo ha realizado.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo hacemos la demo de sprint&lt;/span&gt;: El hecho de tener que hacer demostraciones al final de cada sprint fuerza al equipo a tener algo hecho que mostrar y fomenta lo comunicación sobre lo que se está haciendo dentro del equipo y con otros equipos que asistan a la demostración. Las demostraciones además permiten obtener realimentación sobre el proyecto por parte del cliente.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;C&lt;span style="font-weight:bold;"&gt;ómo hacemos las restrospectivas de sprint&lt;/span&gt;: La retrospectiva es la segunda tarea más importante, puesto que es la que premite mejorar. La restrospectiva es una reunión que tiene lugar al final de cada sprint donde el equipo expone sus ideas sobre qué cosas se pueden hacer mejor.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Descansos entre sprints&lt;/span&gt;: Después de cada sprint, que pueden ser muy intensos, es necesario un tiempo de descanso que permita además asimilar nuevas ideas o información.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo hacemos la planificación de entregas y los contratos de precio fijo&lt;/span&gt;: En algunos casos, normalmente unidos a un contrato de precio fijo, es necesario planificar con antelación las entregas de varios sprints posteriores. Para ello el propietario del producto necesita estimaciones de las tareas incluidas en el contrato, que se deben haber realizado de forma conjunta con el equipo. En función de estas estimaciones y la velocidad del equipo se establece el plan de entregas a lo largo de los siguientes sprints. Este plan puede ser modificado a medida que surgen cambios según el proceso avanza.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo combinamos Scrum con XP&lt;/span&gt;: Scrum y XP se complementan a la perfección, puesto que Scrm se centra en la gestión y la organización del proyecto y XP se centra en las prácticas de programación. Algunas de las prácticas de XP son también parte inherente de Scrum, como el concepto de equipo, sentarse juntos, las historias de usuario y el juego de la planificación. Además, hay otras prácticas de XP que se complementan con Scrum, como la programación en parejas, el desarrollo guiado por pruebas (TDD), el diseño incremental, la integración continua, la propiedad colectiva del código y su estandarización y el trabajo a un ritmo enérgico pero sostenible.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo hacemos pruebas&lt;/span&gt;: Esta es la parte más difícil del desarrollo de software y la más variable entre distintas organizaciones. Es necsario realizar algún test de aceptación manual antes de dar un trabajo por realizado. Sin embargo, se puede reducir esta fase de test aumentando la calidad del código entregado y aumentando la eficiencia de las pruebas automáticas realizadas. O, incluso, incluir que algún miembro del equipo realice tareas de tester. El tester será la persona que certifique que una tarea está completamente terminada. Las pruebas de aceptación no encajan bien dentro del ciclo de un sprint, por lo que se definen ciclos de aceptación fuera del sprint.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo manejar múltiples equipos Scrum&lt;/span&gt;: Los equipos demasiado grandes no se adaptan bien a las prácticas de Scrum porque la comunicación entre todos los miembros es mucho más difícil. Es preferible tener varios equipos pequeños que uno grande, si el proyecto lo permite. El número ideal de personas parece estar entre 5 y 9 personas.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Cómo gestionamos equipos distribuidos geográficamente&lt;/span&gt;: Aquí se discuten distintas formas de gesrionar equipos distribuídos, que pueden ser bien distintos equipos en localizaciones distintas o un mismo equipo con miembros distribuídos.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Lista de comprobación del Scrum Master&lt;/span&gt;: Aquí se listan las tareas administrativas del Scrum Master, tareas que debe realizar al comienzo, durante y al final de cada sprint.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Este libro es una introducción estupenda a &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt; y permite comenzar a usar esta metodología siguiendo las ideas que en él se exponen. Luego, a través de la práctica, se pueden ir perfeccionando las prácticas en base a aquello que resulte realmente valioso.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.infoq.com/minibooks/scrum-xp-from-the-trenches"&gt;Scrum &amp; XP from the trenches&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.proyectalis.com/wp-content/uploads/2008/02/scrum-y-xp-desde-las-trincheras.pdf"&gt;Scrum y XP desde las trincheras&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-572412483917418526?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/572412483917418526/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/scrum-y-xp-desde-las-trincheras.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/572412483917418526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/572412483917418526'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/scrum-y-xp-desde-las-trincheras.html' title='Scrum y XP desde las trincheras'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-2231521033421993379</id><published>2010-06-10T16:43:00.011+02:00</published><updated>2011-10-26T09:38:58.103+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Adapter</title><content type='html'>Este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; convierte la interfaz de una clase en otra distinta que es la que esperan los clientes y permite que cooperen clases que de otra manera no podrían por tener interfaces incompatibles.&lt;br /&gt;&lt;br /&gt;Se encarga de proporcionar a una clase cliente el interfaz que necesita para trabajar utilizando en su implementación una clase o clases que no cumplen con dicho interfaz.&lt;br /&gt;&lt;br /&gt;La mejor forma de ver este patrón es a través de un ejemplo. Supongamos que tenemos una clase &lt;span style="font-style:italic;"&gt;Cliente&lt;/span&gt; que realiza cálculos matemáticos complejos cuya realización se delegan en otra clase. Vamos a suponer a modo de ejemplo que estos cálculos complejos pueden ser una suma o una resta. La interfaz requerida por esta clase cliente para sus cálculos se define en la interfaz &lt;span style="font-style:italic;"&gt;Calculadora&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.adapter;&lt;br /&gt;&lt;br /&gt;public interface Calculadora {&lt;br /&gt; public int suma(int operador1, int operador2);&lt;br /&gt; public int resta(int operador1, int operador2);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Para la ejecución de estos complejos cálculos se dispone de la clase &lt;span style="font-style:italic;"&gt;Procesador&lt;/span&gt; que los implementa:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.adapter;&lt;br /&gt;&lt;br /&gt;public class Procesador {&lt;br /&gt; public static final int SUMA = 1;&lt;br /&gt; public static final int RESTA = 2;&lt;br /&gt; &lt;br /&gt; public static int realizarOperacion(&lt;br /&gt;   int operador1,&lt;br /&gt;   int operador2,&lt;br /&gt;   int operacion) {&lt;br /&gt;  int resultado = 0;&lt;br /&gt;  &lt;br /&gt;  switch(operacion) {&lt;br /&gt;   case SUMA:&lt;br /&gt;    resultado = operador1 + operador2;&lt;br /&gt;    break;&lt;br /&gt;   case RESTA:&lt;br /&gt;    resultado = operador1 - operador2;&lt;br /&gt;    break;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  return resultado;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;En este caso, a pesar de que la clase &lt;span style="font-style:italic;"&gt;Procesador&lt;/span&gt; realiza las operaciones que necesita la clase &lt;span style="font-style:italic;"&gt;Cliente&lt;/span&gt;, no implementa la interfaz que ésta necesita para poder usarla. Sin embargo, se puede crear una clase &lt;span style="font-style:italic;"&gt;Adaptador&lt;/span&gt; que adapte la clase Procesador a la interfaz &lt;span style="font-style:italic;"&gt;Calculadora&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.adapter;&lt;br /&gt;&lt;br /&gt;public class Adaptador implements Calculadora {&lt;br /&gt; public int suma(&lt;br /&gt;   int operador1,&lt;br /&gt;   int operador2) {&lt;br /&gt;  return Procesador.realizarOperacion(&lt;br /&gt;    operador1,&lt;br /&gt;    operador2,&lt;br /&gt;    Procesador.SUMA);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public int resta(&lt;br /&gt;   int operador1,&lt;br /&gt;   int operador2) {&lt;br /&gt;  return Procesador.realizarOperacion(&lt;br /&gt;    operador1,&lt;br /&gt;    operador2,&lt;br /&gt;    Procesador.RESTA);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;De esta forma, la clase &lt;span style="font-style:italic;"&gt;Cliente&lt;/span&gt; puede usar los cálculos realizados en la clse &lt;span style="font-style:italic;"&gt;Procesador&lt;/span&gt; a través de la clase &lt;span style="font-style:italic;"&gt;Adaptador&lt;/span&gt;, que la adecúa a la interfaz Calculadora que necesita la clase &lt;span style="font-style:italic;"&gt;Cliente&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;El siguiente diagrama &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; refleja las relaciones entre dichas clases:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/TBD6ic0BJ_I/AAAAAAAAK-g/1w0XYkKtSW4/s1600/DC_Adapter.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 293px; height: 222px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/TBD6ic0BJ_I/AAAAAAAAK-g/1w0XYkKtSW4/s320/DC_Adapter.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5481156216266762226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Adapter_pattern"&gt;Adapter pattern en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Adapter_%28patr%C3%B3n_de_dise%C3%B1o%29"&gt;Patrón Adaptador en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://java.dzone.com/articles/design-patterns-uncovered-0"&gt;Design Patterns Uncovered: The Adapter Pattern en DZone&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.oodesign.com/adapter-pattern.html"&gt;Adapter Pattern en OODesign.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-2231521033421993379?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/2231521033421993379/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/patrones-de-diseno-adapter.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2231521033421993379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2231521033421993379'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/patrones-de-diseno-adapter.html' title='Patrones de diseño: Adapter'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_WQMxntNMWT0/TBD6ic0BJ_I/AAAAAAAAK-g/1w0XYkKtSW4/s72-c/DC_Adapter.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-1092744182503846803</id><published>2010-06-04T13:24:00.007+02:00</published><updated>2010-06-08T10:17:46.379+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><title type='text'>Consideraciones sobre el diseño</title><content type='html'>Este artículo está basado en el &lt;a href="http://martinfowler.com/articles/designDead.html"&gt;artículo de Martin Fowler “Is Design Dead?”&lt;/a&gt; y en su &lt;a href="http://www.programacionextrema.org/articulos/designdead.es.html"&gt;traducción al castellano realizada por Alejandro Sierra&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;La verdad es que he descubierto en &lt;span style="font-weight:bold;"&gt;Martin Fowler&lt;/span&gt; una verdadera fuente de inspiración y de ideas sobre la &lt;span style="font-weight:bold;"&gt;ingeniería del software&lt;/span&gt;. En los últimos tiempos, basándome en sus artículos, estoy encontrando respuestas y reflexiones valiosas sobre los problemas que me afectan como desarrollador de software.&lt;br /&gt;&lt;br /&gt;En este caso, llevo algún tiempo en conflicto entre la idea de realizar el diseño al principio del proyecto, paralizando todo desarrollo hasta tener una visión clara, o comenzar a desarrollar tan pronto como sea posible para tener algo que ofrecer como propugnan las &lt;span style="font-weight:bold;"&gt;metodologías ágiles&lt;/span&gt;, aunque esto implique rehacer lo ya hecho cuando las ideas se aclaran o varían.&lt;br /&gt;&lt;br /&gt;En este artículo, &lt;span style="font-weight:bold;"&gt;Martin Fowler&lt;/span&gt; expone sus ideas sobre el diseño dentro de una &lt;span style="font-weight:bold;"&gt;metodología ágil&lt;/span&gt; como es &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; que, aparentemente, no le da importancia.  &lt;br /&gt;&lt;br /&gt;Hay dos maneras de plantear el diseño, el diseño evolutivo y el diseño planeado:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Durante el &lt;span style="font-weight:bold;"&gt;diseño evolutivo&lt;/span&gt; el diseño se realiza a medida que  el sistema evoluciona, formando parte de la programación. Esta forma de diseño suele acabar en desastre porque termina siendo una agregación de decisiones puntuales que complican el código y deterioran el diseño.&lt;/li&gt;&lt;li&gt;El &lt;span style="font-weight:bold;"&gt;diseño planeado&lt;/span&gt; se corresponde con la visión del diseño de cualquier ingeniería clásica, en donde se trata de anticipar los problemas de forma abstracta sin entrar en la codificación hasta haber terminado esta fase de diseño. Sin embargo, es difícil anticipar todos los problemas antes de comenzar con la programación, lo que hace aparecer tensiones entre programadores y diseñadores. También se pueden producir cambios en los requisitos que pueden deberse a cambios en el negocio y que, por tanto, son muy difíciles de preveer y de controlar sus efectos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; aboga por el diseño evolutivo. Sin embargo, para ello propugna una serie de prácticas que permiten controlar los efectos negativos de este tipo de diseño. Según la &lt;a href="http://www.agilemodeling.com/essays/costOfChange.htm"&gt;curva del cambio del software&lt;/a&gt;, el coste del cambio en programación aumenta exponencialmente a medida que avanza un proyecto, dificultando el diseño evolutivo. Pero esta curva se puede aplanar mediante una serie de prácticas que reducen el efecto de los cambios. Estas prácticas son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Pruebas&lt;/span&gt;: permiten controlar el efecto de los cambios eviatndo la introducción de nuevos errores.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Integración continua&lt;/span&gt;: permite mantener el equipo en sincronía evitando que los cambios afecten a más gente.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Refactorización&lt;/span&gt;: permite limpiar el código y hacerlo más mantenible y fácil de modificar.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;En el diseño evolutivo &lt;span style="font-weight:bold;"&gt;XP&lt;/span&gt; dice que “hay que hacer la cosa más simple que pueda funcionar” y que no lleve a cabo todo aquello que no sea necesario (principio YAGNI – “You Ain’t Gonna Need It”). Se trata de mantener el diseño lo más simple posible haciendo sólo aquello estructamente necesario. Para ello existen dos razones:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Si se hace algo que no es necesario ahora mismo se está comprometiendo el esfuerzo para quello que sí lo es. Además, se puede estar haciendo de forma incorrecta por falta de información, es mejor posponer su implementación hasta que se conozca con más detalle.&lt;/li&gt;&lt;li&gt;Un diseño complicado es más difícil de comprender e implementar que uno sencillo. Haciendo lo estrictamente necasio se tiene un diseño más sencillo y fácil de implementar.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Sin embargo, esta forma de mantener el diseño simple añadiendo posteriormente lo que se vaya convirtiendo en necesario sólo es factible si se están usando las prácticas anteriormente descritas para reducir el costo del cambio.&lt;br /&gt;&lt;br /&gt;Como pautas de le lo que es un diseño simple, &lt;span style="font-weight:bold;"&gt;Kent Beck&lt;/span&gt; expone los siguientes cuatro criterios:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Correr todas la pruebas.&lt;/li&gt;&lt;li&gt;Revelar toda la intención del código haciendo que sea fácil de leer.&lt;/li&gt;&lt;li&gt;Evitar duplicación.&lt;/li&gt;&lt;li&gt;El menor número de clases y métodos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;No es necesario perder demasiado tiempo buscando el diseño más simple. La refactorización permite irlo simplificando a medida que se va entendiendo. Tampoco es bueno usar patrones de diseño sin ton ni son, es mejor dejar que el diseño evolutivo te guíe hacia el uso de un patrón que introducirlo prematuramente.&lt;br /&gt;&lt;br /&gt;Respecto al uso de diagramas y &lt;span style="font-weight:bold;"&gt;UML XP&lt;/span&gt; dice que se usen si son útiles, pero no es partidario de su uso. Los diagramas pueden ser útiles para la comunicación siempre y cuando se reduzcan a la mayor sencillez posible. Sin embargo, el uso de diagramas se complica cuando se producen cambios durante la evolución del proyecto, porque es difícil mantenerlos en sincronía con el código.&lt;br /&gt;&lt;br /&gt;Algo importante en el diseño es evitar la irreversibilidad de las decisiones. De esta manera la toma de decisiones no es dramática porque las malas decisiones pueden ser deshechas. En este sentido es importante contar con sistemas de control del código que permitan garantizar la reversibilidad.&lt;br /&gt;&lt;br /&gt;Es importante contar con gente involucrada en el diseño. Alguien debe ejecercer control sobre el proyecto vigilando el diseño del código y responsabilizándose de él. Estas personas deben actuar cuando se detecta que el diseño puede verse comprometido o hay alguna dificultad técnica durante el proyecto. Esta rol es el del líder técnico. No tiene sentido el rol de arquitecto, puesto que no puede existir el diseño por parte de alguien que luego se desentienda de la construcción del software.&lt;br /&gt;&lt;br /&gt;El diseño de un proyecto se puede medir en función de la calidad del código base. Si la calidad del código base de un proyecto se deteriora y se vuelve más difícl trabajar, entonces el diseño es insuficiente. Éste es un criterio subjetivo, pero es la gente técnica la que primero sufre la dificultad de hacer cambios y a quienes se debe escuchar.&lt;br /&gt;&lt;br /&gt;Según &lt;span style="font-weight:bold;"&gt;Martin Fowler&lt;/span&gt;, la naturaleza del sideño ha cambiado. Ahora se buscan las siguientes habilidades:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mantener el código tan claro y simple&lt;/span&gt; como sea posible.&lt;/li&gt;&lt;li&gt;Ser capaz de &lt;span style="font-weight:bold;"&gt;refactorizar&lt;/span&gt;, haciendo mejoras en el diseño cuando sea necesario.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Conocer y reconocer patrones&lt;/span&gt; y cuándo evolucinar hacia ellos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Saber comunicar el diseño&lt;/span&gt; mediante diagramas, código y comunicación directa con las demás personas.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Como resumen, &lt;span style="font-weight:bold;"&gt;Martin Fowler&lt;/span&gt; aboga por un diseño evolutivo que permita comenzar con el desarrollo de forma temprana. Pero esto no se puede hacer de cualquier manera, es necesario introducir prácticas que faciliten el cambio durante el desarrollo de forma que el diseño pueda mejorar y adaptarse a las nuevas necesidades que vayan apareciendo.&lt;br /&gt;&lt;br /&gt;Esto va en contra de un diseño planeado que deja todo por sentado en un larga fase inicial y que es seguido por una fase de implemantación en que los cambios no se contemplan y que, cuando se incorporan porque terminan siendo absolutamente inevitables, son difíciles de incorporar, rompiendo el diseño previamente establecido e introduciendo una gran propensión a errores.&lt;br /&gt;&lt;br /&gt;El diseño evolutivo delega gran cantidad de trabajo de diseño en los desarrolladores. No existe la figura de arquitecto como persona que realiza todo el trabajo de diseño, sino como alguien que supervisa el trabajo de estos. Se debe contar con un equipo capaz y comprometido para poder seguir esta forma de trabajo, de lo contrario, se hace inviable.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/articles/designDead.html"&gt;Is Desing Dead? - Por Martin Fowler &lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.programacionextrema.org/articulos/designdead.es.html"&gt;¿Ha muerto el diseño? - Traducción de Alejandro Sierra&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.agilemodeling.com/essays/costOfChange.htm"&gt;Examining the Agile Cost of Change Curve&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-1092744182503846803?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/1092744182503846803/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/consideraciones-sobre-el-diseno.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1092744182503846803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1092744182503846803'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/06/consideraciones-sobre-el-diseno.html' title='Consideraciones sobre el diseño'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-1723438479859712655</id><published>2010-04-12T23:15:00.007+02:00</published><updated>2011-10-26T09:41:46.595+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>UML2</title><content type='html'>Este libro de &lt;a href="http://www.anayamultimedia.es/"&gt;Anaya Multimedia&lt;/a&gt; es la traducción al castellano de “&lt;span style="font-style:italic;"&gt;UML2 and the Unified Proces&lt;/span&gt;s”, escrito por Jim Arlow e Ila Neustadt. Este libro no sólo es una introducción al lenguaje de modelado &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; en su versión 2, también presenta el flujo de trabajo el &lt;span style="font-weight:bold;"&gt;Proceso Unificad&lt;/span&gt;o, que es el proceso de desarrollo de software creado por los autores de &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; y utiliza &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; como lenguaje de modelado.&lt;br /&gt;&lt;br /&gt;El libro, nos sumerge en &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;UP&lt;/span&gt; a través de los siguientes capítulos:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;¿Qué es UML?&lt;/span&gt;: Se presenta &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; como un lenguaje de modelado visual. &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; permite crear modelos de la arquitectura de los objetos de un sistema, capturando la estructura estática y el comportamiento dinámico del mismo a través de diagramas, compuestos de elementos y relaciones. Se presentan los mecanismos de especificación, adornos, divisiones comunes y extensibilidad que se utilizan en &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt; para construir el modelo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;¿Qué es el proceso unificado?&lt;/span&gt;: Es un proceso de ingeniería del software de los mismos autores que &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt;. Es un proceso dirigido por riesgo y requisitos, centrado en la arquitectura, iterativo e incremental. Cada iteración realiza los workflows de requisitos, análisis, diseño, implementación y prueba. Separa la vida del proyecto en las fases de comienzo, elaboración, construcción y transición.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El workflow de requisitos&lt;/span&gt;: El workflow de requisitos se desarrolla principalmente durante las fases de comienzo y elaboración y recoge y organiza los requisitos funcionales y no funcionales. Se presentan técnicas que ayudan a encontrar requisitos, como las entrevistas, cuestionarios y workshops.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Modelado del caso de uso&lt;/span&gt;: Los casos de uso son funciones que el sistema realiza en nombre de actores específicos. Se dan pautas sobre cómo encontrar estos casos de uso y define una especificación de caso de uso que los describe. Se indica la necesidad de crear una matriz de trazabilidad de requisitos que relacione los requisitos funcionales y los casos de uso.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Modelado avanzado de caso de uso&lt;/span&gt;: En este capítulo se explica la generalización de actores y la generalización, inclusión y extensión de casos de uso. Se dan sugerencias para escribir casos de uso.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El workflow de análisis&lt;/span&gt;: Se presenta el workflow de análisis, que trata de crear modelos que capturen los requisitos esenciales y las características del sistema deseado. Se presentan las características del modelo de análisis y los artefactos y actividades del workflow de análisis. Se dan reglas generales para el análisis.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Objetos y clases&lt;/span&gt;: Se presentan que son los objetos y las clases y su notación en &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Encontrar clases de análisis&lt;/span&gt;: Se presenta la actividad de análisis de un caso de uso, centrándose en la obtención de clases de análisis. Se definen las propiedades de estas clases de análisis y se dan reglas generales sobre sus propiedades. Se presentan las técnicas para encontrar estas clases, como el análisis nombre/verbo, el análisis CRC y los estereotipos RUP.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Relaciones&lt;/span&gt;: Se analizan las relaciones, conexiones semánticas entre los elementos de un modelo que son equivalentes a que una clase tenga un pseudoatributo que pueda albergar instancias de la otra clase. Las conexiones entre objetos son los vínculos, y las asociaciones son las conexiones entre clases. Las asociaciones pueden estar definidas por un nombre de asociación, nombres de roles, multiplicidad y navegabilidad. Se presentan las clases de asociación y las asociaciones cualificadas. Las dependencias son relaciones en que un cambio en el proveedor afecta al cliente. Las dependencias pueden ser de uso, de abstracción o de permiso.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Herencia y polimorfismo&lt;/span&gt;: La herencia de clase es una relación de generalización entre clases. La subclase puede añadir nuevas características o anular operaciones heredadas. Las clases abstractas tienen alguna operación abstracta y no se pueden heredar. El polimorfismo permite que una operación tenga distintas implementaciones según su clase. Se presentan los conjuntos de generalización y los powertypes.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Paquetes de análisis&lt;/span&gt;: El paquete es el mecanismo de agrupación de &lt;span style="font-weight:bold;"&gt;UML&lt;/span&gt;. Todo elemento del modelo está contenido en un paquete. Un paquete define un conjunto de nombres encapsulado. Existen varias relaciones de dependencia entre paquetes: use, import, access, trace, merge. El análisis de la arquitectura de un sistema trata de dividir conjuntos cohesivos de clases de análisis en paquetes de análisis. Es importante maximizar la cohesión dentro de los paquetes y minimizar las dependencias de otros paquetes.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Realización de casos de uso&lt;/span&gt;: Las realizaciones de casos de uso muestran cómo las instancias de clases de análisis interactúan para realizar los requisitos funcionales especificados por los casos de uso. Las interacciones están representadas por las líneas de vida de los participantes y los mensajes que se envían entre ellos para comunicarse. Las interacciones se expresan mediante diagramas de interacción, que pueden ser principalmente de secuencia o de comunicación.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Realización avanzada de casos de uso&lt;/span&gt;: Se muestran características avanzadas de los diagramas de interacción, como las ocurrencias de interacción, que pueden hacer uso de parámetros o puertas, y las continuaciones.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Diagramas de actividad&lt;/span&gt;: Son diagramas de flujo orientados a objeto que se utilizan para modelar todo tipo de procesos. Tienen semántica de Redes de Petri. Las actividades son redes de nodos conectadas por extremos. Se presenta la notación de los diagramas de actividad.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Diagramas avanzado de actividad&lt;/span&gt;: Se presentan características avanzadas de diagramas de actividad, como regiones de actividad interrumpibles, pins de excepción, nodos protegidos, nodos de expansión, envío y recepción de señales y conjuntos de parámetros.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Workflow de diseño&lt;/span&gt;: En esta actividad se trata de determinar como se implementará la funcionalidad especificada en el modelo de análisis. Es la principal actividad de la última parte de la fase de elaboración y de la primera parte de la fase de construcción. Se discute la conveniencia de mantener modelos aparte de análisis y diseño.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Diseñar clases&lt;/span&gt;: Las clases de diseño son clases cuyas especificaciones se han completado hasta un nivel que se puede implementar. Proceden tanto del ámbito del problema como del de la solución. Tienen especificaciones completas y presentan las características de ser completas, suficientes, sencillas, altamente cohesionadas y poco acopladas. Las clases de diseño hacen uso de la herencia y la realización de interfaz.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mejorar relaciones de análisis&lt;/span&gt;: Convertir relaciones de análisis en relaciones de diseño implica convertir asociaciones en agregación o composición, implementar clases de asociación, implementar asociaciones uno a muchos, muchos a uno, muchos a muchos, bidireccionales, añadir navegabilidad, añadir multiplicidad, añadir nombres de rol a los extremos y utilizar clasificadores estructurados.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Interfaces y componentes&lt;/span&gt;: Las interacciones entre subsistemas están mediadas por interfaces, que especifican un conjunto de características públicas. Diseñar mediante interfaces permite hacer las cosas más flexibles a costa de mayor complejidad. Los componentes son partes modulares del sistema y que encapsulan contenidos, siendo éstos componentes reemplazables. Un subsistema es un componente que actúa como una unidad de descomposición para un sistema más amplio. Se utilizan interfaces para ocultar los detalles de implementación de los subsistemas.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Realización de un caso de uso&lt;/span&gt;: diseño: La realización de un caso de uso en diseño es una extensión de la realización de un caso de uso en análisis y se encarga de encontrar las clases de diseño, interfaces y componentes que interactúan para proporcionar el comportamiento de un caso de uso. La realización de un caso de uso se muestra en diagramas de interacción de diseño y diagramas de clase de diseño. Se utilizan clases activas para modelar concurrencia, diagramas de interacción de subsistema para mostrar interacciones entre sus partes y diagramas de tiempo para modelar restricciones de tiempo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Máquinas de estado&lt;/span&gt;: Las máquinas de estado se basan en el trabajo de Harel y modelan comportamiento dinámico de un objeto reactivo. Las máquinas de estado pueden ser de comportamiento o de protocolo. Los diagramas de estado se componen de acciones, actividades, estados, transiciones y eventos.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Máquinas de estado avanzadas&lt;/span&gt;: Los estados compuestos pueden tener una o más submáquinas anidadas. Un estado compuesto secuencial tiene una submáquina anidada, un estado compuesto concurrente contiene dos o más submáquinas anidadas que se ejecutan concurrentemente. La historia (superficial o profunda) permite que un superestado recuerde el último subestado antes de una transición de salida.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;El workflow de implementación&lt;/span&gt;: Es el foco principal de la fase de construcción y trata sobre la transformación de un modelo de diseño en código ejecutable.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Despliegue&lt;/span&gt;: Los diagramas de despliegue permiten modelar la distribución de un sistema de software sobre hardware físico. Un diagrama de despliegue está formado por nodos, relaciones y componentes.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;El libro termina con material adicional, como una referencia al Lenguaje de Restricción de Objetos (OCL – Object Constraint Language).&lt;br /&gt;&lt;br /&gt;Es un libro que me ha resultado fácil de leer y que creo que hace una buena introducción al modelado de sistemas en análisis y diseño, proporcionando técnicas útiles y buenos consejos.&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=844152033X&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=844152033X&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-1723438479859712655?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/1723438479859712655/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/04/uml2.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1723438479859712655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1723438479859712655'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/04/uml2.html' title='UML2'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-5991292367155664054</id><published>2010-04-09T20:39:00.012+02:00</published><updated>2010-06-08T08:42:47.896+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JBoss Drools'/><title type='text'>JBoss Drools</title><content type='html'>Según la Wikipedia: "&lt;span style="font-style:italic;"&gt;Las reglas de negocio describen las políticas, normas, operaciones, definiciones y restricciones presentes en una organización y que son de vital importancia para alcanzar sus objetivos. Las reglas de negocio especifican en detalle lo que una organización puede hacer.&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;Ejemplos de reglas de negocio podrían ser:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;"A una persona que ingresa más de 20.000 euros al año Hacienda le retiene el 15%"&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;"A los clientes que gasten más de 1.000 euros se les hace un descuento del 5%"&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Como se ve en los ejemplos, las reglas de negocio tienen una semántica &lt;span style="font-style:italic;"&gt;if/then&lt;/span&gt;, si se cumple una determinada condición se debe realizar una determinada acción.&lt;br /&gt;&lt;br /&gt;Cuando un negocio dispone de muchas reglas que se deben aplicar, las aplicaciones que las gestionan se convierten en una maraña de código formado por estructuras &lt;span style="font-style:italic;"&gt;if/else&lt;/span&gt; anidadas, que dificultan enormemente la comprensión y mantenibilidad del código. &lt;br /&gt;&lt;br /&gt;Si las reglas de negocio se aíslan del resto del código, se está separando la verdadera inteligencia sobre el negocio (las reglas) del resto del programa. Los sistemas de gestión de reglas de negocio (&lt;span style="font-weight:bold;"&gt;BRMS – Bussiness Rule Management System&lt;/span&gt;) permiten gestionar de forma independiente las reglas de negocio. Facilitan la modificación o inclusión de nuevas reglas en tiempo de ejecución.&lt;br /&gt; &lt;br /&gt;Dentro de los sistemas de gestión de reglas de negocio en Java más populares hoy en día encontramos &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt;. &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt; es un &lt;span style="font-weight:bold;"&gt;BRMS&lt;/span&gt; de JBoss que implementa la &lt;span style="font-style:italic;"&gt;Java Rule Engine API (JSR 94)&lt;/span&gt; y utiliza una implementación mejorada del algoritmo de Rete para la ejecución de reglas.&lt;br /&gt;&lt;br /&gt;A continuación voy a mostrar un ejemplo simple de cómo utilizar &lt;span style="font-weight:bold;"&gt;Drool&lt;/span&gt;s y cómo permite parametrizar las reglas del negocio de forma externa a la aplicación que las utiliza. Antes de comenzar, recomiendo haber instalado &lt;span style="font-weight:bold;"&gt;JBoss Tools&lt;/span&gt; en &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt;, puesto que nos ofrecerá herramientas que facilitan el desarrollo de apicaciones que usan &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;El caso de uso que vamos a implementar en el ejemplo será el de una tienda online. En esta tienda hay dos tipos de clientes, aquellos que se han registrado previamente y los que no. Para todos los clientes que gasten más de 1.000 euros se les hace un descuento del 5%. A los que se han registrado, se les ofrece un descuento adicional del 5% en todas su compras, independientemente del importe. Vamos a hacer una aplicación que calcule el descuento que corresponde a cada usuario.&lt;br /&gt;&lt;br /&gt;En primer lugar creamos un proyecto &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt; en &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt;, lo que es posible gracias a las utilidades instaladas en &lt;span style="font-weight:bold;"&gt;JBoss Tools&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/S792dnutpfI/AAAAAAAAK7s/dQUTFUGoGVo/s1600/imagen1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/S792dnutpfI/AAAAAAAAK7s/dQUTFUGoGVo/s320/imagen1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5458211524649526770" /&gt;&lt;/a&gt;&lt;br /&gt;El nuevo proyecto se va a llamar &lt;span style="font-style:italic;"&gt;CalculadorDescuento&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/S792vGl2AUI/AAAAAAAAK70/aoexJ5f6CHI/s1600/imagen2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/S792vGl2AUI/AAAAAAAAK70/aoexJ5f6CHI/s320/imagen2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5458211824991600962" /&gt;&lt;/a&gt;&lt;br /&gt;El asistente nos permite crear ejemplos de uso de &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/S793OBAYRsI/AAAAAAAAK78/Pfzr_gZxg-M/s1600/imagen3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/S793OBAYRsI/AAAAAAAAK78/Pfzr_gZxg-M/s320/imagen3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5458212356068230850" /&gt;&lt;/a&gt;&lt;br /&gt;Es necesario especificar el &lt;span style="font-style:italic;"&gt;runtime&lt;/span&gt; de &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt;, es decir, la carpeta donde se encuentran las librerías de &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_WQMxntNMWT0/S793jR4UhYI/AAAAAAAAK8E/sxfKXQ5t6TY/s1600/imagen4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_WQMxntNMWT0/S793jR4UhYI/AAAAAAAAK8E/sxfKXQ5t6TY/s320/imagen4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5458212721375085954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/S793tUjZ8gI/AAAAAAAAK8M/-09StQED5RA/s1600/imagen5.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/S793tUjZ8gI/AAAAAAAAK8M/-09StQED5RA/s320/imagen5.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5458212893891359234" /&gt;&lt;/a&gt;&lt;br /&gt;Ahora, creamos una clase &lt;span style="font-style:italic;"&gt;Cliente&lt;/span&gt; que refleje los datos del cliente, su nombre, si está registrado, el gasto que ha realizado y el descuento que se le aplica:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.drools;&lt;br /&gt;&lt;br /&gt;public class Cliente {&lt;br /&gt; String nombre;&lt;br /&gt; boolean registrado;&lt;br /&gt; float gasto;&lt;br /&gt; float descuento;&lt;br /&gt; &lt;br /&gt; // Getters y setters...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;En la clase &lt;span style="font-style:italic;"&gt;CalculadorDescuento&lt;/span&gt; se crea el siguiente método, que lee las reglas que se han definido en el fichero &lt;span style="font-style:italic;"&gt;Descuentos.drl&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;private static KnowledgeBase readKnowledgeBase()&lt;br /&gt; throws Exception {&lt;br /&gt; KnowledgeBuilder kbuilder = &lt;br /&gt;  KnowledgeBuilderFactory.newKnowledgeBuilder();&lt;br /&gt; kbuilder.add(&lt;br /&gt; ResourceFactory.newClassPathResource("Descuentos.drl"),&lt;br /&gt; ResourceType.DRL);&lt;br /&gt; KnowledgeBuilderErrors errors = kbuilder.getErrors();&lt;br /&gt; if (errors.size() &gt; 0) {&lt;br /&gt;  for (KnowledgeBuilderError error: errors) {&lt;br /&gt;   System.err.println(error);&lt;br /&gt;  }&lt;br /&gt;  throw new IllegalArgumentException("Could not parse knowledge.");&lt;br /&gt; }&lt;br /&gt; KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();&lt;br /&gt; kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());&lt;br /&gt; return kbase;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;El método &lt;span style="font-style:italic;"&gt;main&lt;/span&gt; de esta clase crea una sesión de &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt; y crea también varios clientes que introduce en esta sesión a los que se aplican las reglas que se definen en el fichero &lt;span style="font-style:italic;"&gt;Descuentos.drl&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;public static void main(String[] args) {&lt;br /&gt; try {&lt;br /&gt;  // Cargar las reglas&lt;br /&gt;  KnowledgeBase kbase = readKnowledgeBase();&lt;br /&gt;  StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();&lt;br /&gt;  KnowledgeRuntimeLogger logger =&lt;br /&gt;   KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");&lt;br /&gt;   &lt;br /&gt;  // Cliente no registrado que gasta más de 1.000 euros&lt;br /&gt;  Cliente cliente1 = new Cliente();&lt;br /&gt;  cliente1.setNombre("Cliente 1");&lt;br /&gt;  cliente1.setRegistrado(false);&lt;br /&gt;  cliente1.setGasto(1200);   &lt;br /&gt;  ksession.insert(cliente1);&lt;br /&gt;   &lt;br /&gt;  // Cliente registrado que gasta menos de 1.000 euros&lt;br /&gt;  Cliente cliente2 = new Cliente();&lt;br /&gt;  cliente2.setNombre("Cliente 2");&lt;br /&gt;  cliente2.setRegistrado(true);&lt;br /&gt;  cliente2.setGasto(800);   &lt;br /&gt;  ksession.insert(cliente2);&lt;br /&gt;   &lt;br /&gt;  // Cliente registrado que gasta más de 1.000 euros&lt;br /&gt;  Cliente cliente3 = new Cliente();&lt;br /&gt;  cliente3.setNombre("Cliente 3");&lt;br /&gt;  cliente3.setRegistrado(true);&lt;br /&gt;  cliente3.setGasto(1600);   &lt;br /&gt;  ksession.insert(cliente3);&lt;br /&gt;   &lt;br /&gt;  ksession.fireAllRules();&lt;br /&gt;  logger.close();&lt;br /&gt;   &lt;br /&gt;  System.out.println("El cliente 1 tiene un descuento de " &lt;br /&gt;   + cliente1.getDescuento() + " euros.");&lt;br /&gt;  System.out.println("El cliente 2 tiene un descuento de " &lt;br /&gt;   + cliente2.getDescuento() + " euros.");&lt;br /&gt;  System.out.println("El cliente 3 tiene un descuento de " &lt;br /&gt;   + cliente3.getDescuento() + " euros.");&lt;br /&gt;   &lt;br /&gt; } catch (Throwable t) {&lt;br /&gt;  t.printStackTrace();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Ahora vamos a ver cómo se definen las reglas anteriormente descritas en el fichero &lt;span style="font-style:italic;"&gt;Descuentos.drl&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint mvec"&gt;package com.roldan.drools&lt;br /&gt;&lt;br /&gt;rule "Gastos superior a 1.000 euros"&lt;br /&gt; when&lt;br /&gt;  cliente : Cliente( gasto &gt; 1000 )&lt;br /&gt; then &lt;br /&gt;  System.out.println("El cliente " &lt;br /&gt;   + cliente.getNombre() + " ha gastado más de 1.000 euros.");&lt;br /&gt;  cliente.setDescuento(&lt;br /&gt;   cliente.getDescuento() + cliente.getGasto()*5/100);&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;rule "Cliente registrado"&lt;br /&gt; when&lt;br /&gt;  cliente : Cliente( registrado == true )&lt;br /&gt; then &lt;br /&gt;  System.out.println("El cliente " &lt;br /&gt;   + cliente.getNombre() + " está registrado.");&lt;br /&gt;  cliente.setDescuento(&lt;br /&gt;   cliente.getDescuento() + cliente.getGasto()*5/100);&lt;br /&gt;end&lt;/pre&gt;&lt;br /&gt;Al ejecutar la clase principal, obtenemos la siguiente salida que nos informa sobre lo que ha pasado:&lt;br /&gt;&lt;pre class="prettyprint log"&gt;El cliente Cliente 3 está registrado.&lt;br /&gt;El cliente Cliente 3 ha gastado más de 1.000 euros.&lt;br /&gt;El cliente Cliente 2 está registrado.&lt;br /&gt;El cliente Cliente 1 ha gastado más de 1.000 euros.&lt;br /&gt;&lt;br /&gt;El cliente 1 tiene un descuento de 60.0 euros.&lt;br /&gt;El cliente 2 tiene un descuento de 40.0 euros.&lt;br /&gt;El cliente 3 tiene un descuento de 160.0 euros.&lt;/pre&gt;&lt;br /&gt;En esta traza vemos qué condiciones ha cumplido cada uno de los clientes y el resultado final de aplicarles todos los descuentos a los que tienen derecho según su condición.&lt;br /&gt;&lt;br /&gt;Aunque este es un ejemplo muy sencillo, se puede apreciar que ahora, si se quisiese variar el descuento aplicado para cada uno de estos casos o aplicar un nuevo descuento según otra condición distinta, no haría falta manipular el código de la aplicación. Bastaría con modificar las reglas definidas de forma separada en el fichero Descuentos.drl.&lt;br /&gt;&lt;br /&gt;Esto no es más que una sencilla aplicación de lo que ofrece &lt;span style="font-weight:bold;"&gt;Drools&lt;/span&gt;, aunque este &lt;span style="font-weight:bold;"&gt;BRMS&lt;/span&gt; es mucho más potente que esto y ofrece mucha más funcionalidad que ya iremos viendo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://java.sys-con.com/node/45082"&gt;Does Your Project Need a Rule Engine&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.dosideas.com/noticias/java/592-primeros-pasos-con-drools.html"&gt;Primeros pasos con Drools&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Drools"&gt;Drools en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Business_rules"&gt;Bussiness rule en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ibm.com/developerworks/java/library/j-drools/"&gt;Implement business logic with the Drools rules engine&lt;/a&gt;&lt;br /&gt;&lt;a href="http://balteus.blogspot.com/2009/05/open-source-brebrms-jsr-94-compliant.html"&gt;Open Source BRE/BRMS JSR-94 compliant&lt;/a&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/developer/technicalArticles/J2SE/JavaRule.html"&gt;Getting Started With the Java Rule Engine API (JSR 94): Toward Rule-Based Applications&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-5991292367155664054?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/5991292367155664054/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/04/jboss-drools.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5991292367155664054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5991292367155664054'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/04/jboss-drools.html' title='JBoss Drools'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_WQMxntNMWT0/S792dnutpfI/AAAAAAAAK7s/dQUTFUGoGVo/s72-c/imagen1.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-3433834649609679241</id><published>2010-03-29T15:12:00.007+02:00</published><updated>2010-06-16T10:21:29.349+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><title type='text'>Los Métodos Ágiles</title><content type='html'>Entre finales de la década pasada y principios de la actual surgieron una serie de métodos de desarrollo de software contrapuestos a la visión clásica de la ingeniería del software. Estos métodos se postulan en contra del control de los proyectos de software basado en la predictibilidad de las tareas a desarrollar, y proponen una orientación de estos que facilite su adaptabilidad de forma continua a las condiciones cambiantes de dichos proyectos.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/articles/newMethodology.html"&gt;En su artículo “&lt;span style="font-style:italic;"&gt;The New Metodology&lt;/span&gt;”&lt;/a&gt;, Martin Fowler hace una exposición de estos métodos, llamados &lt;span style="font-weight:bold;"&gt;métodos ágiles&lt;/span&gt;. Voy a hacer un pequeño repaso a este artículo a través de la &lt;a href="http://www.programacionextrema.org/articulos/newMethodology.es.html"&gt;traducción al castellano realizada por Alejandro Sierra&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Según Martin Fowler, la forma más habitual de trabajar en un proyecto de desarrollo de software es a través de la prueba y error con un mínimo plan inicial, y completando el diseño con decisiones a corto plazo. Esto funciona bien para proyectos pequeños pero no para proyectos más grandes, que necesitan de largas fases de prueba a posteriores que desbordan toda planificación.&lt;br /&gt;&lt;br /&gt;Para remediar esta situación se dispone de metodologías de desarrollo, que imponen un proceso disciplinado que trata de convertir el desarrollo de software en algo predecible y eficiente, similar a otras ingerierías. Sin embargo, estos métodos introducen mucha burocracia en los proyectos, retrasando su avance.&lt;br /&gt;&lt;br /&gt;En opocición a estas metodologías, surgen los &lt;span style="font-weight:bold;"&gt;métodos ágiles&lt;/span&gt;, que se sitúan en medio de las metodologías tradicionales y la falta de metodología. Están más orientados a producir código que documentación debido a sus dos características principales:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Son adaptables en lugar de predictivos&lt;/span&gt;. En vez de planear todos los aspectos del proyecto tratan de adaptarse en los cambios que se producen durante la ejecución del proyecto.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Son orientados a la gente en lugar de al proceso&lt;/span&gt;. Tratan de apoyar el equipo de desarrollo en su trabajo, en vez de forzar al equipo a trabajar de una forma estricta.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Las ingenierías tradicionales enfatizan en que hay que planear antes de construir. En ellas, el plan define de forma exacta cómo se llevará a cabo la construcción. La realización del plan es una actividad mucho más exigente que la ejecución, y requiere de personal especializado. La ejecución es algo más mecánico que puede ser llevado a cabo por personal de nivel bajo.&lt;br /&gt;&lt;br /&gt;Sin embargo, en desarrollo de software, no es fácil diseñar un plan que convierta el desarrollo en una actividad de construcción predecible. Un diseño en UML no suele ser todo lo completo que sería necesario y suele variar con respecto a la implementación. En estos casos el costo del esfuerzo del plan es mucho mas cercano a la implementación que en proyectos de ingenierías tradicionales.&lt;br /&gt;&lt;br /&gt;Por tanto, se observa que en el desarrollo de software la construcción es barata ya que casi todo el esfuerzo está en el diseño, que es un proceso creativo. Como los procesos creativos no se planean fácilmente, la previsibilidad es una meta difícil de alcanzar.&lt;br /&gt;&lt;br /&gt;Además, en los proyectos de desarrollo de software, los cambios en los requisitos son habituales, debido a las condiciones cambiantes en las que se dearrollan los proyectos. Además, ya que el desarrollo de software es una actividad de diseño, esta es difícil de planear y cuantificar, por lo que la estimación de los requisitos es difícil, y con ello la posibilidad de obtener un plan predecible.&lt;br /&gt;&lt;br /&gt;Es por ello que en desarrollo de software es necesario un proceso que controle esta imprevisibilidad mediante adaptabilidad. Esto se logra mediante el desarrollo iterativo, que permite obtener retralimentación sobre la situación del proyecto en intervalos frecuentes.&lt;br /&gt;&lt;br /&gt;De esta forma, se hace evidente tanto la situación actual del proyecto como posibles fallos de entendimiento del mismo o bugs.&lt;br /&gt;&lt;br /&gt;Sin embargo, este tipo de desarrollo necesita un tipo de cliente distinto al tradicional. El cliente debe estar involucrado con el equipo, revisando el resultado de las iteraciones y proporcionando información sobre el proyecto de forma constante. Además, el contrato de precio fijo deja de tener sentido. &lt;br /&gt;&lt;br /&gt;Ya que no se puede fijar tiempo, precio y alcance, lo normal es fijar precio y tiempo y permitir que el alcance varie de manera controlada. Gracias a las iteraciones, el cliente tiene control a escala fina sobre la evolución del proyecto, pudiendo fijar la dirección del proyecto de acuerdo a sus prioridades. Esta visibilidad sobre el proyecto que otorgan las iteraciones permite controlar también el riesgo.&lt;br /&gt;&lt;br /&gt;En un proceso de este tipo se requiere de un equipo eficaz de desarrolladores. Las personas involucradas en un proyecto ya no son recursos reemplazables, debido a que el trabajo que se realiza es algo creativo y en este tipo de trabajo hay grandes diferencias entre las personas. Además, si las personas trabajan en equipo, se establecen sinergias que hacen que el equipo sea más que la suma de sus miembros.&lt;br /&gt;&lt;br /&gt;También hay que reconocer a los profesionales de software como profesionales competentes capaces de dirigir su trabajo técnico. La labor de la gerencia será favorecer este trabajo con la menor interferencia posible.&lt;br /&gt;&lt;br /&gt;Las &lt;span style="font-weight:bold;"&gt;metodologías ágiles&lt;/span&gt; tambien rechazan las métricas como herramienta de control del rendimiento de las personas, puesto que no se han encontrado métricas fiables en este sentido. Por ello favorecen la gestión delegatoria, donde los que finalmente hacen el trabajo deciden sobre cómo hacerlo.&lt;br /&gt;&lt;br /&gt;Pero para llevar esto a cabo no se puede confiar sólo en la parte técnica. Es necesario que los expertos de negocio estén accesibles y pueden resolver las dudas que surjan a medida que el proyecto avanza. Se favorece la comunicación interdisciplinar.&lt;br /&gt;&lt;br /&gt;Además, el propio proceso de desarrollo debe evaluarse y someterse a modificaciones que permitan mejorarlo.&lt;br /&gt;&lt;br /&gt;Varias metodologías comparten estas bases. Entre ellas, podemos citar:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;XP.&lt;/li&gt;&lt;li&gt;Scrum.&lt;/li&gt;&lt;li&gt;Crystal.&lt;/li&gt;&lt;li&gt;FDD (Feature Driven Development).&lt;/li&gt;&lt;li&gt;DSDM (Dynamic System Development Method).&lt;/li&gt;&lt;li&gt;Lean.&lt;/li&gt;&lt;li&gt;Etc.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A pesar de todo, es importante resaltar que el uso de estas metodologías no es apropiado para todos los casos. Hay que considerar la naturaleza de cada proyecto y evaluar si encajaría con estos principios o no.&lt;br /&gt;&lt;br /&gt;Factores que sugieren un proceso adaptable:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Requisitos inciertos.&lt;/li&gt;&lt;li&gt;Desarrolladores responsables.&lt;/li&gt;&lt;li&gt;Clientes implicados.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Factores que sugieren un proceso predictivo:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Equipos grandes.&lt;/li&gt;&lt;li&gt;Contratos con alcance y precio fijo.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;Sin embargo, no todo son parabienes para estos métodos y su aparición ha suscitado amplios debates entre sus defensores y los defensores de las metodologías tradicionales. Como ejemplo, este &lt;a href="http://www.javahispano.org/contenidos.item.action?id=1602515961&amp;menuId=NEWS"&gt;artículo de Miguel Ángel Abián&lt;/a&gt; y el &lt;a href="http://www.javahispano.org/contenidos/es/metodos_giles/"&gt;debate que suscitó dentro de la comunidad JavaHispano&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/articles/newMethodology.html"&gt;&lt;span style="font-style:italic;"&gt;The New Metodology&lt;/span&gt; por Martin Fowler&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.programacionextrema.org/articulos/newMethodology.es.html"&gt;Traducción al castellano del artículo &lt;span style="font-style:italic;"&gt;The New Metodology&lt;/span&gt; por Martin Fowler realizada por Alejandro Sierra&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.javahispano.org/contenidos.item.action?id=1602515961&amp;menuId=NEWS"&gt;Artículo de Miguel Ángel Abián sobre las Metodologías Agiles&lt;/a&gt;&lt;br /&gt;&lt;a href=" http://www.javahispano.org/contenidos/es/metodos_giles/"&gt;Discusión en JavaHispano en torno al artículo de Miguel Ángel Abián&lt;/a&gt;&lt;br /&gt;&lt;a href="http://balteus.blogspot.com/2009/10/la-falacia-de-la-ingenieria-del.html"&gt;&lt;span style="font-style:italic;"&gt;La Falacia de la Ingeniería del Software&lt;/span&gt; por Samuel Zarza&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.dzone.com/links/r/waterfall_vs_agile_can_they_be_friends.html"&gt;&lt;span style="font-style:italic;"&gt;Waterfall vs. Agile: Can they be Friends?&lt;/span&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-3433834649609679241?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/3433834649609679241/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/03/los-metodos-agiles.html#comment-form' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3433834649609679241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3433834649609679241'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/03/los-metodos-agiles.html' title='Los Métodos Ágiles'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-986505564920911145</id><published>2010-02-24T11:17:00.004+01:00</published><updated>2010-08-31T13:43:47.129+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Lean'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><title type='text'>Lean</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Lean manufacturing&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;Lean production&lt;/span&gt;, conocido normalmente como &lt;span style="font-weight:bold;"&gt;Lean&lt;/span&gt;, es una es una filosofía de gestión cuyo origen principal es el &lt;span style="font-weight:bold;"&gt;TPS (Toyota Production System)&lt;/span&gt;, y que considera como desperdicio cualquier gasto de recursos que no esté orientado a la creación de valor para el cliente. Lo que intenta es crear un mayor valor con el menor gasto.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Lean&lt;/span&gt; intenta optimizar el flujo del proceso de producción, tratando de incrementar la eficiencia, reducir el gasto, y usar métodos empíricos para decidir qué es lo verdaderamente importante.&lt;br /&gt;&lt;br /&gt;La &lt;span style="font-weight:bold;"&gt;metodología de desarrollo de software Lean&lt;/span&gt; es una translación de los principios y prácticas de la manufacturación Lean hacia el dominio del desarrollo del software. El &lt;span style="font-weight:bold;"&gt;desarrollo de software Lean&lt;/span&gt; tiene origen en el un libro del mismo nombre, escrito por Mary y Tom Poppendieck.&lt;br /&gt; &lt;br /&gt;El desarrollo Lean se resume en los siguientes siete principios:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Eliminar los residuos.&lt;/li&gt;&lt;li&gt;Fomentar el aprendizaje.&lt;/li&gt;&lt;li&gt;Retrasar las decisiones.&lt;/li&gt;&lt;li&gt;Reaccionar rápidamente.&lt;/li&gt;&lt;li&gt;Potenciar el equipo.&lt;/li&gt;&lt;li&gt;Fomentar la integridad.&lt;/li&gt;&lt;li&gt;Ver todo el conjunto.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A continuación, pasamos a explicar cada uno de estos principios.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Eliminar los residuos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En &lt;span style="font-weight:bold;"&gt;Lean&lt;/span&gt;, todo lo que no añade valor al cliente se considera un residuo. Hay que ser capaz de reconocer las actividades que son residuos. Si el resultado esperado se puede alcanzar sin realizar alguna actividad, esta actividad es un residuo:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;La codificación parcial eventualmente abandonada durante el proceso de desarrollo es un residuo.&lt;/li&gt;&lt;li&gt;Los procesos extra y funcionalidades que no utilizan con frecuencia por los clientes son residuos.&lt;/li&gt;&lt;li&gt;Las esperas ocasionadas por otras actividades, equipos o procesos son residuo.&lt;/li&gt;&lt;li&gt;Defectos y menor calidad son los residuos.&lt;/li&gt;&lt;li&gt;Gastos generales de gestión que no producen valor real son residuos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A continuación se deben señalar las fuentes de los residuos y eliminarlos. Y todo ello debe hacerse de forma iterativa.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Fomentar el aprendizaje&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;El desarrollo de software es un proceso de aprendizaje continuo. La forma más eficaz para mejorar un entorno de desarrollo de software es el aprendizaje:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;La acumulación de defectos debe evitarse ejecutando las pruebas tan pronto como el código está escrito.&lt;/li&gt;&lt;li&gt;En lugar de añadir más documentación o planificación detallada, las distintas ideas podrían ser juzgados escribiendo código y construyendo.&lt;/li&gt;&lt;li&gt;El proceso de recopilación de requisitos de usuarios podría simplificarse mediante la presentación de las pantallas de los usuarios finales y para que estos puedan hacer sus aportes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;El proceso de aprendizaje es acelerado por el uso de ciclos de iteración cortos que incrementan el &lt;span style="font-style:italic;"&gt;feedback&lt;/span&gt; de los clientes, ayuda a determinar la fase actual de desarrollo y ajusta los esfuerzos para introducir mejoras en el futuro.&lt;br /&gt; &lt;br /&gt;Durante estos ciclos, tanto los clientes como el equipo de desarrollo aprenden sobre el dominio del problema y buscar posibles soluciones para un mejor desarrollo. De esta forma los clientes comprenden mejor sus necesidades y los desarrolladores aprenden a satisfacerlas mejor.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Retrasar las decisiones&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;El desarrollo de software está siempre asociado con cierto grado de incertidumbre. Los mejores resultados se alcanzan cuando se puede decidir entre varias opciones basándose en hechos y no en suposiciones y pronósticos inciertos. &lt;br /&gt;&lt;br /&gt;Cuanto más complejo es un proyecto, más capacidad para el cambio debe incluirse en este, así que debe permitirse el retraso en las decisiones importantes. Este enfoque de desarrollo puede llevar a opciones antes a los clientes. Por lo tanto, es conveniente retrasar algunas decisiones cruciales hasta que los clientes se hayan reconocido mejor sus necesidades. También permite la adaptación tardía a los cambios y previene de las costosas decisiones delimitadas por la tecnología.&lt;br /&gt;&lt;br /&gt;Esto no significa que no haya un planificación del proceso. Por el contrario, las actividades de planificación se centran en las diferentes opciones y se las adapta a la situación actual. Esto permite clarificar las situaciones confusas y establecer las pautas para una acción rápida.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Reaccionar rápidamente&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En el mercado actual, cuanto antes se entrega el producto final sin defectos considerables, más pronto se pueden recibir comentarios, que pueden ser incorporados en la siguiente iteración. Cuanto más cortas sean las iteraciones, mejor es el aprendizaje y la comunicación dentro del equipo.&lt;br /&gt; &lt;br /&gt;La velocidad asegura el cumplimiento de las necesidades actuales del cliente y les da la oportunidad de demorarse pensando lo que realmente necesitan, hasta que adquieran un mejor conocimiento. &lt;br /&gt;&lt;br /&gt;La ideología de producción &lt;span style="font-style:italic;"&gt;Just In Time&lt;/span&gt; se aplica a programas de desarrollo. El equipo se organiza y se divide las tareas para lograr el resultado necesario para una iteración específica. El cliente dispone los requisitos necesarios en pequeñas historias y los desarrolladores estimarán el tiempo necesario para el desarrollo de cada una de ellas. Cada mañana, cada miembro del equipo evalúa lo que se ha hecho ayer, y lo que hay que hacer hoy y mañana, y pregunta por cualquier nueva entrada necesaria de parte de sus colegas o del cliente.&lt;br /&gt; &lt;br /&gt;Otra idea clave se establece a base de diseño. Si un nuevo sistema es necesario, tres equipos pueden diseñar soluciones al mismo problema. Cada equipo aprende sobre el problema y diseña una posible solución. Cuando una solución se considera irrazonable, se desecha. Al final de un periodo, los diseños sobrevivientes se comparan y se elige uno, quizá con algunas modificaciones basadas en el aprendizaje de los demás. Mediante esta práctica se minimiza el riesgo provocado por un solo gran diseño realizado por adelantado.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Potenciar el equipo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hasta el momento los administradores dicen a los trabajadores cómo hacer su trabajo. Ahora, los roles cambian, los  trabajadores son los que dicen qué acciones podrían tomarse y sugieren mejoras. Los directores de proyecto más experimentados dicen que la clave de éxito de los proyectos es: "Buscar la buena gente y dejarles hacer su propio trabajo".&lt;br /&gt; &lt;br /&gt;Otra creencia errónea ha sido considerar a las personas como recursos. En el desarrollo de software, las personas necesitan motivación y un objetivo hacia el cual trabajar, con la garantía de que el equipo puede elegir sus propios compromisos. Los desarrolladores deberían tener acceso a los clientes, el jefe de equipo debe proporcionar apoyo y ayuda en situaciones difíciles, y asegurarse de mantener el espíritu de equipo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Fomentar la integridad&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La integridad consiste en que los componentes separados del sistema función bien tanto juntos como en un todo.&lt;br /&gt;&lt;br /&gt;Una de las maneras más saludables hacia una arquitectura que mantinen la integridad es la refactorización, que consiste en mantener la sencillez, la claridad, la cantidad mínima de funcionalidades en el código. Las repeticiones en el código son signo un mal diseños de código y deben evitarse. El completo y automatizado proceso de construcción debe ir acompañada de una suite completa y automatizada de pruebas, tanto para desarrolladores y clientes, que tengan la misma versión, sincronización y semántica que el sistema actual. &lt;br /&gt;&lt;br /&gt;Al final, la integridad debe ser verificada con una prueba global, garantizando que el sistema hace lo que el cliente espera haga.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ver todo el conjunto&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Los sistemas de software hoy en día no son simplemente la suma de sus partes, sino también el producto de sus interacciones. Cuanto mayor sea el sistema, más serán las organizaciones que participan en su desarrollo y más partes son las desarrolladas por diferentes equipos; mayor es la importancia de tener bien definidas las relaciones entre los diferentes proveedores, con el fin de producir una buena interacción entre los componentes del sistema.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Para terminar, simplemente quiero recalcar que &lt;span style="font-weight:bold;"&gt;Lean&lt;/span&gt; define los principios a aplicar en un desarrollo de software, pero no la forma concreta de aplicarlos. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://najaraba.blogspot.com/2008/02/desarrollo-software-lean.html"&gt;Desarrollo software Lean&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Lean_Manufacturing"&gt;Lean Manufacturing&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Lean_Software_Development"&gt;Lean software development&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-986505564920911145?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/986505564920911145/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/lean.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/986505564920911145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/986505564920911145'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/lean.html' title='Lean'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-379758215721443260</id><published>2010-02-23T15:49:00.006+01:00</published><updated>2011-10-26T09:42:53.153+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Prototype</title><content type='html'>El &lt;span style="font-weight:bold;"&gt;patrón Prototype&lt;/span&gt; es un &lt;span style="font-weight:bold;"&gt;patrón de diseño creacional&lt;/span&gt; en el que los objetos se crean a partir de una instancia prototípica, que es clonada para dar lugar a nuevos objetos.&lt;br /&gt;&lt;br /&gt;Este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; se usa en los siguientes casos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Para evitar las subclases de un objeto creador como hace el patrón Abstract Factory.&lt;/li&gt;&lt;li&gt;Para evitar el costo inherente a la creación de un objeto nuevo mediante el operador new cuando esto demasiado costoso para la aplicación.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Para implementar este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt;, se declara una clase base abstracta que tiene un método &lt;span style="font-style:italic;"&gt;clone()&lt;/span&gt;. Cualquier clase que necesite un constructor deriva de la clase abstracta e implementa el método &lt;span style="font-style:italic;"&gt;clone()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;El cliente, en vez de escribir codigo que hace uso del operador &lt;span style="font-style:italic;"&gt;new&lt;/span&gt; sobre una clase específica, llama al método &lt;span style="font-style:italic;"&gt;clone()&lt;/span&gt; de la clase prototipo, o llama a un método factoría con un parámetro que especifica la clase deseada, o invoca el método &lt;span style="font-style:italic;"&gt;clone()&lt;/span&gt; de la clase de alguna otra forma.&lt;br /&gt;&lt;br /&gt;El &lt;a href="http://es.wikipedia.org/wiki/Archivo:Prototype_UML.svg"&gt;siguiente diagrama UML&lt;/a&gt; representa este patrón:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/S4PraRGKmdI/AAAAAAAAK6o/bqcUeFoCySM/s1600-h/Prototype_UML.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 127px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/S4PraRGKmdI/AAAAAAAAK6o/bqcUeFoCySM/s320/Prototype_UML.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5441451611292080594" /&gt;&lt;/a&gt;&lt;br /&gt;Un ejemplo en Java de este patrón es el siguiente, sacado de la &lt;a href="http://en.wikipedia.org/wiki/Prototype_pattern"&gt;Wikipedia&lt;/a&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;/** Prototype Class */&lt;br /&gt;abstract class PrototypeFactory implements Cloneable {&lt;br /&gt; public PrototypeFactory clone() throws CloneNotSupportedException {&lt;br /&gt; // call Object.clone()&lt;br /&gt; PrototypeFactory copy = (PrototypeFactory) super.clone();&lt;br /&gt; //In an actual implementation of this pattern you might &lt;br /&gt; //now change references to&lt;br /&gt; //the expensive to produce parts from the copies &lt;br /&gt; //that are held inside the prototype.&lt;br /&gt; return copy;&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;abstract void prototypeFactory(int x);&lt;br /&gt; abstract void printValue();&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;/** Concrete Prototypes to clone */&lt;br /&gt;class PrototypeImpl extends PrototypeFactory {&lt;br /&gt; int x;&lt;br /&gt; &lt;br /&gt; public PrototypeImpl(int x) {&lt;br /&gt;  this.x = x;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Override&lt;br /&gt; void prototypeFactory(int x) {&lt;br /&gt;  this.x = x;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void printValue() {&lt;br /&gt;  System.out.println("Value :" + x);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;/** Client Class */&lt;br /&gt;public class PrototypeExample {&lt;br /&gt; private PrototypeFactory example; &lt;br /&gt; // Could have been a private Cloneable example.&lt;br /&gt; &lt;br /&gt; public PrototypeExample(PrototypeFactory example) {&lt;br /&gt;  this.example = example;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public PrototypeFactory makeCopy() throws CloneNotSupportedException {&lt;br /&gt;  return this.example.clone();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static void main(String args[]) {&lt;br /&gt;  try {&lt;br /&gt;   PrototypeFactory tempExample = null;&lt;br /&gt;   int num = 1000;&lt;br /&gt;   PrototypeFactory prot = new PrototypeImpl(1000);&lt;br /&gt;   PrototypeExample cm = new PrototypeExample(prot);&lt;br /&gt;   for (int i = 0; i &lt; 10; i++) {&lt;br /&gt;    tempExample = cm.makeCopy();&lt;br /&gt;    tempExample.prototypeFactory(i * num);&lt;br /&gt;    tempExample.printValue();&lt;br /&gt;   }&lt;br /&gt;  } catch (CloneNotSupportedException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;También se puede combinar el uso del &lt;span style="font-weight:bold;"&gt;patrón Prototype&lt;/span&gt; con el de &lt;span style="font-weight:bold;"&gt;Factory Method&lt;/span&gt;, como en el siguiente ejemplo, también extraído de la &lt;a href="http://es.wikipedia.org/wiki/Prototype_%28patr%C3%B3n_de_dise%C3%B1o%29"&gt;Wikipedia&lt;/a&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;// Los productos deben implementar esta interface&lt;br /&gt;public interface Producto extends Cloneable {&lt;br /&gt; Object clone();&lt;br /&gt; // Aqui van todas las operaciones comunes a los productos que genera la factoria&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;// Un ejemplo basico de producto&lt;br /&gt;public class UnProducto implements Producto {&lt;br /&gt; private int atributo;&lt;br /&gt; &lt;br /&gt; UnProducto(int atributo) {&lt;br /&gt;  this.atributo = atributo;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Object clone() {&lt;br /&gt;  return new UnProducto(this.atributo);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public String toString() {&lt;br /&gt;  return ((Integer)atributo).toString();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;// La clase encargada de generar objetos a partir de los prototipos&lt;br /&gt;public class FactoriaPrototipo {&lt;br /&gt; private HashMap mapaObjetos;&lt;br /&gt; private String nombrePorDefecto;&lt;br /&gt; &lt;br /&gt; public FactoriaPrototipo() {&lt;br /&gt;  mapaObjetos = new HashMap();&lt;br /&gt;  // Se incluyen al mapa todos los productos prototipo&lt;br /&gt;  mapaObjetos.put("producto 1", new UnProducto(1));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Object create() {&lt;br /&gt;  return create(nombrePorDefecto);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Object create(String nombre) {&lt;br /&gt;  nombrePorDefecto = nombre;&lt;br /&gt;  UnProducto objeto = (UnProducto)mapaObjetos.get(nombre);&lt;br /&gt;  return objeto != null ? objeto.clone() : null;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;public class PruebaFactoria {&lt;br /&gt; static public void main(String[] args) {&lt;br /&gt;  FactoriaPrototipo factoria = new FactoriaPrototipo();&lt;br /&gt;  Producto producto = (Producto) factoria.create("producto 1");&lt;br /&gt;  System.out.println ("Este es el objeto creado: " + producto);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Prototype_%28patr%C3%B3n_de_dise%C3%B1o%29"&gt;Prototype (patrón de diseño)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Prototype_pattern"&gt;Prototype pattern&lt;/a&gt;&lt;br /&gt;&lt;a href="http://software.guisho.com/prototype-pattern-patron-prototipo-patrones-de-diseno"&gt;Prototype Pattern – Patron Prototipo — Patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.design-nation.net/es/archivos/001904.php"&gt;Un ejemplo del Patrón Prototype ( la versión Java )&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.developer.com/java/other/article.php/626041/Pattern-Summaries-Prototype.htm"&gt;Pattern Summaries: Prototype&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.apwebco.com/gofpatterns/creational/Prototype.html"&gt;Prototype Design Pattern, UML diagram, Java Example&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-379758215721443260?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/379758215721443260/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-prototype.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/379758215721443260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/379758215721443260'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-prototype.html' title='Patrones de diseño: Prototype'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_WQMxntNMWT0/S4PraRGKmdI/AAAAAAAAK6o/bqcUeFoCySM/s72-c/Prototype_UML.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-5542207921419719659</id><published>2010-02-11T21:06:00.009+01:00</published><updated>2010-06-04T14:04:41.149+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apache Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='Calidad'/><title type='text'>Sonar: Métricas de calidad del código</title><content type='html'>Según su propia web, &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; es una plataforma que permite gestionar la calidad del código controlando los 7 ejes principales de dicha calidad del código:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Arquitectura y diseño&lt;/li&gt;&lt;li&gt;Duplicaciones&lt;/li&gt;&lt;li&gt;Pruebas unitarias&lt;/li&gt;&lt;li&gt;Complejidad&lt;/li&gt;&lt;li&gt;Errores potenciales&lt;/li&gt;&lt;li&gt;Reglas de codificación&lt;/li&gt;&lt;li&gt;Comentarios&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; realiza varios análisis de nuestro código a través de &lt;a href="http://tratandodeentenderlo.blogspot.com/2009/10/herramientas-de-analisis-de-calidad-del.html"&gt;otras herramientas (Checkstyle, PMD, Cobertura…)&lt;/a&gt; y presenta de manera unificada a través de su interfaz la información generada por ellas en forma de métricas.&lt;br /&gt;&lt;br /&gt;A través de la interfaz de &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; podemos ver de forma detallada los puntos débiles de nuestro proyecto como errores potenciales en el código, escasez de comentarios, clases demasiado complejas, escasez de cobertura de las pruebas unitarias, y más.&lt;br /&gt;&lt;br /&gt;Lo mejor es ilustrar la potencia de esta herramienta con un ejemplo de su uso, para lo cual vamos instalarla en nuestro equipo en primer lugar desde la &lt;a href="http://sonar.codehaus.org/downloads"&gt;página web del proyecto Sonar&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Descargamos la versión actual, que en este momento es la &lt;span style="font-weight:bold;"&gt;1.12&lt;/span&gt;. Una vez que hemos descargado &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt;, tenemos un archivo .zip que podemos descomprimir en cualquier lugar, yo lo haré en la carpeta &lt;span style="font-style:italic;"&gt;D:\java&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;Por sencillez, para las pruebas vamos a lanzar el servidor de &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; en modo &lt;span style="font-style:italic;"&gt;standalone&lt;/span&gt;, aunque lo ideal sería instalarlo en un servidor de aplicaciones. Desde la línea de comandos vamos a la carpeta &lt;span style="font-style:italic;"&gt;D:\java\sonar-1.12\bin\windows-x86-32&lt;/span&gt; (estoy haciendo la prueba en Windows) y ejecutamos &lt;span style="font-style:italic;"&gt;StartSonar.bat&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/S3RkKwCGPkI/AAAAAAAAK5U/TzX50lAEijE/s1600-h/img1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 82px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/S3RkKwCGPkI/AAAAAAAAK5U/TzX50lAEijE/s320/img1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5437080785998200386" /&gt;&lt;/a&gt;&lt;br /&gt;Esto lanzará el servidor de &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt;, al que podremos acceder desde la URL &lt;a href="http://localhost:9000/"&gt;http://localhost:9000/&lt;/a&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/S3RkT293-7I/AAAAAAAAK5c/ix3iVm1Mks4/s1600-h/img2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 230px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/S3RkT293-7I/AAAAAAAAK5c/ix3iVm1Mks4/s320/img2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5437080942478359474" /&gt;&lt;/a&gt;&lt;br /&gt;Como acabamos de instalar &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt;, la interfaz aparecerá prácticamente vacía hasta que empecemos a analizar nuestros proyectos. Para ello iremos a uno de nuestros proyectos, gestionados con &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;, y le pediremos a &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; que lo analice mediante el target de &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; &lt;span style="font-style:italic;"&gt;mvn sonar:sonar&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/S3Rkk91kiJI/AAAAAAAAK5k/8sf5MtnIK00/s1600-h/img3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 162px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/S3Rkk91kiJI/AAAAAAAAK5k/8sf5MtnIK00/s320/img3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5437081236380354706" /&gt;&lt;/a&gt;&lt;br /&gt;Si ahora refrescamos la interfaz de &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt;, veremos que aparece el nuevo proyecto analizado:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/S3Rkr-pMkaI/AAAAAAAAK5s/ESt3LkeHRN8/s1600-h/img4.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 230px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/S3Rkr-pMkaI/AAAAAAAAK5s/ESt3LkeHRN8/s320/img4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5437081356855972258" /&gt;&lt;/a&gt;&lt;br /&gt;Además ya nos va mostrando información sobre el proyecto, como el porcentaje de cumplimiento de las reglas de análisis o el porcentaje de cobertura de las pruebas unitarias. Pero, si queremos más información, no tenemos más que pinchar sobre nuestro proyecto para ir a la siguiente pantalla:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/S3Rkyhg9c4I/AAAAAAAAK50/kjA9pRHqaNc/s1600-h/img5.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 230px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/S3Rkyhg9c4I/AAAAAAAAK50/kjA9pRHqaNc/s320/img5.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5437081469295883138" /&gt;&lt;/a&gt;&lt;br /&gt;Aquí se empieza a ver la potencia de &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt;. En una interfaz compacta nos muestra una cantidad importante de información sobre el código del proyecto como:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;medida en líneas de código&lt;/li&gt;&lt;li&gt;complejidad de los componentes&lt;/li&gt;&lt;li&gt;cantidad de comentarios introducidos&lt;/li&gt;&lt;li&gt;duplicidad del código&lt;/li&gt;&lt;li&gt;cobertura del código&lt;/li&gt;&lt;li&gt;conformidad respecto a ciertas reglas de codificación&lt;/li&gt;&lt;li&gt;violaciones del código&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Para ampliar la información, podemos, por ejemplo, acceder a las violaciones tipo &lt;span style="font-style:italic;"&gt;major&lt;/span&gt; de las reglas de codificación:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/S3RlRfCs-kI/AAAAAAAAK58/Zn3nJQoOmfs/s1600-h/img6.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 230px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/S3RlRfCs-kI/AAAAAAAAK58/Zn3nJQoOmfs/s320/img6.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5437082001208048194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; nos muestra información sobre las reglas que se están incumpliendo, y los paquetes y clases en que esto ocurre. Y, si pinchamos sobre una de las clases &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; muestra cuál es el código que está incumpliendo estas reglas y da indicaciones para corregirlo:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/S3RlxIBneTI/AAAAAAAAK6E/bUpFNAlP8Os/s1600-h/img7.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 230px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/S3RlxIBneTI/AAAAAAAAK6E/bUpFNAlP8Os/s320/img7.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5437082544785291570" /&gt;&lt;/a&gt; &lt;br /&gt;A mí &lt;span style="font-weight:bold;"&gt;Sonar&lt;/span&gt; me ha parecido una maravilla, y no he hecho más que empezar a ver sus posibilidades. Os invito a que utilicéis esta herramienta y exploréis su interfaz en busca de toda la información que ofrece sobre el código del proyecto.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://"&gt;Página web del proyecto Sonar&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.chuidiang.com/2009/01/27/metricas-en-java-sonar/"&gt;Métricas en Java: Sonar&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=UtilizandoSonar"&gt;Analizando la calidad del código Java con Sonar&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-5542207921419719659?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/5542207921419719659/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/sonar-metricas-de-calidad-del-codigo.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5542207921419719659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5542207921419719659'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/sonar-metricas-de-calidad-del-codigo.html' title='Sonar: Métricas de calidad del código'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_WQMxntNMWT0/S3RkKwCGPkI/AAAAAAAAK5U/TzX50lAEijE/s72-c/img1.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-6722673478952077224</id><published>2010-02-09T18:13:00.005+01:00</published><updated>2011-10-26T09:43:09.440+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Builder</title><content type='html'>El &lt;span style="font-weight:bold;"&gt;patrón Builder&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;Constructor&lt;/span&gt; es otro de los &lt;span style="font-weight:bold;"&gt;patrones creacionales&lt;/span&gt;. Este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; permite separar la construcción de un objeto complejo de su representación, de modo que el mismo proceso de construcción pueda crear diferentes representaciones de este objeto.&lt;br /&gt;&lt;br /&gt;La siguiente imagen muestra el diagrama de clases de este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_WQMxntNMWT0/S3GYtOFnxlI/AAAAAAAAK5M/--487QspOnc/s1600-h/Builder2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 144px;" src="http://3.bp.blogspot.com/_WQMxntNMWT0/S3GYtOFnxlI/AAAAAAAAK5M/--487QspOnc/s320/Builder2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5436294127856109138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Builder&lt;/span&gt;: interfaz abstracta para crear productos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Concrete Builder&lt;/span&gt;: implementación del &lt;span style="font-weight:bold;"&gt;Builder&lt;/span&gt;, construye y reúne las partes necesarias para construir los productos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Director&lt;/span&gt;: construye un objeto usando el patrón &lt;span style="font-weight:bold;"&gt;Builder&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Producto&lt;/span&gt;: El objeto complejo bajo construcción.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A continuación se muestra un ejemplo de este patrón, extraído de la &lt;a href="http://en.wikipedia.org/wiki/Builder_pattern"&gt;Wikipedia&lt;/a&gt;. En este ejemplo tenemos un cocina (&lt;span style="font-style:italic;"&gt;Director&lt;/span&gt;) que produce pizzas (&lt;span style="font-style:italic;"&gt;Producto&lt;/span&gt;) de con diferentes características (&lt;span style="font-style:italic;"&gt;Concrete Builder&lt;/span&gt;):&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint java"&gt;/** "Product" */&lt;br /&gt;class Pizza {&lt;br /&gt; private String dough = "";&lt;br /&gt; private String sauce = "";&lt;br /&gt; private String topping = "";&lt;br /&gt; &lt;br /&gt; public void setDough(String dough) {&lt;br /&gt;  this.dough = dough;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setSauce(String sauce) {&lt;br /&gt;  this.sauce = sauce;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setTopping(String topping) {&lt;br /&gt;  this.topping = topping;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;/** "Abstract Builder" */&lt;br /&gt;abstract class PizzaBuilder {&lt;br /&gt; protected Pizza pizza;&lt;br /&gt; &lt;br /&gt; public Pizza getPizza() {&lt;br /&gt;  return pizza;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void createNewPizzaProduct() {&lt;br /&gt;  pizza = new Pizza();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public abstract void buildDough();&lt;br /&gt; &lt;br /&gt; public abstract void buildSauce();&lt;br /&gt; &lt;br /&gt; public abstract void buildTopping();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/** "ConcreteBuilder" */&lt;br /&gt;class HawaiianPizzaBuilder extends PizzaBuilder {&lt;br /&gt; public void buildDough() {&lt;br /&gt;  pizza.setDough("cross");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void buildSauce() {&lt;br /&gt;  pizza.setSauce("mild");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void buildTopping() {&lt;br /&gt;  pizza.setTopping("ham+pineapple");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;/** "ConcreteBuilder" */&lt;br /&gt;class SpicyPizzaBuilder extends PizzaBuilder {&lt;br /&gt; public void buildDough() {&lt;br /&gt;  pizza.setDough("pan baked");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void buildSauce() {&lt;br /&gt;  pizza.setSauce("hot");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void buildTopping() {&lt;br /&gt;  pizza.setTopping("pepperoni+salami");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/** "Director" */&lt;br /&gt;class Cook {&lt;br /&gt; private PizzaBuilder pizzaBuilder;&lt;br /&gt;  &lt;br /&gt; public void setPizzaBuilder(PizzaBuilder pb) {&lt;br /&gt;  pizzaBuilder = pb;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public Pizza getPizza() {&lt;br /&gt;  return pizzaBuilder.getPizza();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void constructPizza() {&lt;br /&gt;  pizzaBuilder.createNewPizzaProduct();&lt;br /&gt;  pizzaBuilder.buildDough();&lt;br /&gt;  pizzaBuilder.buildSauce();&lt;br /&gt;  pizzaBuilder.buildTopping();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;/** A given type of pizza being constructed. */&lt;br /&gt;public class BuilderExample {&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  Cook cook = new Cook();&lt;br /&gt;  &lt;br /&gt;  PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();&lt;br /&gt;  PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();&lt;br /&gt;  &lt;br /&gt;  cook.setPizzaBuilder(hawaiianPizzaBuilder);&lt;br /&gt;  cook.constructPizza();&lt;br /&gt; &lt;br /&gt;  Pizza pizza = cook.getPizza();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Hay quién confunde el &lt;span style="font-weight:bold;"&gt;patrón Builder&lt;/span&gt; con &lt;span style="font-weight:bold;"&gt;Factory&lt;/span&gt;, pero la diferencia es que, mientras el &lt;span style="font-weight:bold;"&gt;patrón Factory&lt;/span&gt; difiere la elección de la clase concreta de un objeto, el &lt;span style="font-weight:bold;"&gt;patrón Builder&lt;/span&gt; simplemente oculta la lógica de creación de un objeto complejo. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Builder_pattern"&gt;Patrón Builder en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://agamenon.uniandes.edu.co/~pfiguero/soo/PatronesDiseno/Builder/Builder.html"&gt;Builder&lt;/a&gt;&lt;br /&gt;&lt;a href="http://software.guisho.com/builder-pattern-interfaces-fluidas-patrones-de-diseno"&gt;Builder Pattern, Interfaces Fluidas– Patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;a href="http://java.dzone.com/news/design-pattern-builder-pattern"&gt;Intro to Design Patterns: Builder Pattern&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.allapplabs.com/java_design_patterns/builder_pattern.htm"&gt;Creational Patterns - Builder Pattern&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.javadesign.info/DesignConcepts/DesignPatterns/GOF/builder_pattern"&gt;Design Pattern - Builder Pattern&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-6722673478952077224?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/6722673478952077224/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-builder.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6722673478952077224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6722673478952077224'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-builder.html' title='Patrones de diseño: Builder'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_WQMxntNMWT0/S3GYtOFnxlI/AAAAAAAAK5M/--487QspOnc/s72-c/Builder2.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-1872065231096432662</id><published>2010-02-02T18:08:00.007+01:00</published><updated>2011-10-26T09:43:23.347+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Factorías</title><content type='html'>Una &lt;span style="font-weight:bold;"&gt;factoría&lt;/span&gt; es un objeto que maneja la creación de otros objetos. Las &lt;span style="font-weight:bold;"&gt;factorías&lt;/span&gt; se utilizan cuando la creación de un objeto implica algo más que una simple instanciación.&lt;br /&gt;Los siguientes ejemplos son casos donde una factoría puede ayudar:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Es necesario acceder a algún recurso para la creación y configuración de un objeto.&lt;/li&gt;&lt;li&gt;No conocemos hasta el momento preciso de la instanciación qué tipo concreto de objeto se va a instanciar.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;En estos casos, en lugar de que sea el propio objeto quien se encargue de todos los aspectos realativos a la creación, se crea otro objeto que lo haga. De esta manera, se libera al objeto que va a ser creado de aquellas responsabilidades que no le corresponden pero que son necesarias para su creación, manteniendo su independencia.&lt;br /&gt;&lt;br /&gt;El siguiente es un ejemplo de la utilización de una &lt;span style="font-weight:bold;"&gt;factoría&lt;/span&gt; para la creación de objetos. Se pueden crear figuras geométricas y calcular su área. Las figuras estarían definidas por una interfaz. Las figuras posibles son círculos y cuadrados.&lt;br /&gt;&lt;br /&gt;Se va a utilizar una &lt;span style="font-weight:bold;"&gt;factoría&lt;/span&gt; para crear las figuras, puesto que no conocemos de antemano a qué clase pertenece el objetoque tenemos que instanciar. El uso de una &lt;span style="font-weight:bold;"&gt;factoría&lt;/span&gt; permite separar la lógica de negocio, igual para todos los casos, de la lógica de instanciación de los objetos. De este forma el código queda más claro.&lt;br /&gt;&lt;pre class="prettyprint java"&gt;public interface Figura {&lt;br /&gt; public double getArea();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Circulo implements Figura {&lt;br /&gt; double radio;&lt;br /&gt; &lt;br /&gt; public Circulo(double radio) {&lt;br /&gt;  this.radio = radio;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public double getArea() {&lt;br /&gt;  return (3.14 * radio * radio);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Cuadrado implements Figura {&lt;br /&gt; double lado;&lt;br /&gt; &lt;br /&gt; public Cuadrado(double lado) {&lt;br /&gt;  this.lado = lado;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public double getArea() {&lt;br /&gt;  return lado * lado;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Principal {&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  int tipo = Integer.parseInt(args[0]);&lt;br /&gt;  double lado = Double.parseDouble(args[0]);  &lt;br /&gt; &lt;br /&gt;  Figura figura = &lt;br /&gt;   FiguraFactory.getFigura(tipo, lado);&lt;br /&gt;&lt;br /&gt;  System.out.println("El area de la figura es: " + figura.getArea());&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class FiguraFactory {&lt;br /&gt; public final static int CUADRADO = 0;&lt;br /&gt; public final static int CIRCULO = 1;&lt;br /&gt; &lt;br /&gt; public static Figura getFigura(int tipo, double lado) {&lt;br /&gt;  switch (tipo) {&lt;br /&gt;   case CUADRADO:&lt;br /&gt;    return new Cuadrado(lado);&lt;br /&gt;   case CIRCULO:&lt;br /&gt;    return new Circulo(lado);&lt;br /&gt;  }  &lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;El ejemplo anterior se corresponde con el &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; de diseño &lt;span style="font-weight:bold;"&gt;Factory Metho&lt;/span&gt;d, que se refiere a la utiliación de un método cuyo propósito principal es la creación de objetos.&lt;br /&gt;&lt;br /&gt;Existe otro patrón de diseño denominado &lt;span style="font-weight:bold;"&gt;Abstract Factory&lt;/span&gt;, que proporciona una interfaz para crear familias de objetos que dependen entre sí, sin especificar sus clases concretas.&lt;br /&gt;&lt;br /&gt;El siguiente es un ejemplo de una &lt;span style="font-weight:bold;"&gt;factoría abstracta&lt;/span&gt; &lt;a href="http://en.wikipedia.org/wiki/Abstract_factory_pattern"&gt;sacado de la Wikipedia&lt;/a&gt;, en el que se crea un botón que puede pertenecer a dos familias distintas de componentes gráficos y la aplicación no sabe hasta el momento de la ejecución a qué familia pertenecerá este botón:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint java"&gt;&lt;br /&gt;interface GUIFactory {&lt;br /&gt; public Button createButton();&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;class WinFactory implements GUIFactory {&lt;br /&gt; public Button createButton() {&lt;br /&gt;  return new WinButton();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;class OSXFactory implements GUIFactory {&lt;br /&gt; public Button createButton() {&lt;br /&gt;  return new OSXButton();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;interface Button {&lt;br /&gt; public void paint();&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;class WinButton implements Button {&lt;br /&gt; public void paint() {&lt;br /&gt;  System.out.println("I'm a WinButton");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;class OSXButton implements Button {&lt;br /&gt; public void paint() {&lt;br /&gt;  System.out.println("I'm an OSXButton");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;class Application {&lt;br /&gt; public Application(GUIFactory factory){&lt;br /&gt;  Button button = factory.createButton();&lt;br /&gt;  button.paint();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;public class ApplicationRunner {&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  new Application(createOsSpecificFactory());&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static GUIFactory createOsSpecificFactory() {&lt;br /&gt;  int sys = readFromConfigFile("OS_TYPE");&lt;br /&gt;  if (sys == 0) {&lt;br /&gt;   return new WinFactory();&lt;br /&gt;  } else {&lt;br /&gt;   return new OSXFactory();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Factory_object"&gt;Objeto Factoría en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Factory_pattern"&gt;Patrón Factoría en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Factory_method_pattern"&gt;Patrón Factory Method en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://software.guisho.com/patrones-de-diseno-factory-pattern"&gt;Factory Pattern - Patrones&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Abstract_factory_pattern"&gt;Patrón Abstract Factory en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://software.guisho.com/patrones-de-diseno-factory-pattern"&gt;Abstract Factory Pattern - Patrones&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-1872065231096432662?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/1872065231096432662/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-factorias.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1872065231096432662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1872065231096432662'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-factorias.html' title='Patrones de diseño: Factorías'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-3600737954133010677</id><published>2010-01-26T18:27:00.011+01:00</published><updated>2011-10-26T09:43:33.263+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño: Singleton</title><content type='html'>En este artículo vamos a ver uno de los &lt;span style="font-weight:bold;"&gt;patrones creacionales&lt;/span&gt; más comunes, el &lt;span style="font-weight:bold;"&gt;Singleton&lt;/span&gt;. Este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; garantiza que una clase sólo tenga una instancia, y proporciona un punto de acceso global a ella.&lt;br /&gt;&lt;br /&gt;Este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; se suele utilizar cuando una clase controla el acceso a un recurso físico único o cuando hay datos  que deben estar disponibles para todos los objetos de la aplicación.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;El patrón Singleton&lt;/span&gt; se implementa mediante una clase con un constructor privado. Existirá un método que creará una instancia del objeto llamando al constructor sólo si todavía no existe ninguna.&lt;br /&gt;&lt;br /&gt;Se pueden producir problemas en programas con múltiples hilos de ejecución, si dos hilos de ejecución intentan crear la instancia al mismo tiempo y ésta no existe todavía. Para que sólo uno de ellos pueda crear el objeto se puede utilizar exclusión mutua (&lt;span style="font-style:italic;"&gt;synchronized&lt;/span&gt;) en el método de creación de la clase que implementa el &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Habría que decir también que si existen varios cargadores de clases para la aplicación puede existir una instancia de la clase en cada uno de ellos, aunque la instancia sea única dentro de ese cargador.&lt;br /&gt;&lt;br /&gt;Una implementación correcta del &lt;span style="font-weight:bold;"&gt;patrón Singleton&lt;/span&gt; en &lt;span style="font-weight:bold;"&gt;Java&lt;/span&gt; podría ser la siguiente, propuesta por el investigador Bill Pough:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;public class Singleton {&lt;br /&gt; // Private constructor prevents instantiation from other classes&lt;br /&gt; private Singleton() {}&lt;br /&gt; &lt;br /&gt; /**&lt;br /&gt;  * SingletonHolder is loaded on the first execution of &lt;br /&gt;  * Singleton.getInstance() or the first access to &lt;br /&gt;  * SingletonHolder.INSTANCE, not before.&lt;br /&gt;  */&lt;br /&gt; private static class SingletonHolder { &lt;br /&gt;  private static final Singleton INSTANCE = new Singleton();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static Singleton getInstance() {&lt;br /&gt;  return SingletonHolder.INSTANCE;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;A pesar de que es ampliamente utilizado, existe una corriente contraria al uso de este &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; debido a los problemas que introduce. En &lt;a href="http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx"&gt;esta página&lt;/a&gt; Scout Densmore expone los problemas que Brian Button achaca a los &lt;span style="font-weight:bold;"&gt;Singletons&lt;/span&gt;. A continuación, hago una adaptación de lo ahí se dice:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Los Singletons normalmente se usan para proporcionar un punto de acceso global para un servicio.&lt;/span&gt; De esta forma no hace falta pasar una referencia a este servicio, lo que viene a ser como usar una variable global. Al final lo que ocurre es que las dependencias de diseño permanecen ocultas dentro del código y no son visibles al examinar las interfaces. Hace falta inspeccionar el código para entender qué objetos están usando las clases.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Los Singletons permiten limitar la creación de los objetos.&lt;/span&gt; Esto es cierto, pero ahora se están mezclando dos responsabilidades diferentes en la misma clase. Una clase no debería preocuparse de si es o no un Singleton, sino que sólo debería preocuparse por sus responsabilidades de negocio. Para limitar la creación de clases se deberían crear factorías u otros objetos que limiten la creación. De esta forma, cada objeto mantendría una responsabilidad mejor definida.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Los Singletons promueven el acoplamiento fuerte entre clases&lt;/span&gt;. Un acoplamiento flojo entre clases permite sustituir implementaciones alternativas de las clases colaboradoras en las pruebas. Una mejor alternativa es modificar el diseño para pasar referencias a los objetos en las clases y métodos, de forma que se reduzca el acoplamiento.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Los Singletons mantienen el estado hasta la finalización del programa.&lt;/span&gt; Este estado persistente es perjudicial para las pruebas unitarias, puesto que cada prueba debe ser independiente de las demás. Si esto no se cumple, podría llevar a situaciones donde las pruebas fallen donde no deben y a que se estén ocultando errores. Esto se puede evitar pasando referencias a objetos a las clases y métodos.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Es por ello que parece un &lt;span style="font-weight:bold;"&gt;patrón de diseño&lt;/span&gt; a evitar dentro de lo posible.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Singleton"&gt;Patrón Singleton en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://software.guisho.com/singleton-pattern-patrones-de-diseno"&gt;Singleton Pattern — Patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.elrincondelprogramador.com/default.asp?id=45&amp;pag=articulos%2Fleer.asp"&gt;Singletons en Java, el patrón instancia única por David Barral&lt;/a&gt;&lt;br /&gt;&lt;a href="http://c2.com/cgi/wiki?SingletonPattern"&gt;Patrón Singleton en c2.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx)"&gt;Why Singletons are Evil por Scott Densmore&lt;/a&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html"&gt;Otros patrones de diseño&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-3600737954133010677?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/3600737954133010677/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno-singleton.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3600737954133010677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3600737954133010677'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno-singleton.html' title='Patrones de diseño: Singleton'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-3164266148332990033</id><published>2010-01-24T10:06:00.007+01:00</published><updated>2010-06-08T10:00:08.565+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apache Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='Pruebas'/><title type='text'>Pruebas funcionales con Selenium</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Selenium HQ&lt;/span&gt; es un framework que permite automatizar las pruebas funcionales sobre aplicaciones web. Está formado por varias herramientas que permiten definir estas pruebas y automatizarlas. En concreto, vamos a ver:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Selenium IDE&lt;/span&gt;: Se trata de un plugin de Firefox que permite definir una prueba de una aplicación web guardando en un script las acciones que ejecuta el usuario sobre el navegador. Este script puede volver a ejecutarse después todas las veces que se quiera.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Selenium RC (Remote Control)&lt;/span&gt;: Permite automatizar las pruebas sobre las aplicaciones web a partir de los scripts definidos mediante Selenium IDE.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Veremos a continuación un ejemplo de prueba funcional de una aplicación web.&lt;br /&gt;&lt;br /&gt;En primer lugar debemos descarganos el plugin de Firefox para &lt;span style="font-weight:bold;"&gt;Selenium IDE&lt;/span&gt;. Podemos hacerlo desde &lt;a href="http://release.openqa.org/selenium-ide/1.0.4/selenium-ide-1.0.4.xpi"&gt;esta página&lt;/a&gt;. Esto descargará el plugin de &lt;span style="font-weight:bold;"&gt;Selenium IDE&lt;/span&gt; y lo instalará en el navegador. A continuación lo reiniciaremos para completar la instalación.&lt;br /&gt;&lt;br /&gt;Ahora vamos a hacer una prueba de una aplicación web. En este caso se trata de una aplicación que guarda todos los artículos de interés de las revistas que voy comprando, y la prueba consistirá en introducir un nuevo artículo.&lt;br /&gt;&lt;br /&gt;En primer lugar, vamos a &lt;span style="font-style:italic;"&gt;Herramientas-&gt;Selenium IDE&lt;/span&gt;. Esto abre una ventana que permite grabar el script con la prueba a realizar:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/S1wPP8b-E4I/AAAAAAAAK4k/bAOJ9CwS7qs/s1600-h/Consola.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 246px; height: 320px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/S1wPP8b-E4I/AAAAAAAAK4k/bAOJ9CwS7qs/s320/Consola.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5430232017297871746" /&gt;&lt;/a&gt;&lt;br /&gt;A partir de este momento todo lo que hagamos sobre el navegador se registrará en el script. En este momento se introducirá un nuevo artículo de nombre “&lt;span style="font-style:italic;"&gt;Nuevo&lt;/span&gt;” y título “&lt;span style="font-style:italic;"&gt;Nuevo&lt;/span&gt;”. Una vez introducido, se pulsa sobre el botón rojo de la ventana de &lt;span style="font-weight:bold;"&gt;Selenium IDE&lt;/span&gt; para que pare la grabación del script. Comprobamos que se ha introducido el artículo. &lt;br /&gt;&lt;br /&gt;Ahora repetimos la prueba pulsando sobre el triángulo verde situado arriba a la derecha de la ventana de &lt;span style="font-weight:bold;"&gt;Selenium IDE&lt;/span&gt;. Esto repite la ejecución anterior y por tanto, en el listado de artículos vemos que ahora existen 2 artículos de nombre “&lt;span style="font-style:italic;"&gt;Nuevo&lt;/span&gt;”.&lt;br /&gt;&lt;br /&gt;Podemos grabar esta prueba desde &lt;span style="font-style:italic;"&gt;Archivo-&gt;Save Test Cas&lt;/span&gt;e. Sin embargo para nosotros será más interesante la opción &lt;span style="font-style:italic;"&gt;Archivo-&gt;Export Test Case As -&gt;Java (JUnit) Selenium RC&lt;/span&gt; que exportará este script a un caso de prueba de &lt;span style="font-weight:bold;"&gt;JUnit&lt;/span&gt; que vamos a utilizar posteriormente para automatizar esta prueba:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.example.tests;&lt;br /&gt;&lt;br /&gt;import com.thoughtworks.selenium.*;&lt;br /&gt;import java.util.regex.Pattern;&lt;br /&gt;&lt;br /&gt;public class Prueba extends SeleneseTestCase {&lt;br /&gt; public void setUp() throws Exception {&lt;br /&gt;  setUp("http://change-this-to-the-site-you-are-testing/", "*chrome");&lt;br /&gt; }&lt;br /&gt; public void testPrueba() throws Exception {&lt;br /&gt;  selenium.open("/RevisteroMyFacesWeb/");&lt;br /&gt;  selenium.click("link=Nuevo Artículo");&lt;br /&gt;  selenium.waitForPageToLoad("30000");&lt;br /&gt;  selenium.type("j_id_jsp_815202587_1:nombreArticulo", "Nuevo");&lt;br /&gt;  selenium.type("j_id_jsp_815202587_1:descripcionArticulo", "Nuevo");&lt;br /&gt;  selenium.click("j_id_jsp_815202587_1:j_id_jsp_815202587_35");&lt;br /&gt;  selenium.waitForPageToLoad("30000");&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Una vez definida la prueba vamos ahora a automatizarla. Para ello usaremos &lt;span style="font-weight:bold;"&gt;JUnit&lt;/span&gt; y la herramienta &lt;span style="font-weight:bold;"&gt;Selenium RC (Remote Control)&lt;/span&gt;. También usaremos el plugin de &lt;span style="font-weight:bold;"&gt;Selenium&lt;/span&gt; para &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;, que permite arrancar el servidor de &lt;span style="font-weight:bold;"&gt;Selenium RC&lt;/span&gt; cuando se ejecutan las pruebas.&lt;br /&gt;&lt;br /&gt;Creamos un proyecto de &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; con el siguiente &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" &lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   &lt;br /&gt; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0&lt;br /&gt; http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;br /&gt; &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;com.roldan&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;RevisteroPruebasSelenium&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;  &lt;br /&gt; &amp;lt;dependencies&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;3.8.2&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;       &lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.seleniumhq.selenium.client-drivers&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;selenium-java-client-driver&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;1.0.1&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt; &amp;lt;/dependencies&amp;gt;  &lt;br /&gt; &amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;selenium-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;executions&amp;gt;&lt;br /&gt;     &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;process-test-classes&amp;lt;/phase&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;       &amp;lt;goal&amp;gt;start-server&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;       &amp;lt;background&amp;gt;true&amp;lt;/background&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;     &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;/executions&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt; &amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;/pre&gt; &lt;br /&gt;Vemos que además de configurar el plugin de &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; para &lt;span style="font-weight:bold;"&gt;Selenium&lt;/span&gt; para que arranque el servidor de &lt;span style="font-weight:bold;"&gt;Selenium&lt;/span&gt; en la fase anterior a la de test (&lt;span style="font-style:italic;"&gt;process-test-classe&lt;/span&gt;s), define dos dependencias, &lt;span style="font-weight:bold;"&gt;JUnit&lt;/span&gt; y el driver de cliente Java para &lt;span style="font-weight:bold;"&gt;Selenium&lt;/span&gt;, que permite ejecutar los tests creados desde &lt;span style="font-weight:bold;"&gt;Selenium IDE&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Vamos a adaptar la clase de test generada desde Selenium IDE para que haga uso del driver de Java para Selenium:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.selenium;&lt;br /&gt;&lt;br /&gt;import com.thoughtworks.selenium.*;&lt;br /&gt;&lt;br /&gt;public class CrearNuevoArticuloTest extends SeleneseTestCase {&lt;br /&gt; &lt;br /&gt; protected DefaultSelenium createSeleniumClient(String url) throws Exception {&lt;br /&gt;  return new DefaultSelenium("localhost", 4444, "*firefox", url);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void testCrearNuevoArticulo() throws Exception {&lt;br /&gt;  DefaultSelenium selenium = createSeleniumClient("http://localhost:8080/");&lt;br /&gt;   selenium.start(); &lt;br /&gt;  &lt;br /&gt;  selenium.open("/RevisteroMyFacesWeb/");&lt;br /&gt;  selenium.click("link=Nuevo Artículo");&lt;br /&gt;  selenium.waitForPageToLoad("30000");&lt;br /&gt;  selenium.type("j_id_jsp_815202587_1:nombreArticulo", "Nuevo");&lt;br /&gt;  selenium.type("j_id_jsp_815202587_1:descripcionArticulo", "Nuevo");&lt;br /&gt;  selenium.click("j_id_jsp_815202587_1:j_id_jsp_815202587_35");&lt;br /&gt;  selenium.waitForPageToLoad("30000");&lt;br /&gt;  &lt;br /&gt;  selenium.stop();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;La diferencia está en que ahora al comienzo de la prueba se crea un cliente de &lt;span style="font-weight:bold;"&gt;Selenium&lt;/span&gt; y al final de la prueba se cierra este cliente.&lt;br /&gt;&lt;br /&gt;Si ahora se lanzan los test para este proyecto con &lt;span style="font-style:italic;"&gt;mvn test&lt;/span&gt;, se verá aparecer un navegador que repite la prueba definida, y se habrá grabado otro artículo más.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://seleniumhq.org/"&gt;Web de Selenium HQ&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=seleniumIDE"&gt;Turorial de Adictos al trabajo sobre Selenium IDE&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=selenium_rc"&gt;Turorial de Adictos al trabajo sobre Selenium RC&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.dosideas.com/java/743-test-secuencial-con-selenium-y-junit.html"&gt;Tutorial de Dos Ideas sobre tests secuenciales con Selenium y JUnit&lt;/a&gt;&lt;br /&gt;&lt;a href=" http://mojo.codehaus.org/selenium-maven-plugin/"&gt;Web del plugin de Selenium para Maven&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-3164266148332990033?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/3164266148332990033/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/01/pruebas-funcionales-con-selenium.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3164266148332990033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3164266148332990033'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/01/pruebas-funcionales-con-selenium.html' title='Pruebas funcionales con Selenium'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_WQMxntNMWT0/S1wPP8b-E4I/AAAAAAAAK4k/bAOJ9CwS7qs/s72-c/Consola.bmp' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-4545896725355774403</id><published>2010-01-08T20:25:00.016+01:00</published><updated>2011-10-26T09:44:32.220+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patrones de diseño'/><title type='text'>Patrones de diseño</title><content type='html'>Cada vez que se comienza el desarrollo de una nueva aplicación, como ingenieros de software nos volvemos a enfrentar a los mismos o similares problemas que ya se han encarado en anteriores desarrollos. No sólo esto, nos estamos enfrentando en muchos casos a los mismo problemas que otros ya han tenido que resolver.&lt;br /&gt;&lt;br /&gt;Aprovechar todo el conocimiento anterior es útil y permite ganar tiempo en el diseño y desarrollo de nuevas aplicaciones. Esto es algo de sobra conocido y por ello han surgido los patrones de diseño, como pautas a seguir en determinadas condiciones avaladas por el conocimiento previo.&lt;br /&gt;&lt;br /&gt;En la construcción, el arquitecto Christopher Alexander propuso el aprendizaje y uso de una serie de &lt;span style="font-weight:bold;"&gt;patrones&lt;/span&gt; para la construcción de edificios de una mayor calidad. Según sus palabras, "&lt;span style="font-style:italic;"&gt;cada &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; describe un problema que ocurre infinidad de veces en nuestro entorno, así como la solución al mismo, de tal modo que podemos utilizar esta solución un millón de veces más adelante sin tener que volver a pensarla otra vez.&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;Los &lt;span style="font-weight:bold;"&gt;patrones&lt;/span&gt; que Christopher Alexander y sus colegas definieron son un intento de formalizar y plasmar de una forma práctica generaciones de conocimiento arquitectónico. Los &lt;span style="font-weight:bold;"&gt;patrones&lt;/span&gt; no son principios abstractos que requieran su redescubrimiento para obtener una aplicación satisfactoria, ni son específicos a una situación particular o cultural; son algo intermedio. Un &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; define una posible solución correcta para un problema de diseño dentro de un contexto dado, describiendo las cualidades invariantes de todas las soluciones.&lt;br /&gt;&lt;br /&gt;Llevando la idea de &lt;span style="font-weight:bold;"&gt;patrón&lt;/span&gt; al mundo de la informática, un &lt;span style="font-weight:bold;"&gt;patrón de diseño&lt;/span&gt; es una solución a un problema de diseño que debe poseer las siguientes características:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Debe haber comprobado su &lt;span style="font-weight:bold;"&gt;efectividad&lt;/span&gt; resolviendo problemas similares en ocasiones anteriores.&lt;/li&gt;&lt;li&gt;Debe ser &lt;span style="font-weight:bold;"&gt;reusable&lt;/span&gt;, lo que significa que es aplicable a diferentes problemas de diseño en distintas circunstancias.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Los &lt;span style="font-weight:bold;"&gt;patrones de diseño&lt;/span&gt; tuvieron un gran éxito a partir de la publicación del libro &lt;span style="font-weight:bold;"&gt;Design Patterns&lt;/span&gt; escrito por el grupo Gang of Four (GoF, en el que se recogían 23 patrones de diseño comunes. Estos &lt;span style="font-weight:bold;"&gt;patrones&lt;/span&gt; definidos por el GoF están divididos en 3 grupos, &lt;span style="font-weight:bold;"&gt;patrones creacionales, estructurales y de comportamiento&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Patrones creacionales&lt;/span&gt;: Tratan de solucionar los problemas que pueden surgir en la creación de objetos.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-factorias.html"&gt;Abstract Factory&lt;/a&gt;&lt;/span&gt;: Proporciona una interfaz para crear familias de objetos o que dependen entre sí, sin especificar sus clases concretas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-factorias.html"&gt;Factory Method&lt;/a&gt;&lt;/span&gt;: Define una interfaz para crear un objeto, pero deja que sean las subclases quienes decidan qué clase instanciar. Permite que una clase delegue en sus subclases la creación de objetos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-builder.html"&gt;Builder&lt;/a&gt;&lt;/span&gt;: Separa la construcción de un objeto complejo de su representación, de forma que el mismo proceso de construcción pueda crear diferentes representaciones.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/02/patrones-de-diseno-prototype.html"&gt;Prototype&lt;/a&gt;&lt;/span&gt;: Especifica los tipos de objetos a crear por medio de una instancia prototípica, y crear nuevos objetos copiando este prototipo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno-singleton.html"&gt;Singleton&lt;/a&gt;&lt;/span&gt;: Garantiza que una clase sólo tenga una instancia, y proporciona un punto de acceso global a ella.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Patrones estructurales&lt;/span&gt;: Tratan de facilitar el diseño identificando formas simples de establecer relaciones entre entidades.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/06/patrones-de-diseno-adapter.html"&gt;Adapter&lt;/a&gt;&lt;/span&gt;: Convierte la interfaz de una clase en otra distinta que es la que esperan los clientes. Permiten que cooperen clases que de otra manera no podrían por tener interfaces incompatibles.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Bridge&lt;/span&gt;: Desvincula una abstracción de su implementación, de manera que ambas puedan variar de forma independiente.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Composite&lt;/span&gt;: Combina objetos en estructuras de árbol para representar jerarquías de parte-todo. Permite que los clientes traten de manera uniforme a los objetos individuales y a los compuestos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Decorator&lt;/span&gt;: Añade dinámicamente nuevas responsabilidades a un objeto, proporcionando una alternativa flexible a la herencia para extender la funcionalidad.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Facade&lt;/span&gt;: Proporciona una interfaz unificada para un conjunto de interfaces de un subsistema. Define una interfaz de alto nivel que hace que el subsistema se más fácil de usar.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Flyweight&lt;/span&gt;: Usa el compartimiento para permitir un gran número de objetos de grano fino de forma eficiente.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/08/patrones-de-diseno-proxy.html"&gt;Proxy&lt;/a&gt;&lt;/span&gt;: Proporciona un sustituto o representante de otro objeto para controlar el acceso a éste.&lt;/li&gt;&lt;/ul&gt;  &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Patrones de comportamiento&lt;/span&gt;: Identifican patrones comunes de comunicación entre objetos y tratan de incrementar la flexibilidad de esta comunicación.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Chain of Responsibility&lt;/span&gt;: Evita acoplar el emisor de una petición a su receptor, al dar a más de un objeto la posibilidad de responder a la petición. Crea una cadena con los objetos receptores y pasa la petición a través de la cadena hasta que esta sea tratada por algún objeto.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Command&lt;/span&gt;: Encapsula una petición en un objeto, permitiendo así parametrizar a los clientes con distintas peticiones, encolar o llevar un registro de las peticiones y poder deshacer la operaciones.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Interpreter&lt;/span&gt;: Dado un lenguaje, define una representación de su gramática junto con un intérprete que usa dicha representación para interpretar las sentencias del lenguaje.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Iterator&lt;/span&gt;: Proporciona un modo de acceder secuencialmente a los elementos de un objeto agregado sin exponer su representación interna.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mediator&lt;/span&gt;: Define un objeto que encapsula cómo interactúan un conjunto de objetos. Promueve un bajo acoplamiento al evitar que los objetos se refieran unos a otros explícitamente, y permite variar la interacción entre ellos de forma independiente.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Memento&lt;/span&gt;: Representa y externaliza el estado interno de un objeto sin violar la encapsulación, de forma que éste puede volver a dicho estado más tarde.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Observer&lt;/span&gt;: Define una dependencia de uno-a-muchos entre objetos, de forma que cuando un objeto cambia de estado se notifica y actualizan automáticamente todos los objetos.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;State&lt;/span&gt;: Permite que un objeto modifique su comportamiento cada vez que cambia su estado interno. Parecerá que cambia la clase del objeto.&lt;/li&gt;&lt;li&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/11/patrones-de-diseno-strategy.html"&gt;&lt;span style="font-weight:bold;"&gt;Strategy&lt;/span&gt;&lt;/a&gt;: Define una familia de algoritmos, encapsula uno de ellos y los hace intercambiables. Permite que un algoritmo varíe independientemente de los clientes que lo usan.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/10/patrones-de-diseno-template-method.html"&gt;Template Method&lt;/a&gt;&lt;/span&gt;: Define en una operación el esqueleto de un algoritmo, delegando en las subclases algunos de sus pasos. Permite que las subclases redefinan ciertos pasos del algoritmo sin cambiar su estructura.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Visitor&lt;/span&gt;: Representa una operación sobre los elementos de una estructura de objetos. Permite definir una nueva operación sin cambiar las clases de los elementos sobre los que opera.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;Con el tiempo, han ido surgiendo nuevos &lt;span style="font-weight:bold;"&gt;patrones&lt;/span&gt;, sobre todo dentro del ámbito del &lt;span style="font-weight:bold;"&gt;desarrollo Java empresarial&lt;/span&gt;. Algunos de ellos son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Controlador frontal&lt;/li&gt;&lt;li&gt;Modelo Vista Controlador (MVC)&lt;/li&gt;&lt;li&gt;Vista de composición&lt;/li&gt;&lt;li&gt;Fachada de sesión - Sesion Facade&lt;/li&gt;&lt;li&gt;Localizador de servicio - Service Locator&lt;/li&gt;&lt;li&gt;Objeto valor - Value object&lt;/li&gt;&lt;li&gt;Objeto de Transferencia de Datos - Data Transfer Object (DTO)&lt;/li&gt;&lt;li&gt;Delegado de empresa - Bussiness Delegate&lt;/li&gt;&lt;li&gt;Objeto de acceso a datos - Data Access Object (DAO)&lt;/li&gt;&lt;li&gt;Dependency Injection(DI) - Inversion of Control (IoC)&lt;/li&gt;&lt;li&gt;Open Session In View (OSIV)&lt;/li&gt;&lt;li&gt;ThreadLocal Session&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;En este artículo sólo he tratado de dar una introducción a los &lt;span style="font-weight:bold;"&gt;patrones de diseño&lt;/span&gt;. En posteriores artículos trataré de desarrollar algunos de los &lt;span style="font-weight:bold;"&gt;patrones&lt;/span&gt; aquí expuestos analizando su utilidad, virtudes y defectos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612"&gt;&lt;span style="font-weight:bold;"&gt;Design Patterns&lt;/span&gt; (Erich Gamma, Richard Helm, Ralph Johnson, Hohn Vlissides)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Professional-Java-Server-Programming-J2EE/dp/1861005377"&gt;&lt;span style="font-weight:bold;"&gt;Professional Java Server Programming J2EE, 1.3 Edition&lt;/span&gt; (Subrahmanyam Allamaraju, Cedric Beust, Marc Wilcox, Sameer Tyagi, Rod Johnson, Gary Watson, Alan Williamson, John Davies, Ramesh Nagappan, Andy Longshaw, P. G. Sarang, Tyler Jewell, Alex Toussaint)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o"&gt;Patrones de diseño en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.elrincondelprogramador.com/default.asp?id=29&amp;pag=articulos/leer.asp"&gt;Introducción al diseño con patrones por Manuel Lagos Torres&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ingenierosoftware.com/analisisydiseno/patrones-diseno.php"&gt;Patrones de diseño en ingenierosoftware.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=0201633612&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-4545896725355774403?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/4545896725355774403/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4545896725355774403'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4545896725355774403'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2010/01/patrones-de-diseno.html' title='Patrones de diseño'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-8901423270695907537</id><published>2009-12-25T16:46:00.006+01:00</published><updated>2011-10-26T09:49:47.068+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Spring in Action Second Edition</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; es un framework Java que trata de simplificar el desarrollo de aplicaciones &lt;span style="font-weight:bold;"&gt;Java&lt;/span&gt; basándose en la inyección de dependencias y la programación orientada a aspectos. En este libro, Craig Walls hace una explicación exhaustiva de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; cubriendo todas las capas del desarrollo de una aplicación.&lt;br /&gt;&lt;br /&gt;El libro consta de los siguientes capítulos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Pasar a la acción&lt;/span&gt;: Se presenta &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; y los módulos que lo componen. Se introducen los conceptos principales de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, la inyección de dependencias y la programación orientada a aspectos.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Conexión básica de beans&lt;/span&gt;: Se presentan los distintos tipos de contenedores de beans, las fábricas de bean y los contextos de aplicación. A continuación se ve cómo crear beans en un contenedor y cómo inyectar valores y propiedades en ellos mediante inyección de dependencias. Después se muestra qué es la autoconexión de beans y, por último, se explica cómo controlar la creación de beans a través de métodos de inicio y destrucción del bean.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Conexión avanzada de beans&lt;/span&gt;: Se muestran conceptos avanzados del contenedor de beans de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;. Primero se ve cómo declarar beans padre de los que otros beans hijos pueden heredar propiedades. Después se enseña la inyección de métodos. Luego se pasa a la inyección de beans que no han sido creados dentro del contenedor de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;. También se ve cómo registrar editores de propiedades y cómo trabajar con beans especiales de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; que se integran en el ciclo de vida de otros bean. Por último, se ve cómo crear beans con lenguajes dinámicos como &lt;span style="font-weight:bold;"&gt;Ruby&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;Groovy&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;Beanshell&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Notificaciones a beans&lt;/span&gt;: En primer lugar, se hace una introducción a la programación orientada a aspectos (AOP). Posteriormente se explica cómo crear aspectos clásicos de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; y qué es el autoproxying. Después se ve la declaración de aspectos POJO y cómo se pueden inyectar aspectos creados con &lt;span style="font-weight:bold;"&gt;AspectJ&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Peticiones a la base de datos&lt;/span&gt;: Se examinan las capacidades de acceso a base de datos que ofrece &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, y su fillosofía de acceso a datos a través de plantillas. Posteriormente se ve cómo se puede integrar &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; con &lt;span style="font-weight:bold;"&gt;JDBC&lt;/span&gt; puro o con ORMs como &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;iBatis&lt;/span&gt;. Por último, se muestran las capacidades de cacheo en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Gestión de transacciones&lt;/span&gt;: Se revisa la gestión de transacciones en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, comenzando por una explicación de sus conceptos fundamentales. Después se enumeran los distintos gestores de transacciones disponibles y se explica cómo manejar las transacciones en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, tanto de forma programática como de forma declarativa&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Seguridad en Spring&lt;/span&gt;: Se hace una introducción a la seguridad en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, que se implementa mediante la antigua librería &lt;span style="font-weight:bold;"&gt;Acegi Security&lt;/span&gt;. Posteriormente vamos viendo cómo se autentican los usuarios y se controla el acceso. Finalmente se ve cómo asegurar una aplicación web y cómo asegurar las invocaciones a métodos.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Servicios remotos basados en Spring y POJO&lt;/span&gt;: Se ve cómo implementar y consumir servicios remotos en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; mediante &lt;span style="font-weight:bold;"&gt;RMI&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;Hessian&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;Burlap&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;Spring HttpInvoker&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;Web Services&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Construcción de servicios web contract-first en Spring&lt;/span&gt;: Comienza con una introducción a &lt;span style="font-weight:bold;"&gt;Spring-WS&lt;/span&gt;, un framework que permite construir servicios web a partir de un contrato definido en primer lugar. Después se ve cómo se manejan los mensajes de estos servicios mediante puntos finales de servicio y como juntar todo esto para la creación de un servicio. Para terminar, se ve cómo consumir servicios web usando &lt;span style="font-weight:bold;"&gt;Spring-WS&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mensajería Spring&lt;/span&gt;: Se explica qué es &lt;span style="font-weight:bold;"&gt;JMS&lt;/span&gt; y cómo se puede usar desde &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;. Después se explica cómo construir POJOS dirigidos por mensajes y, por último, cómo utilizar &lt;span style="font-weight:bold;"&gt;RPC&lt;/span&gt; basado en mensajes, en contraposición a los servicios remotos vistos en el capítulo 8.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Spring y Enterprise Java Beans&lt;/span&gt;: Se muestra cómo conectarse a &lt;span style="font-weight:bold;"&gt;EJBs&lt;/span&gt; desde &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;. Después se ve cómo desarrollar &lt;span style="font-weight:bold;"&gt;EJBs&lt;/span&gt; que puedan aprovecharse de las capacidades de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;. Por último, se ve cómo utilizar anotaciones &lt;span style="font-weight:bold;"&gt;EJB 3&lt;/span&gt;, a través del proyecto &lt;span style="font-weight:bold;"&gt;Pitchfork&lt;/span&gt;, para realizar inyección de dependencia y AOP en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Acceso a servicios empresariales&lt;/span&gt;: En este capítulo se estudia el uso en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; de capacidades empresariales como &lt;span style="font-weight:bold;"&gt;JNDI&lt;/span&gt;, correo electrónico &lt;span style="font-weight:bold;"&gt;JMS&lt;/span&gt;, planificación de tareas y gestión de beans mediante &lt;span style="font-weight:bold;"&gt;JMX&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Manejo de peticiones Web&lt;/span&gt;: Se introduce el marco MVC de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; para la capa web, en el que las peticiones son manejadas por controladores. Se ve cómo mapear las peticiones a los controladores de la aplicación y los distintos tipos de controladores que se pueden utilizar. También se ve cómo se manejan las excepciones que se pueden producir durante el procesamiento de estos controladores.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mostrar vistas Web&lt;/span&gt;: Se ve cómo &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; MVC resuelve la vista que debe mostrar como respuesta a una petición. Se examinan las diferentes posibilidades, como &lt;span style="font-weight:bold;"&gt;JSP&lt;/span&gt;, con o sin &lt;span style="font-weight:bold;"&gt;Tiles&lt;/span&gt;, y otras alternativas a &lt;span style="font-weight:bold;"&gt;JSP&lt;/span&gt;, como &lt;span style="font-weight:bold;"&gt;Velocity&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;Freemarker&lt;/span&gt;. También se ve cómo es posible generar salida no-HTML, como documentos de Excel o PDFs.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Spring Web Flow&lt;/span&gt;: Se explica qué es &lt;span style="font-weight:bold;"&gt;Spring Web Flow&lt;/span&gt;, un marco de trabajo que permite definer el flujo de navegación de una aplicación. Se ve cómo se puede definir el flujo de la aplicación desde los conceptos básicos hasta técnicas más avanzadas. También se ve cómo se puede integrar &lt;span style="font-weight:bold;"&gt;Spring Web Flow&lt;/span&gt; con otros frameworks web como &lt;span style="font-weight:bold;"&gt;Struts&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;JSF&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Integración con otros marcos de trabajo Web&lt;/span&gt;: Se explica cómo se pueden utilizar las capacidades empresariales de Spring junto con otros conocidos frameworks web como &lt;span style="font-weight:bold;"&gt;Struts&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;WebWork/Struts2&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;Tapestry&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;JSF&lt;/span&gt; y aplicaciones &lt;span style="font-weight:bold;"&gt;Ajax&lt;/span&gt; con &lt;span style="font-weight:bold;"&gt;DWR&lt;/span&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Este libro es sencillo de leer y te va introduciendo paulatinamente dentro de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, explicando los conceptos principales y utilizando gran parte de sus funcionalidades. A mí me ha servido para aprender &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; desde cero, así como para entender la inyección de dependencias y la programación orientada a aspectos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(ACTUALIZACION 26/10/2011: Ya está disponible la tercera versión de este libro, actualizada a Spring 3.)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=1935182358&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=1935182358&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-8901423270695907537?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/8901423270695907537/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/spring-in-action-second-edition.html#comment-form' title='3 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/8901423270695907537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/8901423270695907537'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/spring-in-action-second-edition.html' title='Spring in Action Second Edition'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-1714429179044606037</id><published>2009-12-13T16:50:00.007+01:00</published><updated>2011-10-26T09:53:13.730+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Hibernate in Action Second Edition</title><content type='html'>Este libro, escrito por Christian Bauer y Gavin King, es una revisión de otro libro anterior, &lt;a href="http://www.manning.com/bauer/"&gt;Hibernate in Action&lt;/a&gt;. Está actualizado a la versión 3 de &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y, además, presenta el estándar de persistencia de de &lt;span style="font-weight:bold;"&gt;EJB 3.0&lt;/span&gt; (&lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;Se trata de un libro de referencia no sólo para &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;, sino también para &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;. En él se puede encontrar información de introducción a estas dos tecnologías ORM, enseña a realizar con éxito los mapeos de objetos a entidades relacionales, explica el funcionamiento interno de &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y cómo optimizar su comportamiento y da pautas sobre cómo construir aplicaciones que hagan uso &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y/o &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Consta de los siguientes capítulos:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Comprender la persistencia objeto/relacional&lt;/span&gt;: Se hace una introducción a los problemas de la persistencia en aplicaciones orientadas a objetos que usan bases de datos relacionales, explicando los desajustes que se producen entre estas dos tecnologías. Se presentan las distintas alternativas existentes para la capa de persistencia y se presentan los ORM como la solución que nos permite abstraernos de los desajustes anteriormente mencionados.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Comenzar un proyecto&lt;/span&gt;: Se presentan las posibles alternativas de desarrollo con &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;, dependiendo de si empezamos desde un modelo de clases o desde un modelo relacional. A continuación se muestra la configuración de Hibernate en un proyecto y se implementa el mismo proyecto de distintas formas: usando Hibernate y mapeo XML, anotaciones, &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt; mediante el &lt;span style="font-weight:bold;"&gt;Hibernate EntityManager&lt;/span&gt; y componentes &lt;span style="font-weight:bold;"&gt;EJB&lt;/span&gt;. Posteriormente se hace una introducción a la ingeniería inversa con &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; dada una base de datos. Por último, se presenta cómo se integra &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; con otros servicios de la plataforma &lt;span style="font-weight:bold;"&gt;JEE&lt;/span&gt; como &lt;span style="font-weight:bold;"&gt;JTA&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;JNDI&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;JMX&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Modelos de dominio y metadatos&lt;/span&gt;: Se presenta el modelo de dominio de ejemplo que se utilizará en el libro, un sistema de subastas. Se presentan las pautas para la implementación de este modelo, como el desarrollo de &lt;span style="font-weight:bold;"&gt;POJOs&lt;/span&gt;. A continuación se muestran las distintas alternativas para los metadatos de mapeo, XML, anotaciones, XDoclet y de forma programática en la ejecución. Por último se presentan representaciones alternativas de las entidades mediante mapas y XML.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mapear clases persistentes&lt;/span&gt;: Se explica la diferencia entre las entidades y los tipos de valor. También se ve el concepto de identidad en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;. Después se ven algunas opciones para el mapeo de clases. Por último, se ve como mapear tipos de valor, tanto para tipos de datos Java como para clases.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Herencia y tipos personalizados&lt;/span&gt;: Se muestran las distintas formas de manejar la herencia en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;. También se ve el conjunto de tipos de datos que ofrece &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y explica como crear tipos de datos personalizados.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mapear colecciones y asociaciones de entidades&lt;/span&gt;: Se presentan los distintos tipos de colecciones que maneja &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y se muestra cómo mapear colecciones de tipos de valor tanto en el caso de tipos simples como de clases. Posteriormente se ve cómo mapear una relación padre/hijo entre entidades.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Mapeo avanzado de asociaciones de entidades&lt;/span&gt;: Se continúa viendo cómo mapear relaciones entre entidades, tanto relaciones simples como múltiples. También se ven las asociaciones polimórficas entre entidades.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Bases de datos heredadas y SQL personalizado&lt;/span&gt;: Se comentan los principales problemas en la integración con bases de datos heredadas. Después se estudia la personalización del SQL que genera &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; en las consultas, y se ve la integración de procedimientos almacenados y funciones. Por último, se muestra cómo mejorar el DDL generado por &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; para personalizar los nombres y los tipos de datos, añadir restricciones o crear índices.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Trabajar con objetos&lt;/span&gt;: En este capítulo se comienza exponiendo el ciclo de vida de los objetos persistentes y después se habla de los conceptos de identidad e igualdad de objetos, introduciendo las conversaciones y el ámbito de identidad de un objeto. A continuación se ven los interfaces de persistencia de &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y de &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;, terminando con una explicación de cómo usar &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt; en componentes &lt;span style="font-weight:bold;"&gt;EJB&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Transacciones y concurrencia&lt;/span&gt;: Se revisan los conceptos básicos de las transacciones en las bases de datos y cómo pueden ser manejadas en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;. También se trata el control del acceso concurrente en las bases de datos, revisando el control optimista de la concurrencia y cómo se pueden obtener garantías adicionales en el aislamiento. Por último, se estudia el acceso no transaccional, viendo en qué casos se puede trabajar en modo autocommit tanto con &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; como con &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Implementando conversaciones&lt;/span&gt;: Se comienza viendo cómo se propaga la sesión en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;, que puede ser a través de una variable &lt;span style="font-style:italic;"&gt;thread-local&lt;/span&gt;, a través de &lt;span style="font-weight:bold;"&gt;JTA&lt;/span&gt; o mediante &lt;span style="font-weight:bold;"&gt;EJBs&lt;/span&gt;. Después se ve cómo se pueden implementar convesaciones en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;EJB&lt;/span&gt; a través de objetos “separados” (&lt;span style="font-style:italic;"&gt;detached&lt;/span&gt;) y extendiendo la sesión.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Modificar objetos eficientemente&lt;/span&gt;: En primer lugar se estudia la persistenca transitiva de objetos a través de las asociaciones en cascada, tanto con &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; como con &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;. Posteriormente se pasa a ver cómo manejar operaciones que implican grandes volúmenes de datos a través de &lt;span style="font-weight:bold;"&gt;HQL&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;JPA QL&lt;/span&gt; y cómo procesar lotes. Por último, se ve cómo filtrar los datos de las consultas y cómo interceptar eventos en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Optimizar la recuperación y el cacheo&lt;/span&gt;: Comenzamos viendo cómo definir el plan de obtención de datos en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y se dan pautas de qué estrategia elegir y cóm optimizarla. Posteriormente se exponen los principios de cacheo en &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y se explica cómo establecer una cache de segundo nivel a través de proveedores de cache.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Hacer consultas con HQL y JPA QL&lt;/span&gt;: Veremos cómo crear y ejecutar consultas a base de datos. Se aprenderá a crear consultas básicas con &lt;span style="font-weight:bold;"&gt;HQL&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;JPA QL&lt;/span&gt; y cómo se usan las joins, las consultas de informes y las &lt;span style="font-style:italic;"&gt;subselects&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Opciones de consulta avanzadas&lt;/span&gt;: En este capítulo se ve cómo usar las APIs &lt;span style="font-weight:bold;"&gt;Criteria&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;Example&lt;/span&gt; para construir consultas de forma programática. También se ve cómo hacer consultas nativas en SQL. Después se ve cómo filtrar colecciones, y, por último, se habla del cacheo de resultados de consultas y en qué casos es conveniente hacerlo.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Crear y probar aplicaciones en capas&lt;/span&gt;: En este capítulo se dan pautas para el diseño de aplicaciones web con &lt;span style="font-weight:bold;"&gt;Hibernat&lt;/span&gt;e, a través de patrones como &lt;span style="font-style:italic;"&gt;OSIV&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;Open Session In View&lt;/span&gt;), &lt;span style="font-style:italic;"&gt;Command&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;DAO&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;Data Access Object&lt;/span&gt;). También se trata el diseño de aplicaciones con &lt;span style="font-weight:bold;"&gt;EJB 3.0&lt;/span&gt;. Por último, se trata el tema de cómo probar estas aplicaciones y se presentan herramientas como &lt;span style="font-weight:bold;"&gt;TestNG&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;DBUnit&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Introducción a JBoss Seam&lt;/span&gt;: En este capítulo se hace un introducción al marco de trabajo &lt;span style="font-weight:bold;"&gt;JBoss Seam&lt;/span&gt;, un marco de trabajo orientado a &lt;span style="font-weight:bold;"&gt;Java EE 5.0&lt;/span&gt; que se base en &lt;span style="font-weight:bold;"&gt;JSF&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;EJB 3.0&lt;/span&gt;. Se ve cómo mejorar una aplicación usando este marco, cómo utilizar componentes contextuales, cómo validar los datos de entrada y cómo simplificar la persistencia.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Se trata de un libro difícil de leer de corrido por la complejidad de los temas que trata. Sin embargo, creo que es un libro de referencia excelente sobre &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;JPA&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?t=tratanddeente-20&amp;o=1&amp;p=8&amp;l=as1&amp;asins=1932394885&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;iframe src="http://rcm-es.amazon.es/e/cm?t=tratanddeente-21&amp;o=30&amp;p=8&amp;l=as1&amp;asins=1932394885&amp;ref=tf_til&amp;fc1=000000&amp;IS2=1&amp;lt1=_blank&amp;m=amazon&amp;lc1=0000FF&amp;bc1=000000&amp;bg1=FFFFFF&amp;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-1714429179044606037?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/1714429179044606037/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/hibernate-in-action-second-edition.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1714429179044606037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1714429179044606037'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/hibernate-in-action-second-edition.html' title='Hibernate in Action Second Edition'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-4969756605981560589</id><published>2009-12-11T11:25:00.005+01:00</published><updated>2010-08-31T13:44:17.765+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ClearCase'/><category scheme='http://www.blogger.com/atom/ns#' term='Control de versiones'/><title type='text'>Control de versiones con ClearCase</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Rational ClearCase&lt;/span&gt; es el sistema de control de versiones de IBM. Aunque &lt;span style="font-weight:bold;"&gt;Subversion&lt;/span&gt; es más de mi agrado por su sencillez, esta herramienta es la que utilizo en el trabajo. Estamos teniendo un montón de problemas trabajando con ella, aunque estoy convencido que es más por desconocimiento que por la herramienta en sí. Así que voy a exponer a continuación que es &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt;, cómo lo usamos y qué problemas estamos encontrando de cara a compartir experiencias con otros usuarios de &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Cómo otros sistemas de control de versiones, &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt; almacena distintas versiones de los &lt;span style="font-style:italic;"&gt;elemento&lt;/span&gt;s que forman parte de un proyecto, que pueden ser directorios o archivos. Estos &lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt; se almacenan en un repositorio que en &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt; se llama &lt;span style="font-style:italic;"&gt;base de objetos de versionado&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;VOB&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt; proporciona un proceso de gestión de la configuración llamado &lt;span style="font-style:italic;"&gt;gestión del cambio unificado&lt;/span&gt; (&lt;span style="font-style:italic;"&gt;UCM&lt;/span&gt;). &lt;span style="font-style:italic;"&gt;UCM&lt;/span&gt; se situa sobre la base de &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt; simplificando el trabajo.&lt;br /&gt;&lt;br /&gt;En &lt;span style="font-style:italic;"&gt;UCM&lt;/span&gt; un &lt;span style="font-style:italic;"&gt;proyecto&lt;/span&gt; es un producto de un desarrollo de software que contiene información de configuración sobre el mismo. Un &lt;span style="font-style:italic;"&gt;proyecto&lt;/span&gt; está formado por &lt;span style="font-style:italic;"&gt;componentes&lt;/span&gt;, que constituyen las partes de un &lt;span style="font-style:italic;"&gt;proyecto&lt;/span&gt;, como módules web o módulos JAR en un proyecto Java.&lt;br /&gt;&lt;br /&gt;Las modificaciones que se llevan a cabo durante las tareas de desarrollo dentro de la ejecución de un &lt;span style="font-style:italic;"&gt;proyecto&lt;/span&gt; se registran en &lt;span style="font-style:italic;"&gt;actividades&lt;/span&gt;, que consisten en varias versiones de distintos &lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt; de un componente.&lt;br /&gt;&lt;br /&gt;Un &lt;span style="font-style:italic;"&gt;proyecto&lt;/span&gt; consta de un área de trabajo compartido y muchas áreas de trabajo privadas. Cada área de trabajo está formada por una &lt;span style="font-style:italic;"&gt;corriente&lt;/span&gt; y una o varias &lt;span style="font-style:italic;"&gt;vistas&lt;/span&gt;. Una &lt;span style="font-style:italic;"&gt;corriente&lt;/span&gt; es un objeto de &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt; que mantiene una lista de &lt;span style="font-style:italic;"&gt;actividades&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;líneas base&lt;/span&gt; que determinan que versiones de &lt;span style="font-style:italic;"&gt;elemento&lt;/span&gt;s aparecen en la &lt;span style="font-style:italic;"&gt;vista&lt;/span&gt;. Una &lt;span style="font-style:italic;"&gt;vista&lt;/span&gt; es un árbol de directorio que muestra una única versión de cada archivo del proyecto.&lt;br /&gt;&lt;br /&gt;Todo proyecto tiene un área de trabajo compartido que se maneja mediante una &lt;span style="font-style:italic;"&gt;corriente&lt;/span&gt; y una &lt;span style="font-style:italic;"&gt;vista de integración&lt;/span&gt;. Su función es registrar las &lt;span style="font-style:italic;"&gt;líneas base&lt;/span&gt; del &lt;span style="font-style:italic;"&gt;proyecto&lt;/span&gt; y recibir las nuevas versiones de los &lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt; compartidos del proyecto para su integración conjunta. &lt;br /&gt;&lt;br /&gt;Cada &lt;span style="font-style:italic;"&gt;línea base&lt;/span&gt; representa una versión de los &lt;span style="font-style:italic;"&gt;elemento&lt;/span&gt;s de un &lt;span style="font-style:italic;"&gt;componente&lt;/span&gt; en un determinado momento del desarrollo. A lo largo del proyecto, el administrador crea y recomienda líneas base para reflejar hitos del proyecto.&lt;br /&gt;&lt;br /&gt;Según &lt;span style="font-style:italic;"&gt;UCM&lt;/span&gt;, los desarrolladores tienen un área de trabajo privada donde realizan sus cambios. Esta área de trabajo consta una de &lt;span style="font-style:italic;"&gt;corriente de desarrollo&lt;/span&gt; que mantiene la lista de &lt;span style="font-style:italic;"&gt;actividades&lt;/span&gt; del desarrollador y determina qué versiones de los &lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt; del proyecto aparecen en su &lt;span style="font-style:italic;"&gt;vista de desarrollo&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Cuando los desarrolladores se unen a un proyecto incluyen en sus áreas de trabajo las versiones de los &lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt; del proyecto marcados en la &lt;span style="font-style:italic;"&gt;línea base&lt;/span&gt; recomendada del &lt;span style="font-style:italic;"&gt;proyecto&lt;/span&gt;. Éstos harán sus cambios dentro de &lt;span style="font-style:italic;"&gt;actividades&lt;/span&gt; en su área de trabajo privada y, una vez finalizados y probados, harán entrega (&lt;span style="font-style:italic;"&gt;deliver&lt;/span&gt;) de estas &lt;span style="font-style:italic;"&gt;actividades&lt;/span&gt; a la &lt;span style="font-style:italic;"&gt;corriente de integración&lt;/span&gt;, lo que podría llevar a tener que combinar &lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt; si otro desarrollador ha hecho modificaciones en los mismos &lt;span style="font-style:italic;"&gt;elementos&lt;span style="font-style:italic;"&gt;&lt;/span&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Periódicamente, los desarrolladores deben hacer &lt;span style="font-style:italic;"&gt;rebase&lt;/span&gt; para actualizarse a las últimas &lt;span style="font-style:italic;"&gt;líneas base&lt;/span&gt; recomendadas. Si las &lt;span style="font-style:italic;"&gt;líneas base&lt;/span&gt; incluyen nuevas versiones de los &lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt; que se están modificando en la &lt;span style="font-style:italic;"&gt;vista de desarroll&lt;/span&gt;o, la operación de &lt;span style="font-style:italic;"&gt;rebase&lt;/span&gt; fusiona las dos versiones en una nueva versión dentro de la &lt;span style="font-style:italic;"&gt;corriente de desarrollo&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Lo explicado hasta ahora es el proceso de gestión de la configuración que define &lt;span style="font-style:italic;"&gt;UCM&lt;/span&gt;, que implica que cada desarrollador tiene su propio área de trabajo privada. Esto permite que los desarrolladores trabajen de forma paralela e independiente sin colisionar entre ellos a la hora de modificar los mismo elementos. Estos serán fusionados posteriormente en las operaciones de &lt;span style="font-style:italic;"&gt;deliver&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;rebase&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Sin embargo, esto añade carga de gestión al desarrollo, porque para ver las últimas modificaciones de otro desarrollador es necesario que haya entregado sus &lt;span style="font-style:italic;"&gt;actividades&lt;/span&gt;, se haya hecho una nueva &lt;span style="font-style:italic;"&gt;línea base&lt;/span&gt; y los otros desarrolladores hagan un &lt;span style="font-style:italic;"&gt;rebase&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Para aligerar esta carga, nosotros usamos una única área de desarrollo para todos los desarrolladores, que tienen &lt;span style="font-style:italic;"&gt;vistas&lt;/span&gt; a ella. Todos los cambios que un desarrollador registra pueden ser vistos por los demás desarrolladores sin más que hacer un &lt;span style="font-style:italic;"&gt;updat&lt;/span&gt;e de su &lt;span style="font-style:italic;"&gt;vista&lt;/span&gt;, permitiendo que los nuevos cambios se publiquen de manera más inmediata.  &lt;br /&gt;&lt;br /&gt;Sin embargo, si todos los desarrolladores están desarrollando en &lt;span style="font-style:italic;"&gt;vistas&lt;/span&gt; de la misma &lt;span style="font-style:italic;"&gt;corriente&lt;/span&gt;, se pueden producir situaciones no deseadas:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Modificaciones concurrentes de los mismos archivos&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Un desarrollador &lt;span style="font-style:italic;"&gt;desaA&lt;/span&gt; está modificando un archivo &lt;span style="font-style:italic;"&gt;fich1&lt;/span&gt;, para lo cual lo ha reservado (&lt;span style="font-style:italic;"&gt;check out&lt;/span&gt;).&lt;/li&gt;&lt;li&gt;Otro desarrollador &lt;span style="font-style:italic;"&gt;desaB&lt;/span&gt; también quiere modificar este archivo, y, si no quiere quedarse bloqueado en su trabajo, lo reserva (&lt;span style="font-style:italic;"&gt;check out&lt;/span&gt;) después de que aparece un aviso de que el desarrollador &lt;span style="font-style:italic;"&gt;desaA&lt;/span&gt; lo ha reservado previamente.&lt;/li&gt;&lt;li&gt;El desarrollador &lt;span style="font-style:italic;"&gt;desaA&lt;/span&gt; sube (&lt;span style="font-style:italic;"&gt;check in&lt;/span&gt;) el archivo con sus modificaciones.&lt;/li&gt;&lt;li&gt;El desarrollador &lt;span style="font-style:italic;"&gt;desaB&lt;/span&gt; sube (&lt;span style="font-style:italic;"&gt;check in&lt;/span&gt;) el archivo con sus modificaciones, pero en ese momento &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt; le avisa de que en el repositorio hay una versión de este archivo posterior a aquella que reservó, por lo que debe fusionar las dos versiones (&lt;span style="font-style:italic;"&gt;merge&lt;/span&gt;). Este &lt;span style="font-style:italic;"&gt;merge&lt;/span&gt; puede ser automático o manual, a través de la herramienta de &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt; para esto.&lt;/li&gt;&lt;li&gt;Este problema, que con un solo archivo puede ser fácil de solucionar, se complica cuando se están modificando varios archivos que coinciden por parte de varios desarrolladores. Se puede llegar a situaciones de bloqueo, por ejemplo, si un desarrollador no puede actualizarse un archivo que ha modificado otro desarrollador y es necesario para que los cambios en otros archivos compilen sin error porque el archivo necesario está reservado y siendo modificado por el desarrollador. Se puede llegar a situaciones difíciles de salir.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Dependencia entre actividades no relacionadas&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Un desarrollador &lt;span style="font-style:italic;"&gt;desaA&lt;/span&gt; está realizando modificaciones dentro de una actividad &lt;span style="font-style:italic;"&gt;activA&lt;/span&gt; que implican a los ficheros &lt;span style="font-style:italic;"&gt;fich1&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;fich2&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;fich3&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Comienza reservando (&lt;span style="font-style:italic;"&gt;check out&lt;/span&gt;) &lt;span style="font-style:italic;"&gt;fich1&lt;/span&gt;, haciendo los cambios pertinentes y subiéndolo (&lt;span style="font-style:italic;"&gt;check in&lt;/span&gt;) al repositorio, y después pasa a reservar &lt;span style="font-style:italic;"&gt;fich2&lt;/span&gt; y modificarlo.&lt;/li&gt;&lt;li&gt;En ese momento, otro desarrollador &lt;span style="font-style:italic;"&gt;desaB&lt;/span&gt; realiza otras modificaciones distintas dentro de otra actividad &lt;span style="font-style:italic;"&gt;activB&lt;/span&gt; que implican modificar el fichero &lt;span style="font-style:italic;"&gt;fich2&lt;/span&gt;, previamente modificado en la actividad &lt;span style="font-style:italic;"&gt;activA&lt;/span&gt; de &lt;span style="font-style:italic;"&gt;desaA&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Por necesidades del proyecto, hace falta crear una nueva versión (&lt;span style="font-style:italic;"&gt;línea base&lt;/span&gt;) del proyecto sólo con la modificación realizada en la actividad &lt;span style="font-style:italic;"&gt;activB&lt;/span&gt; y no las modificaciones de &lt;span style="font-style:italic;"&gt;activA&lt;/span&gt;. Por ejemplo, porque &lt;span style="font-style:italic;"&gt;activB&lt;/span&gt; es una corrección de un bug que queremos solucionar rapidamente en producción, pero &lt;span style="font-style:italic;"&gt;activA&lt;/span&gt; es un nuevo desarrollo que no queremos subir hasta no haberlo probado concienzudamente.&lt;/li&gt;&lt;li&gt;Al tratar de subir la actividad &lt;span style="font-style:italic;"&gt;activB&lt;/span&gt;, ClearCase nos dirá que esta actividad depende de la actividad &lt;span style="font-style:italic;"&gt;activA&lt;/span&gt; y que también hay que subirla. Esto es debido a que la modificación del fichero &lt;span style="font-style:italic;"&gt;fich2&lt;/span&gt; se hizo sobre la versión modificada en la actividad &lt;span style="font-style:italic;"&gt;activA&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Resultado, no se puede subir &lt;span style="font-style:italic;"&gt;activB&lt;/span&gt; de forma independiente de &lt;span style="font-style:italic;"&gt;activA&lt;/span&gt;. Y este problema se puede complicar exponencialmente a mayor número de desarrolladores.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Conclusión, hay que evitar que varios desarrolladores modifiquen los mismo archivos por el bien de la productividad del equipo y de la facilidad en la gestión del proyecto. Lo cual me hace pensar que lo mejor sería un área de desarrollo privada por cada desarrollador como dicta &lt;span style="font-style:italic;"&gt;UCM&lt;/span&gt;, pero esta forma de trabajar, que también usamos en otro proyecto aumentaría el número de merges de forma considerable con el riego que conllevan.&lt;br /&gt;&lt;br /&gt;Aquí os pido colaboración. ¿Alguien tiene experiencia con &lt;span style="font-weight:bold;"&gt;ClearCase&lt;/span&gt;? Me gustaría saber qué estrategias se están usando en otros proyectos y cómo solucionan todos estos problemas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.info-ab.uclm.es/asignaturas/42551/trabajosAnteriores/Trabajo_ClearCase.pdf"&gt;Introducción a Rational ClearCase LT (Rosa María Carretero López)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/IBM_Rational_ClearCase"&gt;ClearCase en Wikipedia&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Comparison_of_revision_control_software"&gt;Comparación de software de control de versiones&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-4969756605981560589?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/4969756605981560589/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/control-de-versiones-con-clearcase.html#comment-form' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4969756605981560589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4969756605981560589'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/control-de-versiones-con-clearcase.html' title='Control de versiones con ClearCase'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-3720121920790536750</id><published>2009-12-04T21:48:00.002+01:00</published><updated>2010-06-08T09:59:24.508+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General'/><title type='text'>Manifiesto en defensa de los derecho fundamentales en Internet</title><content type='html'>Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de internet manifestamos nuestra firme oposición al proyecto, y declaramos que…&lt;br /&gt;&lt;br /&gt;1.- &lt;span style="font-weight:bold;"&gt;Los derechos de autor no pueden situarse por encima de los derechos fundamentales de los ciudadanos&lt;/span&gt;, como el derecho a la privacidad, a la seguridad, a la presunción de inocencia, a la tutela judicial efectiva y a la libertad de expresión.&lt;br /&gt;&lt;br /&gt;2.- &lt;span style="font-weight:bold;"&gt;La suspensión de derechos fundamentales es y debe seguir siendo competencia exclusiva del poder judicial&lt;/span&gt;. Ni un cierre sin sentencia. Este anteproyecto, en contra de lo establecido en el artículo 20.5 de la Constitución, pone en manos de un órgano no judicial -un organismo dependiente del ministerio de Cultura-, la potestad de impedir a los ciudadanos españoles el acceso a cualquier página web.&lt;br /&gt;&lt;br /&gt;3.- &lt;span style="font-weight:bold;"&gt;La nueva legislación creará inseguridad jurídica en todo el sector tecnológico español&lt;/span&gt;, perjudicando uno de los pocos campos de desarrollo y futuro de nuestra economía, entorpeciendo la creación de empresas, introduciendo trabas a la libre competencia y ralentizando su proyección internacional.&lt;br /&gt;&lt;br /&gt;4.- &lt;span style="font-weight:bold;"&gt;La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural&lt;/span&gt;. Con Internet y los sucesivos avances tecnológicos se ha democratizado extraordinariamente la creación y emisión de contenidos de todo tipo, que ya no provienen prevalentemente de las industrias culturales tradicionales, sino de multitud de fuentes diferentes.&lt;br /&gt;&lt;br /&gt;5.- &lt;span style="font-weight:bold;"&gt;Los autores, como todos los trabajadores, tienen derecho a vivir de su trabajo con nuevas ideas creativas&lt;/span&gt;, modelos de negocio y actividades asociadas a sus creaciones. Intentar sostener con cambios legislativos a una industria obsoleta que no sabe adaptarse a este nuevo entorno no es ni justo ni realista. Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo.&lt;br /&gt;&lt;br /&gt;6.- &lt;span style="font-weight:bold;"&gt;Consideramos que las industrias culturales necesitan para sobrevivir alternativas modernas, eficaces, creíbles y asequibles y que se adecuen a los nuevos usos sociales&lt;/span&gt;, en lugar de limitaciones tan desproporcionadas como ineficaces para el fin que dicen perseguir.&lt;br /&gt;&lt;br /&gt;7.- &lt;span style="font-weight:bold;"&gt;Internet debe funcionar de forma libre y sin interferencias políticas&lt;/span&gt; auspiciadas por sectores que pretenden perpetuar obsoletos modelos de negocio e imposibilitar que el saber humano siga siendo libre.&lt;br /&gt;&lt;br /&gt;8.- &lt;span style="font-weight:bold;"&gt;Exigimos que el Gobierno garantice por ley la neutralidad de la Red en España&lt;/span&gt;, ante cualquier presión que pueda producirse, como marco para el desarrollo de una economía sostenible y realista de cara al futuro.&lt;br /&gt;&lt;br /&gt;9.- &lt;span style="font-weight:bold;"&gt;Proponemos una verdadera reforma del derecho de propiedad intelectual&lt;/span&gt; orientada a su fin: devolver a la sociedad el conocimiento, promover el dominio público y limitar los abusos de las entidades gestoras.&lt;br /&gt;&lt;br /&gt;10.- &lt;span style="font-weight:bold;"&gt;En democracia las leyes y sus modificaciones deben aprobarse tras el oportuno debate público y habiendo consultado previamente a todas las partes implicadas&lt;/span&gt;. No es de recibo que se realicen cambios legislativos que afectan a derechos fundamentales en una ley no orgánica y que versa sobre otra materia.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-3720121920790536750?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/3720121920790536750/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/manifiesto-en-defensa-de-los-derecho.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3720121920790536750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3720121920790536750'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/12/manifiesto-en-defensa-de-los-derecho.html' title='Manifiesto en defensa de los derecho fundamentales en Internet'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-5648395576287568360</id><published>2009-11-27T19:20:00.003+01:00</published><updated>2010-08-13T12:09:03.548+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Utilidades Java'/><title type='text'>Configuración de Log4j en una aplicación web</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Log4j&lt;/span&gt; es una librería que permite guardar registros informativos sobre el funcionamiento de una aplicación. En este artículo vamos a ver cómo configurar &lt;span style="font-weight:bold;"&gt;Log4j&lt;/span&gt; para su uso en una aplicación web.&lt;br /&gt;&lt;br /&gt;En primer lugar vamos a crear en &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt; un proyecto war &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; que se llame &lt;span style="font-style:italic;"&gt;PruebaLog4jWeb&lt;/span&gt;. Crearemos también una página de inicio &lt;span style="font-style:italic;"&gt;index.jsp&lt;/span&gt; y desplegaremos la aplicación en un servidor. La URL de la aplicación será &lt;a href="http://localhost:8080/PruebaLog4jWeb/"&gt;http://localhost:8080/PruebaLog4jWeb/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Añadimos la dependencia a la API de servlets para poder trabajar en nuestro proyecto con sus clases. Esta librería no hace falta desplegarla en el servidor, puesto que éste tendrá su propia implementación de esta API:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;servlet-api&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;2.5&amp;lt;/version&amp;gt;&lt;br /&gt; &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;br /&gt;Añadimos la dependencia a &lt;span style="font-weight:bold;"&gt;Log4j&lt;/span&gt; en el pom.xml del proyecto:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;log4j&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;log4j&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;1.2.15&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;br /&gt;Ahora vamos a crear el siguiente servlet:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.log4j;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;&lt;br /&gt;import javax.servlet.RequestDispatcher;&lt;br /&gt;import javax.servlet.ServletException;&lt;br /&gt;import javax.servlet.http.HttpServlet;&lt;br /&gt;import javax.servlet.http.HttpServletRequest;&lt;br /&gt;import javax.servlet.http.HttpServletResponse;&lt;br /&gt;&lt;br /&gt;import org.apache.log4j.Logger;&lt;br /&gt;&lt;br /&gt;public class ServletPrueba extends HttpServlet {&lt;br /&gt;&lt;br /&gt; private static final long serialVersionUID = 1L;&lt;br /&gt;&lt;br /&gt; static Logger logger = Logger.getLogger(ServletPrueba.class);&lt;br /&gt; &lt;br /&gt; public ServletPrueba() { }&lt;br /&gt;&lt;br /&gt; protected void doGet(&lt;br /&gt;  HttpServletRequest request, &lt;br /&gt;  HttpServletResponse response) &lt;br /&gt;  throws ServletException, IOException {&lt;br /&gt;  &lt;br /&gt;  logger.debug("Se ha llamado al servlet mediante un GET.");&lt;br /&gt;  &lt;br /&gt;  execute(request, response);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected void doPost(&lt;br /&gt;  HttpServletRequest request, &lt;br /&gt;  HttpServletResponse response) &lt;br /&gt;  throws ServletException, IOException {&lt;br /&gt;  &lt;br /&gt;  logger.debug("Se ha llamado al servlet mediante un POST.");&lt;br /&gt;  &lt;br /&gt;  execute(request, response);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; protected void execute(&lt;br /&gt;  HttpServletRequest request, &lt;br /&gt;  HttpServletResponse response) &lt;br /&gt;  throws ServletException, IOException {&lt;br /&gt;  &lt;br /&gt;  logger.info("Se redirige a la página de inicio.");&lt;br /&gt;  &lt;br /&gt;  RequestDispatcher rd = &lt;br /&gt;   request.getRequestDispatcher("index.jsp");&lt;br /&gt;  rd.forward(request, response);&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;En él hemos creado un logger estático de &lt;span style="font-weight:bold;"&gt;Log4j&lt;/span&gt; que usamos en los distintos métodos del servlet para mostrar logs con distinto grado de importancia.&lt;br /&gt;&lt;br /&gt;Para configurar la salida de los logs tenemos que crear un archivo &lt;span style="font-style:italic;"&gt;log4j.properties&lt;/span&gt;, donde definiremos cómo queremos que se muestren los logs. Vamos a mostrar los logs de nuestra aplicación tanto por consola como en un archivo:&lt;br /&gt;&lt;pre class="prettyprint"&gt;log4j.logger.com.roldan.log4j=debug, stdout, file&lt;br /&gt;&lt;br /&gt;log4j.appender.stdout=org.apache.log4j.ConsoleAppender&lt;br /&gt;log4j.appender.stdout.layout=org.apache.log4j.PatternLayout&lt;br /&gt;&lt;br /&gt;# Pattern to output the caller's file name and line number.&lt;br /&gt;log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n&lt;br /&gt;&lt;br /&gt;log4j.appender.file=org.apache.log4j.RollingFileAppender&lt;br /&gt;log4j.appender.file.File=example.log&lt;br /&gt;&lt;br /&gt;log4j.appender.file.MaxFileSize=100KB&lt;br /&gt;# Keep one backup file&lt;br /&gt;log4j.appender.file.MaxBackupIndex=1&lt;br /&gt;&lt;br /&gt;log4j.appender.file.layout=org.apache.log4j.PatternLayout&lt;br /&gt;log4j.appender.file.layout.ConversionPattern=%p %t %c - %m%n&lt;/pre&gt;&lt;br /&gt;Por último, debemos inicializar &lt;span style="font-weight:bold;"&gt;Log4j&lt;/span&gt; dentro de cada aplicación web, para que cada aplicación pueda trabajar satisfactoriamente de modo independiente. Para ello, vamos a incluir en la aplicación el siguiente servlet de inicialización:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.log4j;&lt;br /&gt;&lt;br /&gt;import org.apache.log4j.PropertyConfigurator;&lt;br /&gt;import javax.servlet.http.HttpServlet;&lt;br /&gt;import javax.servlet.http.HttpServletRequest;&lt;br /&gt;import javax.servlet.http.HttpServletResponse;&lt;br /&gt;&lt;br /&gt;public class Log4jInit extends HttpServlet {&lt;br /&gt;&lt;br /&gt; public void init() {&lt;br /&gt;  String prefix =  getServletContext().getRealPath("/");&lt;br /&gt;  String file = getInitParameter("log4j-init-file");&lt;br /&gt;&lt;br /&gt;  if(file != null) {&lt;br /&gt;   PropertyConfigurator.configure(prefix+file);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void doGet(HttpServletRequest req, HttpServletResponse res) {}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;E incluiremos la siguiente configuración en el archivo &lt;span style="font-style:italic;"&gt;web.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt; &amp;lt;servlet-name&amp;gt;log4j-init&amp;lt;/servlet-name&amp;gt;&lt;br /&gt; &amp;lt;servlet-class&amp;gt;com.roldan.log4j.Log4jInit&amp;lt;/servlet-class&amp;gt;&lt;br /&gt; &amp;lt;init-param&amp;gt;&lt;br /&gt;  &amp;lt;param-name&amp;gt;log4j-init-file&amp;lt;/param-name&amp;gt;&lt;br /&gt;  &amp;lt;param-value&amp;gt;WEB-INF/log4j.properties&amp;lt;/param-value&amp;gt;&lt;br /&gt; &amp;lt;/init-param&amp;gt;&lt;br /&gt; &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;/pre&gt;&lt;br /&gt;Cuando redesplegamos y ejecutamos la aplicación llamando al servlet mediante la URL &lt;a href="http://localhost:8080/PruebaLog4jWeb/ServletPrueba"&gt;http://localhost:8080/PruebaLog4jWeb/ServletPrueba&lt;/a&gt; se muestran los siguientes logs en la consola:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;DEBUG [http-8080-2] (ServletPrueba.java:23) &lt;br /&gt; - Se ha llamado al servlet mediante un GET.&lt;br /&gt;INFO [http-8080-2] (ServletPrueba.java:39) &lt;br /&gt; - Se redirige a la página de inicio.&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://logging.apache.org/log4j/1.2/index.html"&gt;http://logging.apache.org/log4j/1.2/index.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://logging.apache.org/log4j/1.2/manual.html"&gt;http://logging.apache.org/log4j/1.2/manual.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-5648395576287568360?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/5648395576287568360/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/configuracion-de-log4j-en-una.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5648395576287568360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5648395576287568360'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/configuracion-de-log4j-en-una.html' title='Configuración de Log4j en una aplicación web'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-6548847399708424531</id><published>2009-11-18T15:51:00.012+01:00</published><updated>2010-11-30T22:11:07.681+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bases de datos'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Configuración de EhCache en Spring</title><content type='html'>En este artículo vamos a ver cómo se puede acceder a los datos almacenados en una base de datos a través de una plantilla JDBC de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;. Para mejorar el rendimiento en este acceso a base de datos introduciremos también una caché usando &lt;span style="font-weight:bold;"&gt;EhCache&lt;/span&gt; que permita almacenar las consultas ya obtenidas evitando el acceso a la base de datos.&lt;br /&gt;&lt;br /&gt;En primer lugar, creamos en &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt; un proyecto &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; e incluimos las dependencias necesarias en el archivo &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt; del proyecto:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;project&lt;br /&gt; xmlns="http://maven.apache.org/POM/4.0.0" &lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0&lt;br /&gt;  http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;br /&gt; &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;com.roldan.spring&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;PruebaCache&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;  &lt;br /&gt; &amp;lt;dependencies&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;spring&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.5.6&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;log4j&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;log4j&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;1.2.15&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;mysql&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;mysql-connector-java&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;5.1.10&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.springmodules&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;spring-modules-cache&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;0.7&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;net.sf.ehcache&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;ehcache&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;1.6.2&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt; &lt;br /&gt; &amp;lt;/dependencies&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;/pre&gt;&lt;br /&gt;Las dependencias necesarias para nuestro proyecto son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;El framework &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Log4j&lt;/span&gt; para sacar logs informativos sobre la ejecución de la aplicación.&lt;/li&gt;&lt;li&gt;El conector a base de datos &lt;span style="font-weight:bold;"&gt;MySql&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;El módulo de cache del proyecto &lt;span style="font-weight:bold;"&gt;spring-modules&lt;/span&gt;, que permite integrar la herramienta &lt;span style="font-weight:bold;"&gt;EhCache&lt;/span&gt; con &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt; de forma sencilla.&lt;/li&gt;&lt;li&gt;La herramienta de cacheo &lt;span style="font-weight:bold;"&gt;EhCache&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Posteriormente hemos creado una base de datos (&lt;span style="font-style:italic;"&gt;pruebacache&lt;/span&gt;) con una única tabla (&lt;span style="font-style:italic;"&gt;elementos&lt;/span&gt;) cuyos elementos serán recogidos por las consultas que realiza la aplicación:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_WQMxntNMWT0/SwQKRX03YyI/AAAAAAAAK1g/H_bJ4HyprLc/s1600/imagen1.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 144px;" src="http://3.bp.blogspot.com/_WQMxntNMWT0/SwQKRX03YyI/AAAAAAAAK1g/H_bJ4HyprLc/s320/imagen1.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5405456746321240866" /&gt;&lt;/a&gt; &lt;br /&gt;El objeto al que se mapean los registros de esta tabla está definido en la siguiente clase:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;package com.roldan.spring.model;&lt;br /&gt;&lt;br /&gt;public class Elemento {&lt;br /&gt; &lt;br /&gt; private int id;&lt;br /&gt; private String descripcion;&lt;br /&gt; private int grupo;&lt;br /&gt; &lt;br /&gt; public int getId() {&lt;br /&gt;  return id;&lt;br /&gt; }&lt;br /&gt; public void setId(int id) {&lt;br /&gt;  this.id = id;&lt;br /&gt; }&lt;br /&gt; public String getDescripcion() {&lt;br /&gt;  return descripcion;&lt;br /&gt; }&lt;br /&gt; public void setDescripcion(String descripcion) {&lt;br /&gt;  this.descripcion = descripcion;&lt;br /&gt; }&lt;br /&gt; public int getGrupo() {&lt;br /&gt;  return grupo;&lt;br /&gt; }&lt;br /&gt; public void setGrupo(int grupo) {&lt;br /&gt;  this.grupo = grupo;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;A continuación se muestra el archivo de configuración de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;spring-config.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xmlns:ehcache="http://www.springmodules.org/schema/ehcache"&lt;br /&gt; xmlns:jdbc="http://www.springmodules.org/schema/jdbc"&lt;br /&gt; xsi:schemaLocation="http://www.springframework.org/schema/beans&lt;br /&gt;  http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&lt;br /&gt;  http://www.springframework.org/schema/jdbc &lt;br /&gt;  http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd&lt;br /&gt;  http://www.springmodules.org/schema/ehcache&lt;br /&gt;  http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd"&amp;gt;&lt;br /&gt; &amp;lt;bean id="datasource"&lt;br /&gt;           class="org.springframework.jdbc.datasource.DriverManagerDataSource"&amp;gt;&lt;br /&gt;  &amp;lt;property name="driverClassName" value="com.mysql.jdbc.Driver"/&amp;gt;&lt;br /&gt;  &amp;lt;property name="url" value="jdbc:mysql://localhost/pruebacache"/&amp;gt;&lt;br /&gt;  &amp;lt;property name="username" value="root"/&amp;gt;&lt;br /&gt;  &amp;lt;property name="password" value="root"/&amp;gt;&lt;br /&gt; &amp;lt;/bean&amp;gt;&lt;br /&gt; &amp;lt;bean id="jdbcTemplate"&lt;br /&gt;            class="org.springframework.jdbc.core.JdbcTemplate"&amp;gt;&lt;br /&gt;  &amp;lt;property name="dataSource" ref="datasource"/&amp;gt;&lt;br /&gt; &amp;lt;/bean&amp;gt;&lt;br /&gt; &amp;lt;bean id="elementoDao" class="com.roldan.spring.dao.ElementoDaoImpl"&amp;gt;&lt;br /&gt;  &amp;lt;property name="jdbcTemplate" ref="jdbcTemplate"/&amp;gt;&lt;br /&gt; &amp;lt;/bean&amp;gt;&lt;br /&gt; &amp;lt;ehcache:config configLocation="classpath:ehcache.xml"/&amp;gt;&lt;br /&gt; &amp;lt;ehcache:proxy id="proxyElementos" refId="elementoDao"&amp;gt;&lt;br /&gt;  &amp;lt;ehcache:caching methodName="get*" cacheName="cacheElementos"/&amp;gt;&lt;br /&gt; &amp;lt;/ehcache:proxy&amp;gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;/pre&gt;&lt;br /&gt;En este archivo se configuran los siguientes beans:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Un datasource sencillo a nuestra base de datos.&lt;/li&gt;&lt;li&gt;Una plantilla de acceso a JDBC de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Un objeto de acceso a datos para recuperar elementos de la base de datos.&lt;/li&gt;&lt;li&gt;Un bean proxy que permite incorporar cacheo en las llamadas al bean DAO.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;En cuanto al los beans &lt;span style="font-style:italic;"&gt;datasource&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;jdbcTemplate&lt;/span&gt;, no hay que hacer más que seguir las instrucciones de configuración de &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;. El bean &lt;span style="font-style:italic;"&gt;elementDao&lt;/span&gt; pertenece a la clase &lt;span style="font-style:italic;"&gt;ElementDaoImpl&lt;/span&gt; que implementa la interfaz &lt;span style="font-style:italic;"&gt;ElementDao&lt;/span&gt;. A continuación vemos la implementación de la clase &lt;span style="font-style:italic;"&gt;ElementDaoImpl&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;package com.roldan.spring.dao;&lt;br /&gt;&lt;br /&gt;import java.sql.ResultSet;&lt;br /&gt;import java.sql.SQLException;&lt;br /&gt;import java.util.ArrayList;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import org.apache.log4j.Logger;&lt;br /&gt;import org.springframework.jdbc.core.JdbcTemplate;&lt;br /&gt;import org.springframework.jdbc.core.RowMapper;&lt;br /&gt;&lt;br /&gt;import com.roldan.spring.Prueba;&lt;br /&gt;import com.roldan.spring.model.Elemento;&lt;br /&gt;&lt;br /&gt;public class ElementoDaoImpl implements ElementoDao {&lt;br /&gt; &lt;br /&gt; private static Logger logger = &lt;br /&gt;  Logger.getLogger(ElementoDaoImpl.class);&lt;br /&gt; &lt;br /&gt; public static final String RECUPERAR_ELEMENTOS = &lt;br /&gt;  "SELECT * FROM ELEMENTO WHERE GRUPO = ?";&lt;br /&gt; public static final String RECUPERAR_TODOS = &lt;br /&gt;  "SELECT * FROM ELEMENTO";&lt;br /&gt; &lt;br /&gt; public List&lt;Elemento&gt; getElements(int grupo) {&lt;br /&gt;  List&lt;Elemento&gt; matches = jdbcTemplate.query(&lt;br /&gt;    RECUPERAR_ELEMENTOS,&lt;br /&gt;    new Object[] {Integer.valueOf(grupo)},&lt;br /&gt;    new RowMapper() {&lt;br /&gt;     public Object mapRow(ResultSet rs, int rowNum) &lt;br /&gt;      throws SQLException {      &lt;br /&gt;      Elemento elemento = new Elemento();&lt;br /&gt;      elemento.setId(rs.getInt(1));&lt;br /&gt;      elemento.setDescripcion(rs.getString(2));&lt;br /&gt;      elemento.setGrupo(rs.getInt(3));&lt;br /&gt;      &lt;br /&gt;      logger.info("Se mapea el elemento " + elemento.getId());&lt;br /&gt;       &lt;br /&gt;      return elemento;&lt;br /&gt;     }&lt;br /&gt;  });  &lt;br /&gt;  return matches;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public List&lt;Elemento&gt; getAllElements() {&lt;br /&gt;  List&lt;Elemento&gt; matches = jdbcTemplate.query(RECUPERAR_TODOS,&lt;br /&gt;    new Object[] {},&lt;br /&gt;    new RowMapper() {&lt;br /&gt;     public Object mapRow(ResultSet rs, int rowNum) &lt;br /&gt;      throws SQLException {&lt;br /&gt;      Elemento elemento = new Elemento();&lt;br /&gt;      elemento.setId(rs.getInt(1));&lt;br /&gt;      elemento.setDescripcion(rs.getString(2));&lt;br /&gt;      elemento.setGrupo(rs.getInt(3));&lt;br /&gt;      &lt;br /&gt;      logger.info("Se mapea el elemento " + elemento.getId());&lt;br /&gt;       &lt;br /&gt;      return elemento;&lt;br /&gt;     }&lt;br /&gt;  });&lt;br /&gt;  &lt;br /&gt;  return matches;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; JdbcTemplate jdbcTemplate;&lt;br /&gt; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {&lt;br /&gt;  this.jdbcTemplate = jdbcTemplate;&lt;br /&gt; }&lt;br /&gt; public JdbcTemplate getJdbcTemplate() {&lt;br /&gt;  return jdbcTemplate;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Tras esto, sólo nos queda revisar la configuración de &lt;span style="font-weight:bold;"&gt;EhCache&lt;/span&gt; en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;, realizada a través del módulo &lt;span style="font-weight:bold;"&gt;spring-modules-cache&lt;/span&gt;. En el archivo &lt;span style="font-style:italic;"&gt;spring-config.xml&lt;/span&gt; vemos que se ha definido que el archivo de configuración de &lt;span style="font-weight:bold;"&gt;EhCache&lt;/span&gt; es &lt;span style="font-style:italic;"&gt;ehcache.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;ehcache&amp;gt;&lt;br /&gt; &amp;lt;defaultCache&lt;br /&gt;  maxElementsInMemory="100"&lt;br /&gt;  eternal="false"&lt;br /&gt;  timeToIdleSeconds="120"&lt;br /&gt;  timeToLiveSeconds="120"&lt;br /&gt;  diskPersistent="false"&lt;br /&gt;  diskExpiryThreadIntervalSeconds="120"&lt;br /&gt;  memoryStoreEvictionPolicy="LFU"/&amp;gt;&lt;br /&gt; &amp;lt;cache name="cacheElementos"&lt;br /&gt;  maxElementsInMemory="100"&lt;br /&gt;  eternal="false"&lt;br /&gt;  timeToIdleSeconds="300"&lt;br /&gt;  timeToLiveSeconds="1"&lt;br /&gt;  memoryStoreEvictionPolicy="LFU"/&amp;gt; &lt;br /&gt;&amp;lt;/ehcache&amp;gt;&lt;/pre&gt;&lt;br /&gt;En este archivo se configura una cache por defecto, que es obligatoria, y una cache para las aplicación. En esta caché se pueden guardar hasta 300 elementos, y cada elemento se corresponde con una llamada a un método con unos determinados parámetros. Si se repiten llamadas al mismo método con los mismos valores de parámetros, el resultado de la llamada estará cacheado y no será necesario ir a la base de datos a recuperarlo.&lt;br /&gt;&lt;br /&gt;Por ejemplo, si ejecutamos la siguiente clase de prueba:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;package com.roldan.spring;&lt;br /&gt;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;import org.springframework.context.ApplicationContext;&lt;br /&gt;import org.springframework.context.support.ClassPathXmlApplicationContext;&lt;br /&gt;&lt;br /&gt;import com.roldan.spring.dao.ElementoDao;&lt;br /&gt;import com.roldan.spring.model.Elemento;&lt;br /&gt;&lt;br /&gt;public class Principal {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) {&lt;br /&gt;  ApplicationContext ctx = &lt;br /&gt;   new ClassPathXmlApplicationContext("spring-config.xml");&lt;br /&gt;&lt;br /&gt;  ElementoDao elementoDao = (ElementoDao) ctx.getBean("proxyElementos");&lt;br /&gt;  &lt;br /&gt;  List&lt;Elemento&gt; elementos = elementoDao.getElements(1);&lt;br /&gt;  for (Elemento elemento : elementos) {&lt;br /&gt;   System.out.println(elemento.getDescripcion());&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  elementos = elementoDao.getAllElements();&lt;br /&gt;  for (Elemento elemento : elementos) {&lt;br /&gt;   System.out.println(elemento.getDescripcion());&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  elementos = elementoDao.getElements(1);&lt;br /&gt;  for (Elemento elemento : elementos) {&lt;br /&gt;   System.out.println(elemento.getDescripcion());&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Se obtienen los siguientes logs:&lt;br /&gt;&lt;pre class="prettyprint"&gt;…&lt;br /&gt;DEBUG - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.roldan.spring.dao.ElementoDaoImpl@2a6f16]&lt;br /&gt;DEBUG - Finished creating instance of bean 'proxyElementos'&lt;br /&gt;DEBUG - Returning cached instance of singleton bean 'proxyElementos'&lt;br /&gt;DEBUG - Attempt to retrieve a cache entry using key &lt;1130820531|30562044&gt; and cache model &lt;org.springmodules.cache.provider.ehcache.EhCacheCachingModel@1c5f743[cacheName='cacheElementos']&gt;&lt;br /&gt;DEBUG - Retrieved cache element &lt;null&gt;&lt;br /&gt;DEBUG - Executing prepared SQL query&lt;br /&gt;DEBUG - Executing prepared SQL statement [SELECT * FROM ELEMENTO WHERE GRUPO = ?]&lt;br /&gt;DEBUG - Fetching JDBC Connection from DataSource&lt;br /&gt;DEBUG - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost/pruebacache]&lt;br /&gt;INFO  - Se mapea el elemento 1&lt;br /&gt;INFO  - Se mapea el elemento 3&lt;br /&gt;DEBUG - Returning JDBC Connection to DataSource&lt;br /&gt;DEBUG - Attempt to store the object &lt;[com.roldan.spring.model.Elemento@7109c4, com.roldan.spring.model.Elemento@1385660]&gt; in the cache using key &lt;1130820531|30562044&gt; and model &lt;org.springmodules.cache.provider.ehcache.EhCacheCachingModel@1c5f743[cacheName='cacheElementos']&gt;&lt;br /&gt;DEBUG - Object was successfully stored in the cache&lt;br /&gt;Primer elemento&lt;br /&gt;Tercer elemento&lt;br /&gt;DEBUG - Attempt to retrieve a cache entry using key &lt;23191881|23191477&gt; and cache model &lt;org.springmodules.cache.provider.ehcache.EhCacheCachingModel@1c5f743[cacheName='cacheElementos']&gt;&lt;br /&gt;DEBUG - Retrieved cache element &lt;null&gt;&lt;br /&gt;DEBUG - Executing prepared SQL query&lt;br /&gt;DEBUG - Executing prepared SQL statement [SELECT * FROM ELEMENTO]&lt;br /&gt;DEBUG - Fetching JDBC Connection from DataSource&lt;br /&gt;DEBUG - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost/pruebacache]&lt;br /&gt;INFO  - Se mapea el elemento 1&lt;br /&gt;INFO  - Se mapea el elemento 2&lt;br /&gt;INFO  - Se mapea el elemento 3&lt;br /&gt;INFO  - Se mapea el elemento 4&lt;br /&gt;DEBUG - Returning JDBC Connection to DataSource&lt;br /&gt;DEBUG - Attempt to store the object &lt;[com.roldan.spring.model.Elemento@4ecfdd, com.roldan.spring.model.Elemento@30d82d, com.roldan.spring.model.Elemento@c09554, com.roldan.spring.model.Elemento@18bf072]&gt; in the cache using key &lt;23191881|23191477&gt; and model &lt;org.springmodules.cache.provider.ehcache.EhCacheCachingModel@1c5f743[cacheName='cacheElementos']&gt;&lt;br /&gt;DEBUG - Object was successfully stored in the cache&lt;br /&gt;Primer elemento&lt;br /&gt;Segundo elemento&lt;br /&gt;Tercer elemento&lt;br /&gt;Cuarto elemento&lt;br /&gt;DEBUG - Attempt to retrieve a cache entry using key &lt;1130820531|30562044&gt; and cache model &lt;org.springmodules.cache.provider.ehcache.EhCacheCachingModel@1c5f743[cacheName='cacheElementos']&gt;&lt;br /&gt;DEBUG - Retrieved cache element &lt;[com.roldan.spring.model.Elemento@7109c4, com.roldan.spring.model.Elemento@1385660]&gt;&lt;br /&gt;Primer elemento&lt;br /&gt;Tercer elemento&lt;/pre&gt;&lt;br /&gt;Se pueden apreciar los siguientes pasos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;En la primera llamada se buscan todos los elementos que pertenecen al grupo 1. La llamada pasa por el proxy, que trata de buscar el resultado de esta llamada en la cache y, como no lo encuentra, acude a base de datos.&lt;/li&gt;&lt;li&gt;En la segunda llamada se buscan todos los elementos. Esta llamada también pasa por el proxy, que trata de buscar el resultado de esta llamada en la cache y, como no lo encuentra, acude a base de datos.&lt;/li&gt;&lt;li&gt;En la tercera llamada se buscan de nuevo todos los elementos que pertenecen al grupo 1. Al pasar por el proxy, éste reconoce que el resultado de la llamada está en la caché y que no hace falta acudir a la base de datos, ahorrándose la consulta.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Con esto, tenemos ya un ejemplo de cómo utilizar una cache en las consultas a base de datos en &lt;span style="font-weight:bold;"&gt;Spring&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.dosideas.com/wiki/EhCache_Con_Spring"&gt;http://www.dosideas.com/wiki/EhCache_Con_Spring&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-6548847399708424531?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/6548847399708424531/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/configuracion-de-ehcache-en-spring.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6548847399708424531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6548847399708424531'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/configuracion-de-ehcache-en-spring.html' title='Configuración de EhCache en Spring'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_WQMxntNMWT0/SwQKRX03YyI/AAAAAAAAK1g/H_bJ4HyprLc/s72-c/imagen1.bmp' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-5841673198255713573</id><published>2009-11-12T22:11:00.009+01:00</published><updated>2011-10-27T10:11:33.213+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ingeniería del software'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><category scheme='http://www.blogger.com/atom/ns#' term='Calidad'/><title type='text'>La Deuda Técnica</title><content type='html'>¿Quién no se ha encontrado en el siguiente dilema? Tenemos que añadir una nueva funcionalidad al sistema y tenemos prisa. Podemos hacerlo rápido y de forma no óptima, más enrevesado o menos eficiente, satisfaciendo las exigencias de entrega. O podemos (si es que podemos…) saltarnos estas exigencias y sentarnos a pensar y hacerlo mejor, con diseño más claro y mantenible.&lt;br /&gt;&lt;br /&gt;La &lt;span style="font-weight:bold;"&gt;Deuda Técnica&lt;/span&gt; es una metáfora ideada por &lt;span style="font-weight:bold;"&gt;Ward Cunningham&lt;/span&gt; que ayuda a pensar sobre este problema. Viene a decir que en caso de hacer las cosas rápido y de manera chapucera se incurre en una “deuda” que vamos a tener que pagar en el futuro, en forma de esfuerzo de desarrollo, como consecuencia de postergar el buen diseño en la implementación. Y a medida que se siga postergando este esfuerzo y el desarrollo deficiente se siga recubriendo con nuevos desarrollos que lo enmascaren o lo usen, esta deuda será cada vez más elevada y difícil de pagar.&lt;br /&gt;&lt;br /&gt;No se quiere decir que no sea sensato incurrir en esta deuda. En ciertas ocasiones es una decisión acertada asumir esta deuda para resolver una situación determinada en un proyecto. Sin embargo, hay que tener en cuenta las repercusiones que puede tomar en el futuro y hay que tratar de satisfacer esta deuda cuanto antes para evitar que crezca desmesuradamente, es decir, que un mal planteamiento en una funcionalidad de la aplicación comprometa la buena marcha del proyecto en el futuro.&lt;br /&gt;&lt;br /&gt;Sobre esta idea, &lt;span style="font-weight:bold;"&gt;Martin Fowler&lt;/span&gt; ha desarrollado el “&lt;span style="font-weight:bold;"&gt;Cuadrante de la Deuda Técnica&lt;/span&gt;”. Según él, una deuda técnica asumida en un proyecto puede clasificarse de dos formas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Prudente&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;imprudente&lt;/span&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Advertida&lt;/span&gt; o &lt;span style="font-weight:bold;"&gt;inadvertida&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;La combinación de estas clasificaciones produce cuatro situaciones distintas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Deuda prudente y advertida&lt;/span&gt;: Se produce cuando somos conscientes de que estamos asumiendo un mal diseño para salir de una situación puntual, como una entrega. Posteriormente se debe evaluar la conveniencia de “pagar la deuda técnica” solucionando esta carencia en función del interés que acarree.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Deuda prudente e inadvertida&lt;/span&gt;: Se produce cuando, con el paso del tiempo, se descubren cómo se deberían haber hecho las cosas. Inevitable, ya que según avanza el proyecto, se aprende de él. Llegado el momento, también se debe evaluar si resulta interesante mejorar el diseño con lo que hemos aprendido o si esto implicaría un esfuerzo demasiado alto.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Deuda imprudente y advertida&lt;/span&gt;: Se deshecha el diseño porque se pretende acelerar el desarrollo. Según la “Hipótesis de Resistencia al Diseño”, esto se puede lograr hasta un punto determinado del proyecto en el que deja de ser posible conseguir un beneficio de obviar el diseño porque la calidad del código se degrada.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Deuda imprudente e inadvertida&lt;/span&gt;: No se conocen las técnicas de diseño ni se es consciente de que se están tomando decisiones incorrectas.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Conviene saber en qué situación nos encontramos. Si bien las tres primeras situaciones se pueden asumir en un momento determinado dentro de un proyecto, la última resulta mucho más peligrosa, porque implica no saber hacia dónde se dirige el proyecto. &lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/bliki/TechnicalDebt.html"&gt;La Deuda Técnica&lt;/a&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/bliki/TechnicalDebtQuadrant.html"&gt;El Cuadrante de la Deuda Técnica&lt;/a&gt;&lt;br /&gt;&lt;a href="http://martinfowler.com/bliki/DesignStaminaHypothesis.html"&gt;La Hipótesis de Resistencia al Diseño&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-5841673198255713573?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/5841673198255713573/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/la-deuda-tecnica.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5841673198255713573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/5841673198255713573'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/la-deuda-tecnica.html' title='La Deuda Técnica'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-1888784612762093694</id><published>2009-11-06T12:24:00.006+01:00</published><updated>2009-11-06T12:46:19.628+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pruebas'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Calidad'/><title type='text'>EclEmma: Visualizar la cobertura de los tests unitarios en Eclipse</title><content type='html'>Hace algún tiempo publiqué un post sobre &lt;a href="http://tratandodeentenderlo.blogspot.com/2009/10/herramientas-de-analisis-de-calidad-del.html"&gt;herramientas de calidad del código&lt;/a&gt;. A las que yo publiqué, Dirty Affairs añadió otra, &lt;span style="font-weight:bold;"&gt;EclEmma&lt;/span&gt;, a la cual he estado echando un vistazo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EclEmma&lt;/span&gt; es una herramienta para &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt; que permite visualizar la cobertura del código de los tests unitarios que hemos hecho. Existen otras herramientas como &lt;span style="font-weight:bold;"&gt;Cobertura&lt;/span&gt;, que generan informes, pero que no permiten visualizar esta informacuón de forma gráfica directamente en &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;EclEmma&lt;/span&gt; se instala en &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt; de forma sencilla, desde &lt;span style="font-style:italic;"&gt;Help -&gt; Software Updates -&gt; Available Software -&gt; Add Site&lt;/span&gt;, se añade el sitio &lt;a href="http://update.eclemma.org/"&gt;http://update.eclemma.org/&lt;/a&gt; y pasamos a realizar la instalación del plugin.&lt;br /&gt;&lt;br /&gt;Una vez instalado el plugin y reiniciado &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt;, aparece una nueva opción en la barra de herramientas:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/SvQIUMPh04I/AAAAAAAAKzk/aJz5U7NE4HU/s1600-h/dibujo1.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 72px; height: 49px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/SvQIUMPh04I/AAAAAAAAKzk/aJz5U7NE4HU/s320/dibujo1.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5400950996100830082" /&gt;&lt;/a&gt;&lt;br /&gt;A través de este botón, podemos lanzar los tests de forma que &lt;span style="font-weight:bold;"&gt;EclEmma&lt;/span&gt; analizará qué parte del código se está cubriendo en ellos. Veamos un ejemplo práctico.&lt;br /&gt;&lt;br /&gt;He creado una clase &lt;span style="font-style:italic;"&gt;OperadorAritmético&lt;/span&gt;, que realiza las operaciones de &lt;span style="font-style:italic;"&gt;suma&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;division&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.tests;&lt;br /&gt; &lt;br /&gt; public class OperadorAritmetico {&lt;br /&gt; &lt;br /&gt; public static int suma(int a, int b) {&lt;br /&gt;  return a + b;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static int division(int a, int b) throws Exception {&lt;br /&gt;  if(b==0) {&lt;br /&gt;   throw new Exception();&lt;br /&gt;  }  &lt;br /&gt;  return a / b;&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Para probar esta clase he creado una clase de test que, en principio, solo prueba la &lt;span style="font-style:italic;"&gt;suma&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;package com.roldan.tests;&lt;br /&gt;&lt;br /&gt;import org.junit.Assert;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;&lt;br /&gt; public class OperadorAritmeticoTest {&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void suma() {&lt;br /&gt;  &lt;br /&gt;  int a = 5;&lt;br /&gt;  int b = 3;&lt;br /&gt;  &lt;br /&gt;  int suma = OperadorAritmetico.suma(a, b);&lt;br /&gt;  &lt;br /&gt;  Assert.assertEquals(8, suma);&lt;br /&gt; } &lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Ahora lanzamos las pruebas para el proyecto, sitándonos en la raíz del proyecto y yendo al botón de &lt;span style="font-weight:bold;"&gt;EclEmma&lt;/span&gt; antes mostrado, seleccionamos la opción &lt;span style="font-style:italic;"&gt;Coverage as -&gt; JUnit Test&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/SvQJeGTZvOI/AAAAAAAAKzs/9Up03R4RZZA/s1600-h/dibujo2.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 232px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/SvQJeGTZvOI/AAAAAAAAKzs/9Up03R4RZZA/s320/dibujo2.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5400952265816784098" /&gt;&lt;/a&gt;&lt;br /&gt;Vemos como las instrucciones de la clase &lt;span style="font-style:italic;"&gt;OperadorAritmetico&lt;/span&gt; has sido coloreadas, con verde aquellas que han sido cubiertas en las pruebas y con rojo aquellas que no. La pestaña &lt;span style="font-style:italic;"&gt;Coverage&lt;/span&gt; muestra el informe de cobertura del proyecto.&lt;br /&gt;&lt;br /&gt;Ahora queremos arreglar un poco esta situación y hacer un prueba para la división:&lt;br /&gt;&lt;pre class="prettyprint java"&gt;@Test&lt;br /&gt;public void division() {&lt;br /&gt;  &lt;br /&gt; int a = 8;&lt;br /&gt; int b = 4;&lt;br /&gt;&lt;br /&gt; int division;&lt;br /&gt; try {&lt;br /&gt;  division = OperadorAritmetico.division(a, b);&lt;br /&gt;  Assert.assertEquals(2, division);&lt;br /&gt; } catch (Exception e) {&lt;br /&gt;  Assert.fail();&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Si ahora volvemos a realizar las pruebas, vemos que la situación se ha mejorado, aunque todavía queda código sin cubrir:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/SvQJ-QBkHhI/AAAAAAAAKz0/kPrlpzACTlQ/s1600-h/dibujo3.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 232px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/SvQJ-QBkHhI/AAAAAAAAKz0/kPrlpzACTlQ/s320/dibujo3.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5400952818182135314" /&gt;&lt;/a&gt;&lt;br /&gt; De esta forma, podemos ir mejorando progresivamente la cobertura de las pruebas para asegurar el buen funcionamiento de nuestro código.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2009/10/herramientas-de-analisis-de-calidad-del.html"&gt;http://tratandodeentenderlo.blogspot.com/2009/10/herramientas-de-analisis-de-calidad-del.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.eclemma.org/"&gt;http://www.eclemma.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://cobertura.sourceforge.net/"&gt;http://cobertura.sourceforge.net/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-1888784612762093694?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/1888784612762093694/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/visualizar-la-cobertura-de-los-tests.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1888784612762093694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/1888784612762093694'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/visualizar-la-cobertura-de-los-tests.html' title='EclEmma: Visualizar la cobertura de los tests unitarios en Eclipse'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_WQMxntNMWT0/SvQIUMPh04I/AAAAAAAAKzk/aJz5U7NE4HU/s72-c/dibujo1.bmp' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-2159997284852047784</id><published>2009-11-05T15:06:00.018+01:00</published><updated>2011-08-03T10:07:27.681+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Lecturas anteriores</title><content type='html'>En esta entrada simplemente se listan los libros que he leído y que vaya leyendo, por tanto, estará en constante actualización.&lt;br /&gt;&lt;br /&gt;También espero que sirva para recibir recomendaciones sobre estos libros o sobre otros que puedan resultar interesantes.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;The Agile Samurai&lt;/span&gt; (Jonathan Rasmusson)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;The Pragmatic Programmer&lt;/span&gt; (Andrew Hunt, David Thomas)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Becoming agile in an imperfect world&lt;/span&gt; (Greg Smith, Ahmed Sidky)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Peopleware: Productive Projects and Teams (Second Edition)&lt;/span&gt; (Tom de Marco, Timothy Lister)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2011/06/apuntes-de-xp.html"&gt;Extreme Programming Explained: Embrace Change&lt;/a&gt;&lt;/span&gt; (Kent Beck)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Design Patterns&lt;/span&gt; (Erich Gamma, Richard Helm, Ralph Johnson, Hohn Vlissides)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Implementation Patterns&lt;/span&gt; (Kent Beck)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2011/03/mythical-man-month.html"&gt;The Mythical Man-Month: Essays on Software Engineering, Anniversary Edition (2nd Edition)&lt;/a&gt;&lt;/span&gt; (Frederick P. Brooks)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2011/01/clean-code.html"&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/a&gt;&lt;/span&gt; (Robet C. Martin)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Diseño Ágil con TDD&lt;/span&gt; (Carlos Blé Jurado, Juan Gutiérrez Plaza, Fran Reyes Perdomo y Gregorio Mena)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Ingeniería del software - Un enfoque práctico&lt;/span&gt; (Roger Pressman)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/07/kanban-y-scrum-obteniendo-lo-mejor-de.html"&gt;Kanban vs Scrum – a practical guide&lt;/a&gt;&lt;/span&gt; (Henrik Kniberg y Mattias Skarin)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/06/scrum-y-xp-desde-las-trincheras.html"&gt;Scrum and XP from the trenches&lt;/a&gt;&lt;/span&gt; (Henrik Kniberg)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2010/04/uml2.html"&gt;UML 2&lt;/a&gt;&lt;/span&gt; (Ila Neustadt, Jim Arlow)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2009/12/spring-in-action-second-edition.html"&gt;Spring in Action&lt;/a&gt;&lt;/span&gt; (Craig Walls)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;&lt;a href="http://tratandodeentenderlo.blogspot.com/2009/12/hibernate-in-action-second-edition.html"&gt;Java Persistence with Hibernate&lt;/a&gt;&lt;/span&gt; (Christian Bauer, Gavin King)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;J2EE Development without EJB&lt;/span&gt; (Rod Johnson)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Version Control with Subversion&lt;/span&gt; (Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Maven - The definitive guide&lt;/span&gt; (Sonatype)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;J2EE Design &amp; Development&lt;/span&gt; (Rod Johnson)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Jakarta Struts&lt;/span&gt; (Chuck Cavaness)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Java &amp; XML&lt;/span&gt; (Brett McLaughlin)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Professional Java Server Programming J2EE, 1.3 Edition&lt;/span&gt; (Subrahmanyam Allamaraju, Cedric Beust, Marc Wilcox, Sameer Tyagi, Rod Johnson, Gary Watson, Alan Williamson, John Davies, Ramesh Nagappan, Andy Longshaw, P. G. Sarang, Tyler Jewell, Alex Toussaint)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-2159997284852047784?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/2159997284852047784/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/lecturas-anteriores_05.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2159997284852047784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/2159997284852047784'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/lecturas-anteriores_05.html' title='Lecturas anteriores'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-7749413405348942734</id><published>2009-11-03T10:33:00.021+01:00</published><updated>2011-06-13T23:26:41.054+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Libros'/><title type='text'>Próximas lecturas</title><content type='html'>Esta entrada no es más que una declaración de intenciones, una recopilación de los libros que tengo previsto leer proximamente. Por tanto, estará en constante actualización.&lt;br /&gt;&lt;br /&gt;También espero que sirva para recibir recomendaciones sobre estos libros o sobre otros que puedan resultar interesantes.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Growing Object-Oriented Software Guided by Tests&lt;/span&gt; (Steve Freeman, Nat Pryce)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Patterns of Enterprise Application Architecture&lt;/span&gt; (David Fowler)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Head First Design Patterns&lt;/span&gt; (Eric T Freeman, Elisabeth Robson, Bert Bates, Kathy Sierra)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-7749413405348942734?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/7749413405348942734/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/proximas-lecturas.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/7749413405348942734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/7749413405348942734'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/11/proximas-lecturas.html' title='Próximas lecturas'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-6706444663402015121</id><published>2009-10-30T12:45:00.003+01:00</published><updated>2009-10-30T12:58:08.260+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bases de datos'/><category scheme='http://www.blogger.com/atom/ns#' term='Pruebas'/><title type='text'>Pruebas de base de datos con DbUnit</title><content type='html'>Cuando se desarrollan aplicaciones que acceden a una base de datos, es conveniente verificar que los datos se están manipulando de forma correcta. Para ello, es necesario hacer pruebas sobre el código que realiza esta manipulaciones de datos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JUnit&lt;/span&gt; es un framework que nos ayuda a la hora de hacer pruebas en nuestra aplicación. Además, también podemos usar &lt;span style="font-weight:bold;"&gt;DbUnit&lt;/span&gt;, que es una extensión de &lt;span style="font-weight:bold;"&gt;JUnit&lt;/span&gt; que permite llevar la base de datos a un estado definido antes de cada prueba y que proporciona clases que nos ayudan a realizar pruebas sobre el contenido de una base de datos. &lt;br /&gt;&lt;br /&gt;DbUnit permite importar y exportar el contenido de la base de datos a ficheros xml.  Por ejemplo, la tabla &lt;span style="font-style:italic;"&gt;PROFESORES&lt;/span&gt; se define de la siguiente forma:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/SurSVsCm5QI/AAAAAAAAKzc/jyQwiEc3svY/s1600-h/imagen1.bmp"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 72px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/SurSVsCm5QI/AAAAAAAAKzc/jyQwiEc3svY/s320/imagen1.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5398358373398144258" /&gt;&lt;/a&gt;&lt;br /&gt;Un registro en la tabla &lt;span style="font-style:italic;"&gt;PROFESORES&lt;/span&gt;, se expresaría en xml como:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;profesores PROFESOR_ID="3" NOMBRE="nombre_profesor"/&amp;gt;&lt;/pre&gt;&lt;br /&gt;Se puede apreciar que el nombre del elemento es el nombre de la tabla y los distintos atributos son los campos de la tabla y su valor para este registro.&lt;br /&gt;&lt;br /&gt;Mediante registros de este tipo se pueden generar distintos conjuntos de datos (datasets) en ficheros xml, que pueden servir como semillas para probar el código que accede a la base de datos en situaciones adecuadas para cada prueba.&lt;br /&gt;&lt;br /&gt;Vamos a ver como exportar un esquema completo de la base de datos utilizando &lt;span style="font-weight:bold;"&gt;DbUnit&lt;/span&gt;. En primer lugar, se debe obtener una conexión a la base de datos. Se puede hacer de la siguiente forma:&lt;br /&gt;&lt;pre class="prettyprint"&gt;Class.forName("com.mysql.jdbc.Driver");&lt;br /&gt;Connection jdbcConnection = &lt;br /&gt; DriverManager.getConnection(&lt;br /&gt;  "jdbc:mysql://localhost/bdprueba", &lt;br /&gt;  "user", &lt;br /&gt;  "pwd");&lt;br /&gt;IDatabaseConnection connection = &lt;br /&gt; new DatabaseConnection(jdbcConnection);&lt;/pre&gt;&lt;br /&gt;Posteriormente pasamos a exportar los datos que hay actualmente en la base de datos. Al exportar hay que tener en cuenta el orden de las tablas ya que se podría romper la integridad referencial que existe entre ellas. Para ello se crea un dataset al que se añaden las tablas de forma ordenada, que se pueden obtener a partir de un &lt;span style="font-style:italic;"&gt;DatabaseSequenceFilter&lt;/span&gt;: &lt;br /&gt;&lt;pre class="prettyprint"&gt;DatabaseSequenceFilter filter = &lt;br /&gt; new DatabaseSequenceFilter(connection);&lt;br /&gt;IDataSet datasetAll = &lt;br /&gt; new FilteredDataSet(&lt;br /&gt;  filter, &lt;br /&gt;  connection.createDataSet());&lt;br /&gt;QueryDataSet partialDataSet = &lt;br /&gt; new QueryDataSet(connection);&lt;br /&gt;&lt;br /&gt;String[] listTableNames = &lt;br /&gt; filter.getTableNames(datasetAll);&lt;br /&gt;for (int i = 0; i &lt; listTableNames.length; i++) {&lt;br /&gt; final String tableName = listTableNames[i];&lt;br /&gt; partialDataSet.addTable(tableName);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Ahora se exportaría este dataset a un archivo xml:&lt;br /&gt;&lt;pre class="prettyprint"&gt;FlatXmlDataSet.write(partialDataSet,&lt;br /&gt; new FileOutputStream("dataset.xml"));&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;?xml version='1.0' encoding='UTF-8'?&amp;lt;&lt;br /&gt;&amp;lt;dataset&amp;gt;&lt;br /&gt;  &amp;lt;academias/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="1" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="3" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="4" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="6" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="8" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="9" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="10" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;estilos ESTILO_ID="12" NOMBRE="nombre_estilo"&lt;br /&gt;   DESCRIPCION="descripcion_estilo"/&amp;gt;&lt;br /&gt;  &amp;lt;clases/&amp;gt;&lt;br /&gt;  &amp;lt;academia_clase/&amp;gt;&lt;br /&gt;  &amp;lt;profesores PROFESOR_ID="3" NOMBRE="nombre_profesor"/&amp;gt;&lt;br /&gt;  &amp;lt;profesores PROFESOR_ID="6" NOMBRE="nombre_profesor"/&amp;gt;&lt;br /&gt;  &amp;lt;profesores PROFESOR_ID="9" NOMBRE="nombre_profesor"/&amp;gt;&lt;br /&gt;  &amp;lt;profesores PROFESOR_ID="12" NOMBRE="nombre_profesor"/&amp;gt;&lt;br /&gt;  &amp;lt;clase_profesor/&amp;gt;&lt;br /&gt;  &amp;lt;profesor_estilo PROFESOR_ID="3" ESTILO_ID="3"/&amp;gt;&lt;br /&gt;  &amp;lt;profesor_estilo PROFESOR_ID="6" ESTILO_ID="6"/&amp;gt;&lt;br /&gt;  &amp;lt;profesor_estilo PROFESOR_ID="9" ESTILO_ID="9"/&amp;gt;&lt;br /&gt;  &amp;lt;profesor_estilo PROFESOR_ID="12" ESTILO_ID="12"/&amp;gt;&lt;br /&gt;&amp;lt;/dataset&amp;gt;&lt;/pre&gt;&lt;br /&gt;Tras esto se ha obtenido un dataset que puede ser usado como semilla para una prueba.&lt;br /&gt;&lt;br /&gt;A la hora de hacer pruebas, &lt;span style="font-weight:bold;"&gt;DbUnit&lt;/span&gt; proporciona la clase &lt;span style="font-style:italic;"&gt;DatabaseTestCase&lt;/span&gt;, que sirve como clase base para las pruebas. Esta clase tiene algunos métodos que debemos sobreescribir. El método &lt;span style="font-style:italic;"&gt;getConnection()&lt;/span&gt; proporciona la conexión a la base de datos, de forma similar a como hemos visto antes:&lt;br /&gt;&lt;pre class="prettyprint"&gt;protected IDatabaseConnection getConnection() &lt;br /&gt; throws Exception {&lt;br /&gt;  &lt;br /&gt; Class driverClass = &lt;br /&gt;  Class.forName("org.gjt.mm.mysql.Driver");&lt;br /&gt;&lt;br /&gt; Connection jdbcConnection = &lt;br /&gt;  DriverManager.getConnection(&lt;br /&gt;   "jdbc:mysql://localhost/bdprueba", &lt;br /&gt;   "user", &lt;br /&gt;   "pwd");&lt;br /&gt;        &lt;br /&gt; return new DatabaseConnection(jdbcConnection);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;El método &lt;span style="font-style:italic;"&gt;getDataSet()&lt;/span&gt; proporciona un dataset que sería la semilla para la prueba que vamos a ejecutar:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;protected IDataSet getDataSet() throws Exception {&lt;br /&gt;   return new FlatXmlDataSet(&lt;br /&gt;      new FileInputStream("dataset.xml "));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Los métodos &lt;span style="font-style:italic;"&gt;getSetUpOperation()&lt;/span&gt; y &lt;span style="font-style:italic;"&gt;getTearDownOperation()&lt;/span&gt; indican lo que debe hacer cada método antes y después de cada prueba. Antes de cada prueba vamos a limpiar la base de datos y a volver a dejarla en el estado que proporciona el dataset que hemos exportado anteriormente, y después de cada prueba no haremos nada:&lt;br /&gt;&lt;pre class="prettyprint"&gt;protected DatabaseOperation getSetUpOperation() &lt;br /&gt; throws Exception {&lt;br /&gt; return DatabaseOperation.CLEAN_INSERT;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;protected DatabaseOperation getTearDownOperation() &lt;br /&gt; throws Exception {&lt;br /&gt; return DatabaseOperation.NONE;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Tras esto, podemos escribir nuestros casos de prueba en la clase que extiende de &lt;span style="font-style:italic;"&gt;DatabaseTestCase&lt;/span&gt;, sabiendo que las pruebas partirán de un estado definido. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias&lt;/span&gt;:&lt;br /&gt;&lt;a href="http://dbunit.sourceforge.net/index.html"&gt;http://dbunit.sourceforge.net/index.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=DBUnitEI"&gt;http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=DBUnitEI&lt;/a&gt;&lt;br /&gt;&lt;a href="http://onjava.com/pub/a/onjava/2004/01/21/dbunit.html"&gt;http://onjava.com/pub/a/onjava/2004/01/21/dbunit.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.oreillynet.com/onjava/blog/2005/10/dbunit_made_easy.html"&gt;http://www.oreillynet.com/onjava/blog/2005/10/dbunit_made_easy.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-6706444663402015121?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/6706444663402015121/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/pruebas-de-base-de-datos-con-dbunit.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6706444663402015121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6706444663402015121'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/pruebas-de-base-de-datos-con-dbunit.html' title='Pruebas de base de datos con DbUnit'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_WQMxntNMWT0/SurSVsCm5QI/AAAAAAAAKzc/jyQwiEc3svY/s72-c/imagen1.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-3873667815333408099</id><published>2009-10-26T10:40:00.009+01:00</published><updated>2009-10-29T14:58:52.237+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><category scheme='http://www.blogger.com/atom/ns#' term='Integración continua'/><category scheme='http://www.blogger.com/atom/ns#' term='Control de versiones'/><title type='text'>Agile Open Spain</title><content type='html'>Los días 23 y 24 de Octubre se ha celebrado en la Escuela Universitaria de Informática del Campus Sur de la Universidad Politécnica de Madrid el &lt;span style="font-weight:bold;"&gt;Agile Open Spain&lt;/span&gt;, organizado por Agile Spain.&lt;br /&gt;&lt;br /&gt;El &lt;span style="font-weight:bold;"&gt;Agile Open Spain&lt;/span&gt; tenía como objetivo la difusión de la &lt;span style="font-weight:bold;"&gt;metodologías ágiles&lt;/span&gt; en España, compartiendo experiencias entre todos los participantes. Se ha desarrollado basándose en el formato Open Space. &lt;br /&gt;&lt;br /&gt;La tarde del viernes 23, tras la introducción al evento por parte de la organización, cualquier participante pudo presentar los temas que más interés tenían para él. Tras votación por parte de los asistentes, se seleccionaron los más votados para confeccionar el horario de charlas para el día siguiente, en el que se establecieron 5 turnos de charlas con 6 charlas distintas en cada uno para escoger.&lt;br /&gt;&lt;br /&gt;Voy a comentar las charlas en las que yo estuve, que, desgraciadamente, no fueron todas las que me habría gustado estar.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Integración continua&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La integración contínua fue el tema de la primera charla a la que asistí. Fue conducida por Juan Gutiérrez y en ella se habló de lo que es la integración continua, presentándola como un proceso continuo de integración del trabajo que se lleva a cabo dentro de un proyecto, que aglutina una serie de buenas prácticas y que está apoyado por una serie de herramientas que permiten automatizarlo.&lt;br /&gt;&lt;br /&gt;Algunos asistentes hablaron de sus experiencias con la integración continua en sus proyectos y se llego a exponer el sistema de integración contínua con que uno de los asistentes trabajaba.&lt;br /&gt;&lt;br /&gt;Se recalcó la idea de que el principio de la integración es el control de versiones (CVS, Subversion, Git, …) y las herramientas de construcción automática (Ant, Maven…) y que, a partir de ahí, existen un montón de herramientas que contribuyen a la automatización de las distintas pruebas (Junit, DBUnit, Selenium…). Y todo esto, orquestado por el servidor de integración continua (Hudson, Bamboo…).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Control de versiones&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En la siguiente sesión se habló sobre el control de versiones en los proyectos, estableciendo la necesidad de establecer una política de ramas bien definida, para lo que se presentaron varias estrategias.&lt;br /&gt;&lt;br /&gt;El conductor, Jose Luis Soria, presentó la serie de tareas necesarias para establecer una política de ramas:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Establecer el modelo de aislamiento: sobre qué rama se realiza un nuevo cambio.&lt;/li&gt;&lt;li&gt;Establecer listas de promoción: definir qué ramas pueden hacer merge a cuáles.&lt;/li&gt;&lt;li&gt;Criterios de calidad.&lt;/li&gt;&lt;li&gt;Establecer un responsable de cada rama, que se encargará de que se mantenga estable.&lt;/li&gt;&lt;li&gt;Establecer permisos.&lt;/li&gt;&lt;li&gt;Estrategia de testeo y construcción automatizada.&lt;/li&gt;&lt;/ol&gt; &lt;br /&gt;Hubo también algún firme impulsor de Git, presentándolo como una alternativa superior a CVS o Subversion, así que habrá que echarle un vistazo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Agilismo de guerrilla&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;En esta charla, conducida por Xavi Gost, se habló sobre cómo intruducir el agilismo en una organización. La idea principal que se me quedó es no esperar que vengan de arriba a ofrecértelo, sino ir introduciendo técnicas ágiles en la medida de lo posible en los proyectos.&lt;br /&gt;&lt;br /&gt;También se habló sobre la resistencia al cambio por parte de la gente. Resistencia, sobre todo, a los grandes cambios. Por el contrario, si se introducen los cambios de forma disimulada, la gente los adopta sin el miedo que supone presentar a un grupo una nueva metodología o conjunto de prácticas de golpe.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Kanban&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Como dijo Xabier Quesada en la presentación, Scrum ha muerto y ahora lo que se lleva es Kanban. Como luego él mismo matizó, esto no es así, puesto que Kanban es algo que todavía se está definiendo. &lt;br /&gt;&lt;br /&gt;Xabier, junto con Robin Diamond, nos presentaron Kanban, una nueva metodología basada en Lean. Los principios de Kanban son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Limitar el trabajo en progreso, todo trabajo empzado y no terminado, puesto que está costando dinero.&lt;/li&gt;&lt;li&gt;Establecer un flujo continuo de trabajo, que entra por un lado y fluye hasta el final de la cadena de producción.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;En la charla contruyeron un tablero Kanban que sirvió para hacernos una idea visual de su funcionamiento.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Historias de usuario&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Sesión conducida por Jose Luis Soria, Rodrigo Corral y otro asistente más cuyo nombre no recuerdo :-(. En esta charla se habló de la documentación en los proyectos.&lt;br /&gt;&lt;br /&gt;La idea principal sería la de hacer simplemente la documentación que aporte valor al proyecto, bien para el desarrollador o para el usuario, y resistirse a documentar por documentar creando tochos que nadie lee ni actualiza y se quedan obsoletos de forma inmediata.&lt;br /&gt;&lt;br /&gt;Se habló mucho de las historias de usuario, representación de un requerimiento a través de una sencilla descripción de la conversación mantenida con un usuario y sus condiciones de aceptación. Una historia de usuario debe tener las siguientes características:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Independente&lt;/li&gt;&lt;li&gt;Que aporte valor&lt;/li&gt;&lt;li&gt;Estimable&lt;/li&gt;&lt;li&gt;Negociable&lt;/li&gt;&lt;li&gt;Testable&lt;/li&gt;&lt;li&gt;Pequeña&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;De todas las charlas me marché con la sensación de haber aprendido bastante. No siempre tienes la oportunidad de tener delante gente que puede hablar sobre su experiencia en temas en los que tú estás empezando a introducirte.&lt;br /&gt;&lt;br /&gt;La pena, no haber podido asistir a otras charlas que también me interesaban. Pero el tener que elegir hace que a las que vayas, lo hagas con el mayor interés.&lt;br /&gt;&lt;br /&gt;Un saludo a la organización del &lt;span style="font-weight:bold;"&gt;Agile Open Spain&lt;/span&gt; y a todos sus participantes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-3873667815333408099?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/3873667815333408099/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/agile-open-space.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3873667815333408099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3873667815333408099'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/agile-open-space.html' title='Agile Open Spain'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-4050584669856284798</id><published>2009-10-20T14:27:00.006+02:00</published><updated>2010-06-08T09:59:36.616+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='General'/><title type='text'>Licencias de Software</title><content type='html'>Según la &lt;a href="http://es.wikipedia.org/wiki/Licencia_de_software"&gt;Wikipedia&lt;/a&gt;, “&lt;span style="font-style:italic;"&gt;una &lt;span style="font-weight:bold;"&gt;licencia de software&lt;/span&gt; es un contrato entre el licenciante (autor/titular de los derechos de explotación/distribuidor) y el licenciatario del programa informático (usuario consumidor /usuario profesional o empresa), para utilizar el software cumpliendo una serie de términos y condiciones establecidas dentro de sus cláusulas.&lt;/span&gt;”&lt;br /&gt;&lt;br /&gt;Por tanto, la licencia establece las condiciones bajo las cuáles podemos usar un software determinado.&lt;br /&gt;&lt;br /&gt;Puesto que existen una amplia variedad de licencias, voy a exponer a continuación algunas de las más comunes, junto con una breve explicación de lo que estas licencias implican desde el punto de vista del usuario.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;GPL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La Licencia Pública General (General Public License) es una &lt;span style="font-weight:bold;"&gt;licencia de software libre&lt;/span&gt; que permite al usuario utilizar un programa licenciado bajo dicha licencia, modificarlo y distribuir las versiones modificadas de éste.&lt;br /&gt;&lt;br /&gt;Todo software desarrollado, aunque sólo sea una parte, con material licenciado bajo GPL debe estar disponible para ser compartido de forma gratuita (copyleft), manteniendo los nombres de los autores originales.&lt;br /&gt;&lt;br /&gt;El software con licencia GPL carece de garantía, el autor no se hace responsable por el malfuncionamiento del mismo. &lt;br /&gt;&lt;br /&gt;Tampoco se puede establecer ningún cobro por las modificaciones realizadas sobre el software.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;LGPL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La Licencia Pública General Menor (Lesser General Public License) &lt;span style="font-weight:bold;"&gt;es una modificación de la licencia GPL&lt;/span&gt;, que permite que los desarrolladores utilicen programas bajo la LGPL sin estar obligados a someter el programa final bajo dichas licencias.&lt;br /&gt;&lt;br /&gt;LGPL no permite que se realicen versiones comerciales del producto licenciado bajo LGPL. Sin embargo, permite realizar versiones comerciales de un producto final que contenga como herramienta adicional un programa LGPL. &lt;br /&gt;&lt;br /&gt;LGPL exige registrar todos los cambios realizados por terceros, a manera de no afectar la reputación del autor original del software.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;BSD&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La Licencia de Distribución de Software de Berkeley (Berkeley Software Distribution) permite a los programadores utilizar, modificar y distribuir a terceros el código fuente y el código binario del programa de software original con o sin modificaciones bajo licencias de código abierto o comercial.&lt;br /&gt;&lt;br /&gt;Esta licencia &lt;span style="font-weight:bold;"&gt;permite el uso del código fuente en software no libre&lt;/span&gt; sin necesidad de mencionar a los autores ni proporcionar el código fuente. Esta licencia sí que establece la renuncia de garantía y la atribución de la autoría sobre trabajos derivados.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;MPL&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La Licencia Pública de Mozilla (Mozilla Public License) es una licencia de código abierto y sofware libre utilizada por el navegador de Internet Mozilla y sus productos derivados. La MPL &lt;span style="font-weight:bold;"&gt;deja abierto el camino a una posible reutilización comercial&lt;/span&gt; y no libre del software y permite la reutilización del código ni el cambio de licencia.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Apache License&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;La Licencia Apache es una licencia de software libre que &lt;span style="font-weight:bold;"&gt;permite al usuario usar el software para cualquier propósito&lt;/span&gt;, distribuirlo, modificarlo, y distribuir versiones modificadas de ese software.&lt;br /&gt;&lt;br /&gt;La Licencia Apache no exige que las obras derivadas del software se distribuyan usando la misma licencia, ni siquiera que se tengan que distribuir como software libre. La Licencia Apache sólo exige que se mantenga una noticia que informe a los receptores que en la distribución se ha usado código con la Licencia Apache. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Actualmente, existen muchas herramientas que están siguiendo una estrategia de &lt;span style="font-weight:bold;"&gt;licenciamiento dual de software&lt;/span&gt;. Estas proporcionan dos tipos de licencias para el mismo software entre las que puede optar el usuario:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Una licencia gratuita de software libre&lt;/span&gt; (por ejemplo, GPL) que permite el uso del software a condición de que lo que el cliente desarrolle tambien sea puesto a disposición de otros usuarios libremente.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Una licencia de pago comercial&lt;/span&gt; que permite que no haya que publicar el código fuente de las aplicaciones desarrolladas.&lt;/li&gt;&lt;/ul&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Licencia_de_software"&gt;http://es.wikipedia.org/wiki/Licencia_de_software&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.gnu.org/licenses/license-list.es.html"&gt;http://www.gnu.org/licenses/license-list.es.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.monografias.com/trabajos55/licencias-de-software/licencias-de-software.shtml"&gt;http://www.monografias.com/trabajos55/licencias-de-software/licencias-de-software.shtml&lt;/a&gt;&lt;br /&gt;&lt;a href="http://es.wikipedia.org/wiki/Apache_License"&gt;http://es.wikipedia.org/wiki/Apache_License&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-4050584669856284798?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/4050584669856284798/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/licencias-de-software.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4050584669856284798'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/4050584669856284798'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/licencias-de-software.html' title='Licencias de Software'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-509153586191092449</id><published>2009-10-19T13:07:00.005+02:00</published><updated>2009-11-05T08:44:10.489+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Formación'/><category scheme='http://www.blogger.com/atom/ns#' term='Metodologías ágiles'/><title type='text'>Scrum Manager</title><content type='html'>En los últimos tiempos se viene oyendo hablar mucho sobre &lt;span style="font-weight:bold;"&gt;metodologías ágiles&lt;/span&gt; y, principalmente, sobre Scrum. El creciente interés por &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt; ha hecho florecer una serie de certificaciones al respecto, promovidas por la Scrum Alliance y, por supuesto, de pago. Contra esta tendencia a lucrarse de una metodología que ha florecido dentro de ambientes “Open Source” se han alzado voces que prefieren compartir el conocimiento a través de la comunidad.&lt;br /&gt;&lt;br /&gt;Una iniciativa en este sentido es &lt;a href="http://www.scrummanager.net/"&gt;Scrum Manager&lt;/a&gt;, que se define como una “&lt;span style="font-style:italic;"&gt;comunidad profesional para la gestión flexible de proyectos y organizaciones TIC&lt;/span&gt;”. Su objetivo es mejorar los procedimientos y métodos de trabajo de las organizaciones y proyectos de software manteniendo de forma abierta a la comunidad profesional la plataforma de conocimiento Open Knowledge.&lt;br /&gt;&lt;br /&gt;Esta plataforma ofrece los siguientes cursos gratuitos sobre &lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt;:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Introducción a Scrum Manager&lt;/span&gt;: Su objetivo es “&lt;span style="font-style:italic;"&gt;conocer los principios de los modelos de procesos y las prácticas ágiles, enmarcados en el mapa o marco de situación que les da sentido, y revela las fortalezas y debilidades de cada estrategia: ingeniería, procesos, gestión predictiva y gestión ágil&lt;/span&gt;”.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Scrum&lt;/span&gt;: Su objetivo es “&lt;span style="font-style:italic;"&gt;conocer el modelo Scrum: origen del modelo, principios y prácticas que emplea para la gestión y seguimiento ágil del proyecto, sus componentes; junto con las razones y consideraciones de fondo para la implementación del modelo&lt;/span&gt;”.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight:bold;"&gt;Métricas ágiles&lt;/span&gt;: Su objetivo es “&lt;span style="font-style:italic;"&gt;conocer la razón y finalidad de las métricas en la gestión ágil de proyectos, y evitar errores habituales en el diseño y aplicación de métricas, normalmente por exceso en el número de métricas o en su complejidad, que suele desbordar las necesidades de estimación y seguimiento ágil&lt;/span&gt;”.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Estos son cursos ofrecen recursos de aprendizaje como material didáctico y foros. Además, a la conclusión de estos cursos existe una prueba de evaluzación final cuya superación satisfactoria otorga puntos de autoridad dentro de la escala de reconocimiento profesional de &lt;span style="font-weight:bold;"&gt;Scrum Manager&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Desde aquí quiero aprovechar para felicitar a los responsables de esta iniciativa y agradecerles su esfuerzo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.scrummanager.net/"&gt;Scrum Manager&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-509153586191092449?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/509153586191092449/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/scru-manager.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/509153586191092449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/509153586191092449'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/scru-manager.html' title='Scrum Manager'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-6456708370432945970</id><published>2009-10-14T11:54:00.008+02:00</published><updated>2010-09-23T20:49:25.073+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apache Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Gestionando un proyecto Hibernate desde Maven</title><content type='html'>Vamos a ver cómo gestionar con &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; un proyecto que utiliza &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;En primer lugar, vamos a ver cómo configurar las dependencias de &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; en &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;. Aquí nos encontramos con un problema, &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; depende de la Sun JTA API, que no está disponible en el repositorio central de &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; porque, debido a problemas de licencias, no puede ser distribuida libremente.&lt;br /&gt;&lt;br /&gt;Para solucionar este problema existen dos posibles soluciones. La primera es descargar la Sun JTA API de la &lt;a href="http://java.sun.com/javaee/technologies/jta/index.jsp"&gt;página web de Sun&lt;/a&gt; y despues instalarla en el repositorio local de &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Usaremos el siguiente &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;project &lt;br /&gt; xmlns="http://maven.apache.org/POM/4.0.0"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 &lt;br /&gt;  http://maven.apache.org/maven-v4_0_0.xsd"&gt;&lt;br /&gt; &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;com.roldan.hibernate&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;HibernateMavenProject&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;  &lt;br /&gt; &amp;lt;dependencies&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.hibernate&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;hibernate&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;3.2.6.ga&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  … &lt;br /&gt; &amp;lt;/dependencies&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;/pre&gt;&lt;br /&gt;Para instalar la Sun JTA API en el repositorio usaremos la siguiente instrucción desde la línea de comandos:&lt;br /&gt;&lt;pre class="prettyprint"&gt;mvn install:install-file&lt;br /&gt; -DgroupId=javax.transaction&lt;br /&gt; -DartifactId=jta&lt;br /&gt; -Dversion=1.0.1B&lt;br /&gt; -Dpackaging=jar&lt;br /&gt; -Dfile=jta-1_0_1B-classes.zip&lt;/pre&gt;&lt;br /&gt;La segunda posible solución sería descartar la dependencia de la Sun JTA API que tiene &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; y, en su lugar, obtener una implementación alternativa de este API que pueda ser descargada libremente, como la de Geronimo:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;project &lt;br /&gt; xmlns="http://maven.apache.org/POM/4.0.0"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0&lt;br /&gt;  http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;br /&gt; &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;com.roldan.hibernate&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;HibernateMavenProject&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;  &lt;br /&gt; &amp;lt;dependencies&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.hibernate&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;hibernate&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;3.2.6.ga&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;exclusions&amp;gt;&lt;br /&gt;    &amp;lt;exclusion&amp;gt;&lt;br /&gt;     &amp;lt;groupId&amp;gt;javax.transaction&amp;lt;/groupId&amp;gt;&lt;br /&gt;     &amp;lt;artifactId&amp;gt;jta&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;/exclusion&amp;gt;&lt;br /&gt;   &amp;lt;/exclusions&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;geronimo-spec&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;geronimo-spec-jta&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;1.0-M1&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  …&lt;br /&gt; &amp;lt;/dependencies&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;/pre&gt;&lt;br /&gt;Una vez resueltas las dependencias de &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; en &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;, podemos usar &lt;span style="font-weight:bold;"&gt;Hibernate&lt;/span&gt; en nuestros proyectos. Una herramienta que nos ayudará a simplificar las tareas de administración de estos proyectos es el &lt;a href="http://mojo.codehaus.org/maven-hibernate3/hibernate3-maven-plugin/index.html"&gt;plugin de Hibernate 3 para Maven&lt;/a&gt;, que se puede obtener del repositorio de Codehaus.&lt;br /&gt;&lt;br /&gt;Por ejemplo, vamos a usar este plugin para generar el DDL de la base de datos durante el desarrollo, permitiendo reconstruir la base de datos para irnos actualizando a los cambios que se vayan produciendo:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;project&amp;gt;&lt;br /&gt; …&lt;br /&gt; &amp;lt;repositories&amp;gt;&lt;br /&gt;  &amp;lt;repository&amp;gt;&lt;br /&gt;   &amp;lt;id&amp;gt;codehaus&amp;lt;/id&amp;gt;&lt;br /&gt;   &amp;lt;name&amp;gt;Maven Codehaus repository&amp;lt;/name&amp;gt;&lt;br /&gt;   &amp;lt;url&amp;gt;http://repository.codehaus.org/&amp;lt;/url&amp;gt;&lt;br /&gt;  &amp;lt;/repository&amp;gt;&lt;br /&gt; &amp;lt;/repositories&amp;gt;&lt;br /&gt; …&lt;br /&gt; &amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;extensions&amp;gt;&lt;br /&gt;   &amp;lt;extension&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;mysql&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;mysql-connector-java&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;5.1.6&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;/extension&amp;gt;&lt;br /&gt;  &amp;lt;/extensions&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;hibernate3-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;2.2&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;     &amp;lt;componentProperties&amp;gt;&lt;br /&gt;      &amp;lt;drop&amp;gt;true&amp;lt;/drop&amp;gt;&lt;br /&gt;      &amp;lt;outputfilename&amp;gt;schema.sql&amp;lt;/outputfilename&amp;gt;&lt;br /&gt;     &amp;lt;/componentProperties&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt; &amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;/pre&gt;&lt;br /&gt;Para lanzar la ejecución de esta tarea de actualización de la base de datos, usamos el comando:&lt;br /&gt;&lt;pre class="prettyprint"&gt;mvn org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-6456708370432945970?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/6456708370432945970/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/gestionando-un-proyecto-hibernate-desde.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6456708370432945970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6456708370432945970'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/gestionando-un-proyecto-hibernate-desde.html' title='Gestionando un proyecto Hibernate desde Maven'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-3777736462736420457</id><published>2009-10-06T12:30:00.007+02:00</published><updated>2010-10-07T19:58:19.159+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apache Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='Subversion'/><title type='text'>Hacer un release de un proyecto con Maven</title><content type='html'>A la hora de hacer un release de un proyecto que estamos gestionando con &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt; y &lt;span style="font-weight:bold;"&gt;Subversio&lt;/span&gt;n podemos seguir los siguientes pasos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cambiar la versión en el &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt; del proyecto y quitar la etiqueta &lt;span style="font-style:italic;"&gt;SNAPSHOT&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Hacer commit del &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt;. &lt;/li&gt;&lt;li&gt;Etiquetar la versión del código en el repositorio de &lt;span style="font-weight:bold;"&gt;Subversion&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Cambiar la version en el &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt; para dejar la siguiente versión: &lt;span style="font-style:italic;"&gt;0.0.2-SNAPSHOT&lt;/span&gt;.&lt;/li&gt;&lt;li&gt;Hacer commit de los &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Si además, en vez de sólo uno, tenemos varios proyectos, el trabajo se multiplica.&lt;br /&gt;&lt;br /&gt;Para simplificar estas tareas, se puede hacer uso de un plugin de &lt;span style="font-weight:bold;"&gt;Maven&lt;/span&gt;, el &lt;span style="font-weight:bold;"&gt;Maven Release Plugin&lt;/span&gt;. Para ello, primero debemos configurar las propiedades del sistema de control de versiones que estamos usando. Esto se hace en el bloque &lt;span style="font-style:italic;"&gt;scm&lt;/span&gt; del &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt;:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;scm&amp;gt;&lt;br /&gt;  &amp;lt;url&amp;gt;svn://localhost/trunk/SimpleProject&amp;lt;/url&amp;gt;&lt;br /&gt;  &amp;lt;developerConnection&amp;gt;&lt;br /&gt;    scm:svn:svn://localhost/trunk/SimpleProject&lt;br /&gt;  &amp;lt;/developerConnection&amp;gt;&lt;br /&gt;&amp;lt;/scm&amp;gt;&lt;/pre&gt;&lt;br /&gt;Ahora, incluimos en el &lt;span style="font-style:italic;"&gt;pom.xml&lt;/span&gt; del proyecto la configuración para el &lt;span style="font-weight:bold;"&gt;Maven Release Plugin&lt;/span&gt;. Vamos a indicar en que ruta se deben dejar los etiquetas de las releases que realicemos:&lt;br /&gt;&lt;pre class="prettyprint xml"&gt;&amp;lt;project&amp;gt;&lt;br /&gt;…&lt;br /&gt;  &amp;lt;build&amp;gt;&lt;br /&gt;    &amp;lt;plugins&amp;gt;&lt;br /&gt;    …&lt;br /&gt;      &amp;lt;plugin&amp;gt;&lt;br /&gt;        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;        &amp;lt;artifactId&amp;gt;maven-release-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;version&amp;gt;2.0-beta-7&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;configuration&amp;gt;&lt;br /&gt;          &amp;lt;tagBase&amp;gt;svn://localhost/tags/releases&amp;lt;/tagBase&amp;gt;&lt;br /&gt;        &amp;lt;/configuration&amp;gt;&lt;br /&gt;      &amp;lt;/plugin&amp;gt;&lt;br /&gt;    …&lt;br /&gt;    &amp;lt;/plugins&amp;gt;&lt;br /&gt;  &amp;lt;/build&amp;gt;&lt;br /&gt;…     &lt;br /&gt;&amp;lt;/project&amp;gt;&lt;/pre&gt;&lt;br /&gt;A la hora de hacer la release he experimentado fallos relacionados con el directorio &lt;span style="font-style:italic;"&gt;target&lt;/span&gt;, puesto que este es un directorio que se elimina cada vez que se hace un &lt;span style="font-style:italic;"&gt;clean&lt;/span&gt;, lo cual genera conflictos entre las versiones del proyecto en &lt;span style="font-weight:bold;"&gt;Subversion&lt;/span&gt;. Puesto que es un directorio cuyo contenido se genera automáticamente en la fase de construcción del proyecto, no es necesario que lo incluyamos en el sistema de control de versiones. Vamos a indicar en &lt;span style="font-weight:bold;"&gt;Eclipse&lt;/span&gt; que este directorio sea ignorado por &lt;span style="font-weight:bold;"&gt;Subversion&lt;/span&gt;, desde la ventana &lt;span style="font-style:italic;"&gt;Preferences&lt;/span&gt;: &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_WQMxntNMWT0/SsshoZbIlJI/AAAAAAAAKzM/VLsYJk-SQNk/s1600-h/imagen1.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 280px;" src="http://3.bp.blogspot.com/_WQMxntNMWT0/SsshoZbIlJI/AAAAAAAAKzM/VLsYJk-SQNk/s320/imagen1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5389438356982109330" /&gt;&lt;/a&gt;&lt;br /&gt;En este momento, ya se podría hacer una release del proyecto mediante el siguiente comando que se ejecutaría dentro del directorio del proyecto:&lt;br /&gt;&lt;pre class="prettyprint"&gt;mvn -Djorge=jorgepassword release:clean release:prepare&lt;/pre&gt;&lt;br /&gt;La ejecución de este comando nos preguntará por la versión de la release que estamos realizando, por el nombre de la etiqueta para esta release y por la siguiente versión del proyecto después de esta release. En nuestro caso, dejaremos las opciones por defecto:&lt;br /&gt;&lt;pre class="prettyprint"&gt;What is the release version for &lt;br /&gt; "Unnamed - com.roldan:SimpleProject:jar:0.0.2-SNAPSHOT"?&lt;br /&gt; (com.roldan:SimpleProject) 0.0.2: :&lt;br /&gt;What is SCM release tag or label for &lt;br /&gt; "Unnamed - com.roldan:SimpleProject:jar:0.0.2-SNAPSHOT"?&lt;br /&gt; (com.roldan:SimpleProject) SimpleProject-0.0.2: :&lt;br /&gt;What is the new development version for&lt;br /&gt; "Unnamed - com.roldan:SimpleProject:jar:0.0.2-SNAPSHOT"?&lt;br /&gt; (com.roldan:SimpleProject) 0.0.3-SNAPSHOT: :&lt;/pre&gt;&lt;br /&gt;Al finalizar, habremos creado la release del proyecto:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/SssiOOcTvXI/AAAAAAAAKzU/t82_nHavxuE/s1600-h/imagen2.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 232px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/SssiOOcTvXI/AAAAAAAAKzU/t82_nHavxuE/s320/imagen2.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5389439006869273970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Referencias:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://maven.apache.org/plugins/maven-release-plugin/index.html"&gt;http://maven.apache.org/plugins/maven-release-plugin/index.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://weblogs.java.net/blog/2008/08/31/using-maven-release-plugin"&gt;http://weblogs.java.net/blog/2008/08/31/using-maven-release-plugin&lt;/a&gt;&lt;br /&gt;&lt;a href="http://jmbeas.blogspot.com/2009/03/versionado-automatico-con-maven.html"&gt;http://jmbeas.blogspot.com/2009/03/versionado-automatico-con-maven.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-3777736462736420457?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/3777736462736420457/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/hacer-un-release-de-un-proyecto-con.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3777736462736420457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/3777736462736420457'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/hacer-un-release-de-un-proyecto-con.html' title='Hacer un release de un proyecto con Maven'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_WQMxntNMWT0/SsshoZbIlJI/AAAAAAAAKzM/VLsYJk-SQNk/s72-c/imagen1.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-6400744617194314269</id><published>2009-10-01T11:38:00.004+02:00</published><updated>2009-10-01T11:46:05.669+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Apache Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Calidad'/><title type='text'>Herramientas de análisis de calidad del código</title><content type='html'>Existen muchas herramientas que nos permiten analizar el código desarrollado y parecen ser ampliamente usadas. Me había propuesto escribir un artículo describiendo el uso de algunas de ellas, pero visto que esta información ya existe y es fácilmente localizable en Internet, me voy a limitar a enumerar estas herramientas y hacer una breve descripción de para qué sirve cada una.&lt;br /&gt;&lt;br /&gt;Las herramientas sobre las que voy a hablar son:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Checkstyle&lt;/li&gt;&lt;li&gt;PMD&lt;/li&gt;&lt;li&gt;Findbugs&lt;/li&gt;&lt;li&gt;JDepend&lt;/li&gt;&lt;li&gt;JavaNCSS&lt;/li&gt;&lt;li&gt;Cobertura&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Checkstyle (&lt;a href="http://checkstyle.sourceforge.net/"&gt;http://checkstyle.sourceforge.net/&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Checkstyle ayuda a escribir código que se adhiera a unas convenciones de codificación determinadas. Además, en las últimas versiones se le han añadido nuevas características que permiten también encontrar problemas en el diseño de las clases, encontrar código duplicado o buscar patrones de error conocidos.&lt;br /&gt;&lt;br /&gt;Checkstyle tiene plugins que permiten que sea usado desde cualquier IDE, como Eclipse (&lt;a href="http://eclipse-cs.sourceforge.net/"&gt;http://eclipse-cs.sourceforge.net/&lt;/a&gt;), resaltando sobre el código los errores encontrados por el analizador. También poseee un plugin para Maven 2 (&lt;a href="http://maven.apache.org/plugins/maven-checkstyle-plugin/"&gt;http://maven.apache.org/plugins/maven-checkstyle-plugin/&lt;/a&gt;) que permite generar informe sobre lor errores encontrados.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;PMD (&lt;a href="http://pmd.sourceforge.net/"&gt;http://pmd.sourceforge.net/&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PMD busca en el código fuente ciertos patrones de error, código no usado, código no óptimo, expresiones demasiado complicadas y código duplicado.&lt;br /&gt;&lt;br /&gt;Podemos usarlo tanto en Eclipse (&lt;a href="http://pmd.sourceforge.net/integrations.html#eclipse"&gt;http://pmd.sourceforge.net/integrations.html#eclipse&lt;/a&gt;) como en Maven (&lt;a href="http://maven.apache.org/plugins/maven-pmd-plugin/project-info.html"&gt;http://maven.apache.org/plugins/maven-pmd-plugin/project-info.html&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Findbugs (&lt;a href="http://findbugs.sourceforge.net/"&gt;http://findbugs.sourceforge.net/&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Se trata de otra herramienta que realiza análisis estático de código en busca de errores. &lt;br /&gt;&lt;br /&gt;También puede ser usado en Eclipse (&lt;a href="http://findbugs.sourceforge.net/manual/eclipse.html"&gt;http://findbugs.sourceforge.net/manual/eclipse.html&lt;/a&gt;) como en Maven (&lt;a href="http://mojo.codehaus.org/findbugs-maven-plugin/2.0.1/"&gt;http://mojo.codehaus.org/findbugs-maven-plugin/2.0.1/&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JDepend (&lt;a href="http://clarkware.com/software/JDepend.html"&gt;http://clarkware.com/software/JDepend.html&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Jdepend proporciona métricas de cálidad entre los paquetes de un proyecto en términos de su extensibilidad, reusabilidad, y mantenibilidad.&lt;br /&gt;&lt;br /&gt; Como las herramientas anteriores, se puede usar en Eclipse (&lt;a href="http://andrei.gmxhome.de/jdepend4eclipse/"&gt;http://andrei.gmxhome.de/jdepend4eclipse/&lt;/a&gt;) y en Maven (&lt;a href="http://mojo.codehaus.org/jdepend-maven-plugin/"&gt;http://mojo.codehaus.org/jdepend-maven-plugin/&lt;/a&gt;). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JavaNCSS (&lt;a href="http://mojo.codehaus.org/jdepend-maven-plugin/"&gt;http://www.kclee.de/clemens/java/javancss/&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Esta herramienta permite recoger métricas sobre el código fuente, como el número de líneas, paquetes, clases o métodos.&lt;br /&gt;&lt;br /&gt;Al igual que todas las herramientas anteriores, se puede susar en Eclipse (&lt;a href="http://freshmeat.net/projects/jncss4eclipse/"&gt;http://freshmeat.net/projects/jncss4eclipse/&lt;/a&gt;) y en Maven (&lt;a href="http://mojo.codehaus.org/javancss-maven-plugin/dependencies.html"&gt;http://mojo.codehaus.org/javancss-maven-plugin/dependencies.html&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Cobertura (&lt;a href="http://cobertura.sourceforge.net/"&gt;http://cobertura.sourceforge.net/&lt;/a&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Esta herramienta permite calcular la cantidad de código al que acceden los tests.&lt;br /&gt;&lt;br /&gt;En este caso, no se dispone de un plugin para Eclipse, pero si que podemos usar esta herramienta desde Maven (&lt;a href="http://mojo.codehaus.org/cobertura-maven-plugin/"&gt;http://mojo.codehaus.org/cobertura-maven-plugin/&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Os animo a que probéis estas herramientas. ¿Conocéis alguna más que pueda resultar útil para el desarrollo de un proyecto Java?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-6400744617194314269?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/6400744617194314269/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/herramientas-de-analisis-de-calidad-del.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6400744617194314269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1253253616658611146/posts/default/6400744617194314269'/><link rel='alternate' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/10/herramientas-de-analisis-de-calidad-del.html' title='Herramientas de análisis de calidad del código'/><author><name>Jorge</name><uri>http://www.blogger.com/profile/04076231677373326747</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='22' src='http://1.bp.blogspot.com/_WQMxntNMWT0/TAlOrvqfv1I/AAAAAAAAK9w/ic8UuRWOM78/S220/Jo,+qu%C3%A9+guapo+soy.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1253253616658611146.post-8640535579429584316</id><published>2009-09-30T09:45:00.011+02:00</published><updated>2010-06-08T08:43:48.229+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Integración continua'/><title type='text'>Usando Hudson como servidor de integración contínua</title><content type='html'>En el &lt;a href="http://tratandodeentenderlo.blogspot.com/2009/09/integracion-continua.html"&gt;artículo anterior&lt;/a&gt; se hizo una descripción de lo que es la &lt;span style="font-weight:bold;"&gt;integración continua&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Ahora vamos a ver cómo usar &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; como servidor de &lt;span style="font-weight:bold;"&gt;integración contínua&lt;/span&gt;, para que construya nuestro proyecto de forma automática si hay algún cambio en el repositorio de Subversion y nos informe por email en caso de que se produzca algún error.&lt;br /&gt;&lt;br /&gt;En primer lugar, nos descargamos la última versión de Hudson de la web:&lt;br /&gt;&lt;a href="https://hudson.dev.java.net/"&gt;https://hudson.dev.java.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Nos descargaremos la último versión de &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; como un archivo .war. &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; es tan fácil de instalar en un servidor Tomcat cómo copiar el .war en el directorio &lt;span style="font-style:italic;"&gt;webapps&lt;/span&gt;. Arrancamos el Tomcat y vamos a &lt;a href="http://localhost/hudson"&gt;http://localhost/hudson&lt;/a&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/SsMNRdFWElI/AAAAAAAAKx0/LVDN69r2kr8/s1600-h/imagen1.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/SsMNRdFWElI/AAAAAAAAKx0/LVDN69r2kr8/s320/imagen1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387164172781228626" /&gt;&lt;/a&gt;&lt;br /&gt;Antes de trabajar con ningún proyecto, vamos a configurar el entorno de &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; desde &lt;span style="font-style:italic;"&gt;Manage Hudson&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMNcpTinWI/AAAAAAAAKx8/WXaBCVauyWY/s1600-h/imagen2.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMNcpTinWI/AAAAAAAAKx8/WXaBCVauyWY/s320/imagen2.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387164365040557410" /&gt;&lt;/a&gt;&lt;br /&gt;Clicamos sobre &lt;span style="font-style:italic;"&gt;Configure System&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMNowqBNrI/AAAAAAAAKyE/xhpWyGyZehM/s1600-h/imagen3.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMNowqBNrI/AAAAAAAAKyE/xhpWyGyZehM/s320/imagen3.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387164573172315826" /&gt;&lt;/a&gt;&lt;br /&gt;En nuestro caso, nos interesa configurar Maven y el JDK para que &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; sea capaz de encontrar sus rutas: &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMNwuLcLTI/AAAAAAAAKyM/wspoY1U5OsI/s1600-h/imagen4.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMNwuLcLTI/AAAAAAAAKyM/wspoY1U5OsI/s320/imagen4.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387164709946142002" /&gt;&lt;/a&gt;&lt;br /&gt;También querremos configurar la notificación por email parapoder enviar correos que alerten sobre construcciones erróneas del proyecto. En caso de no tener un servidor de correo, se puede usar fácilmente Apache James como servidor de correo. Vimos cómo hacerlo en un &lt;a href="http://tratandodeentenderlo.blogspot.com/2009/08/uso-de-un-nodo-node_20.html"&gt;post anterior&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Una vez tenemos el servidor de correo instalado, podemos modificar la configuración de &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMOGxITzHI/AAAAAAAAKyU/OfIm5Ui-I30/s1600-h/imagen5.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMOGxITzHI/AAAAAAAAKyU/OfIm5Ui-I30/s320/imagen5.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387165088695438450" /&gt;&lt;/a&gt;&lt;br /&gt;Ahora podemos crear un nuevo proyecto Java en Eclipse. Para nuestro ejemplo hemos creado un proyecto Maven de una aplicación web y la hemos incorporado a Subversion.&lt;br /&gt;&lt;br /&gt;Posteriormente, volvemos a la pantalla principal de &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; para crear un nuevo job que maneje nuestro proyecto:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMOR_Tv4qI/AAAAAAAAKyc/mroKXXqc4-I/s1600-h/imagen6.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMOR_Tv4qI/AAAAAAAAKyc/mroKXXqc4-I/s320/imagen6.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387165281480073890" /&gt;&lt;/a&gt;&lt;br /&gt;Seleccionaremos la última opción &lt;span style="font-style:italic;"&gt;Build a maven2 project&lt;/span&gt;. A continuación entraremos a la ventana de configuración del proyecto. Configuramos el repositorio de Subversion del proyecto y la consulta de &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; a este repositorio en busca de cambios que lancen una nueva construcción. Hacemos que esta consulta a Subversion se realice cada minuto:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMOeJsYlzI/AAAAAAAAKyk/OdBEsejKBUo/s1600-h/imagen7.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMOeJsYlzI/AAAAAAAAKyk/OdBEsejKBUo/s320/imagen7.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387165490426189618" /&gt;&lt;/a&gt;&lt;br /&gt;Ahora lanzamos una construcción de forma manual para construir el espacio de trabajo desde el apartado &lt;span style="font-style:italic;"&gt;Workspace&lt;/span&gt; del proyecto:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMO289xl2I/AAAAAAAAKys/zdtXkw91eFU/s1600-h/imagen8.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_WQMxntNMWT0/SsMO289xl2I/AAAAAAAAKys/zdtXkw91eFU/s320/imagen8.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387165916506199906" /&gt;&lt;/a&gt;&lt;br /&gt;Desde este momento, una vez construido el proyecto, cualquier cambio en el proyecto que sea entregado a Subversion debería reflejarse en una reconstrucción del proyecto. Si subimos una modificación a Subversion, podemos ver cómo &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; programa una nueva construcción cuando detecta el cambio:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMPAezxebI/AAAAAAAAKy0/Hmr8zTDSPTo/s1600-h/imagen9.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_WQMxntNMWT0/SsMPAezxebI/AAAAAAAAKy0/Hmr8zTDSPTo/s320/imagen9.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387166080209877426" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/SsMPMjqdJcI/AAAAAAAAKy8/E4SS25JO32U/s1600-h/imagen10.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/SsMPMjqdJcI/AAAAAAAAKy8/E4SS25JO32U/s320/imagen10.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387166287671403970" /&gt;&lt;/a&gt;&lt;br /&gt;Si ahora introducimos un cambio con un error de compilación, la construcción detectará este error y enviará un correo alertando de este situación:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_WQMxntNMWT0/SsMPSg6hoYI/AAAAAAAAKzE/aYcFT9eyD7g/s1600-h/imagen11.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_WQMxntNMWT0/SsMPSg6hoYI/AAAAAAAAKzE/aYcFT9eyD7g/s320/imagen11.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5387166390012715394" /&gt;&lt;/a&gt;&lt;br /&gt;Con esto, hemos visto cómo configurar y empezar a usar &lt;span style="font-weight:bold;"&gt;Hudson&lt;/span&gt; cocmo servidor de &lt;span style="font-weight:bold;"&gt;integración continua&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1253253616658611146-8640535579429584316?l=tratandodeentenderlo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tratandodeentenderlo.blogspot.com/feeds/8640535579429584316/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://tratandodeentenderlo.blogspot.com/2009/0
