Kortsoft

Thursday, February 04, 2010

Código limpio 1

Ahora que estoy leyendo pasajes del libro "Clean Code" de Robert C. Martin me ha surgido la idea de escribir algo sobre código real que he visto estos dias en varios sitios (de varios proyectos distintos de empresas distintas).
En ambos casos la operación que se estaba codificando era:

Obtener A
Modificar A
Actualizar/Guardar A

Bastante sencillo y típico, ¿no? Entonces, ¿por qué es tan fácil encontrar código tan mal hecho?. A las pruebas me remito (he cambiado el nombre de las variables para ocultar el origen del código):

Settings settings = page.getSettings();
settings.setProperty("propertyName", propertyValue);
pageService.updatePageSettings(page.getId(), page.getSettings());

¿Funciona este código? Sí. ¿Es de buena calidad? NO. Y fundamentalmente es porque no sigue la línea de pensamiento que una persona cuerda haría (obtener A, modificar A, guardar A). La lógica de este código anterior dice:

Obtener A
Modificar A
Guardar B

¿¿¿Comorrr??? Sí, eso es lo que dice, lo que pasa es que por artificios del lenguaje (de programación), en este caso A <=> B. (page.getSettings() <=> settings). En este caso, el lector del código (la segunda persona más importante que tiene que entender el código después del señor procesador), rápidamente entiende el error lógico del código y después de preferir un juramento contra el creador del fragmento, puede seguir leyendo, entendiendo o depurando el código. Pero ¿qué pasa si se complica un poco el código? Veamos un ejemplo:

Settings settings = page.getSettings();
settings.setProperty("propertyName", propertyValue);
pageService.updatePageProperties(page.getId(), page.getProperties());

(y el método page.getProperties()):

public Properties getProperties() {
   return this.settings.asProperties();
}

En este caso la confusión es mucho mayor si no conocemos el método page.getProperties() el cual coge nuestro objeto A y lo convierte en B. Efectivamente, el código funciona, porque cuando actualizo el segundo objeto estoy teniendo en cuenta los cambios hechos al primero (pero esta relación no está explícita en el código, sino que tengo que deducirla investigando). La solución de este segundo caso quizás implica una refactorización de varias clases que no obligue a :

  • Trabajar y modificar el objeto A
  • Actualizar el objeto B
Valdría por ejemplo un API que permitiese actualizar objetos de tipo A, y que internamente los transforme a objetos B y luego los actualice.

Al final, lo único que necesitamos es que la trama de nuestro código sea lógica y lineal, y que cualquier lector pueda seguirla. No es necesario hacer tramas tipo Memento aunque en el cine funcionen muy bien.

Labels:

Wednesday, December 02, 2009

Un chascarrillo

Me ha encantado:

Saturday, November 24, 2007

Del lenguaje de marcado al lenguaje estructurado. Parte I

Actualmente en la industria del software se usa XML para casi todo tipo de estructuras de información, desde ficheros de configuración, plantillas de presentación hasta formato de intercambio entre sistemas.
Cualquiera que haya participado en un proyecto web de tamaño mediano-grande, habrá experimentado un hastío después de trabajar constantemente con estos ficheros XML. Y es que este lenguaje es muy verboso, y su verbosidad viene dictada porla función inicial para el que se pensaron los lenguajes de marcado . Por ejemplo la frase "A markup language provides a way to combine a text and extra information about it. The extra information, including structure, layout, or other information, is expressed using markup, which is typically intermingled with the primary text." nos demuestra una de las motivaciones iniciales de estos tipos de lenguaje, el entremezclar texto primario, con información extra. Por tanto estos lenguajes están orientados a generar un lenguaje primario con facilidad anotado con pequeños trozos de información extra; y por eso, la información extra es muy verbosa.Por ejemplo, un fragmento típico sería :

<exampleText>Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, <tag1>quis nostrud</tag1> exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla <tag2 attrib="some">pariatur</tag2>. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</exampleText>


En este fragmento, la mayoría es de texto primario, y por eso no resulta tan verboso y hasta comprensible (por ejemplo hay una relación de 45/2 en caracters de información vs. caracteris de marcado). Sin embargo, tomando otro ejemplo de un script de maven:

<goal name="performanceTest" prereqs="eclipse:prepare">
<attainGoal name="test:single">
<property name="testcase" value="com.germinus.xpression.jcr.JCRPerformanceTest"/>
</attainGoal>
</goal>
<goal name="install" >
<attainGoal name="jar:install"/>
<maven:reactor
basedir="${basedir}/modules"
includes="*/project.xml"
goals="install"
banner="Installing Module"
ignoreFailures="false"
/>
</goal>
<goal name="deploy" >
<attainGoal name="jar:deploy"/>
<maven:reactor
basedir="${basedir}/modules"
includes="*/project.xml"
goals="deploy"
banner="Deploying Module"
ignoreFailures="false"
/>
</goal>
<goal name="test:all">
<j:set var="testcase" value="com.germinus.xpression.cms.AllTests"/>
<attainGoal name="test:single"/>
</goal>


nos encontramos con un caracter de marcado por cada 6 de información (724 caracteres por 116 de marcado; no he contado los ':' dentro de los nombres de los elementos ya que se pueden considerar como parte de información semántica, no léxica), que ya empieza a ser bastante significativo. ¿Os parece legible este fragmento a simple vista? a mi no... (y eso que no habeis visto la versión "escapada" que he tenido que poner para que muestre todos los caracteres HTML ;-) )
Si os fijáis además en este último ejemplo podéis apreciar que no hay nada de texto fuera de los elementos, osea no hay "marcado" alguno en todo el documento, cosa muy habitual en los XML que se manejan en el mundo del desarrollo hoy en dia. ¿Es necesario un lenguaje de marcado para representar este tipo de información? Realmente no, lo que me está pidiendo es un luenguaje "estructurado". ¿Qué tal algo así?:


goal {    name "performanceTest"
prereqs "eclipse:prepare"
attainGoal{ name "test:single"
property{ name"testcase"
value "com.germinus.xpression.jcr.JCRPerformanceTest"
}
}
}
goal { name"install"
attainGoal{name "jar:install"}
maven_reactor {
basedir "${basedir}/modules"
includes "*/project.xml"
goals "install"
banner "Installing Module"
ignoreFailures "false"
}
}
goal { name "deploy"
attainGoal{ name="jar:deploy"}
maven_reactor {
basedir "${basedir}/modules"
includes "*/project.xml"
goals "deploy"
banner "Deploying Module"
ignoreFailures "false"
}
}
goal { name="test:all"
j_set{
var "testcase"
value "com.germinus.xpression.cms.AllTests"
}
attainGoal{ name "test:single" }
}



Más legible ¿no?. Además se han reducido los caracteres de escapado a 71 (1 cada 10 de información), pero, además hemos eliminado caracteres totales también ya que en esta versión no es necesario reescribir el nombre del elemento de nuevo al cerrar un tag (lo que me lleva a pensar que en realidad es información redundante y por tanto podría estar incluidos en los caracteres de escapado).
Y ¿qué diría si os dijese que el parseador para este lenguaje se puede implementar en una mañana? Pues sí, ya que el analizador sintáctico y léxico ya existe y se llama Groovy.

to be continued...


Labels:

Friday, April 07, 2006

Liferay Portal 4.0 released with new fine-grained security model: "Liferay has released Liferay Portal 4.0, which brings a revamped fine-grained security model, enterprise taxonomy, delegated and cascading permissions and administration, public and private pages, JSR-170 compliance via Jackrabbit integration, and page-level themes to the popular open-source portal application.

Thursday, March 23, 2006

APT-Jelly (template-based interface to APT) released: "APT-Jelly provides a template-oriented interface to Sun's Annotation Processing Tool (APT). As an alternative to other source-processing engines (e.g. XDoclet), APT-Jelly fully leverages Java syntax and features including annotations, generics and typesafe enums. "
Por fin una herramienta útil para poder sacarle todo su jugo a las anotaciones. Además usando el lenguaje de scripting Jelly, el cual tiene tanto detractores como simpatizantes. Por mi parte pienso que puede ser muy útil para ciertas cosas, y estas puede ser una de ellas.

Friday, December 23, 2005

Spring Framework 2.0 M1 released: "El comienzo de la nueva temporada de Spring está aquí: Spring Framework 2.0 M1.

Bájatelo

Características nuevas incluidas:

  • Configuración XML simplificada y extensible

  • Nuevas funcionalidades de AOP muy potentes. Integración con AspectJ

  • Facilidades asíncronas JMS mediante message-driven POJO's

  • Spring Portlet MVC, un framework para JSR-168 Portlets

  • y mucho más...


(Se mantiene la compatibildad hacia atrás al 100% con Spring 1.2 y continúa siendo ejecutable en Java 1.3 o mayor)

Wednesday, December 14, 2005

'Pimp My Shirt' Sample Application: Puedes encontrar aquí una aplicación de ejemplo usando Spring Web Flow y algunos conceptos complejos de Spring MVC (subida de ficheros, data binding avanzado, redirect-after-post, etc...).
La aplicación fué presentada en la Spring Web Tier Session por Erwin Vervaet y Alef Andersen en JavaPolis 2005