Aprende un nuevo lenguaje

Es una recomendación muy común la de aprender nuevos lenguajes de programación para, como mínimo, mejorar nuestras aptitudes. Y hace unos días que me encontré ¡Aprende un nuevo lenguaje! ¡Ahora! que posteó Venkman(un crack ;)) en debug_mode=on, que a mi me parece que explica perfecta y ampliamente las razones para hacerlo:

Existe una teoría (hipótesis de Sapir-Whorf) que, en su más extrema versión, sostiene que el lenguaje determina la forma en que pensamos. La teoría es muy discutida y en esa versión extrema está, en general, rechazada. Sin embargo, sí es aceptado comúnmente que el lenguaje sí tiene cierta influencia sobre la forma en que pensamos. Más aún, que utilizando determinadas expresiones y favoreciendo determinados términos, el lenguaje puede influir sobre la forma en que pensamos o apreciamos un tema o un concepto. Esto, que se refiere a los lenguajes naturales, es aplicable quizá incluso con mayor intensidad a los lenguajes de programación, al ser estos mucho más formales y estrictos.

El post completo en ¡Aprende un nuevo lenguaje! ¡Ahora!

Migrado de Wordpress 2.0.11 a 2.7.1

Sí, tal y como suena... hace casi dos años que congelé mi instalación de wordpress(lo sé, lo sé... :P). Hasta que me llegó un email de la gente de DH diciendo que igual era hora de actualizarse XD.

Como bien pone en el título, ha sido una migración en un paso y no una actualización o serie de actualizaciones: me ha tocado crear una base de datos nueva, tener una instalación limpia de wordpress, cargar algunos datos manualmente, cargar los posts y comentarios de la antigua base de datos vía dump, previo paso de problemillas con la codificación de carácteres... y mirar un poco el código de wordpress(por curiosidad más que otra cosa y... pfff).

También he aprovechado a buscar un theme más limpio, hacía un tiempo que el que tenía no me convencía, y aunque este lo debería ajustar un poco para que esté más a mi gusto, ha sido el que más me ha convencido.

En fin, espero ir más al día ahora que parece que trae una herramienta para automatizar las actualizaciones, la verdad es que tengo muy fácil tener la instalación más al día de lo que la he tenido hasta ahora XD

MacPorts ahorrándome trabajo

Finalmente la historia con el Macbook que compré en navidades, ha acabado con que me lo han sustituído por uno nuevo, entonces todavía lo estoy poniendo a punto para poder trabajar con el y dejar ya de retén a mi viejo Toshiba Satellite, por si las moscas aún tardaré en darle la jubilación...

MacPorts facilita la instalación(compilación, instalación y actualización) de software open source para Mac OS, ya lo tenía oído/leído y la verdad es que me está ayudando bastante a instalar mis herramientas de trabajo.

Por ejemplo para instalar Grails:

  • Ejecutar: sudo port install grails
  • Y ya sólo nos queda añadir la variable de entorno GRAILS_HOME en nuestro
    .profile:
    export GRAILS_HOME="/opt/local/share/java/grails"
    export PATH="$PATH:$GRAILS_HOME/bin"
  • Para comprobar que no han habido problemas, simplemente ejecutamos el comando grails help para comprobar que todo ha ido correcto.

Otro ejemplo podría ser git:

  • Ejecutamos sudo port install git-core
  • Y luego ejecutando git comprobamos que, efectivamente, lo tenemos instalado

Pues eso, que es una gozada que haya herramientas que te faciliten la vida, sobre todo cuando eres novato :)

Lo que viene con Grails 1.1

Todavía no he tenido oportunidad(¿tiempo?) de probar las betas de la versión 1.1 de Grails, pero ya llevo unas semanas siguiendo un poco las novedades que están llegando con las tres betas que se han publicado, tanto con las relesae notes como en la lista de correo.

Hay cosas que me parecen muy interesantes: el trabajo que se ha hecho en cuanto infraestructura, el manejo de submits duplicados, el "nuevo" framework de testing, las mejoras para el desarrollo de plugins, poder usar GORM fuera de Grails...

Estas son las principales novedades:

GORM:

GORM es standalone, ya se puede usar fuera de Grails.

Se completan los eventos de GORM con afterInsert, afterUpdate y afterDelete.

Persistencia de colecciones de tipos básicos, como colecciones de String:
class Person {
static hasMany = [nicknames:String]
}

Persistencia de coleciones de tipos enum:
enum VehicleStatus { OFF, IDLING, ACCELERATING, DECELARATING }
class Truck {
static hasMany = [statuses:VehicleStatus]
}

Acceder a objetos persistentes en modo sólo lectura, buscándolos por id:
def book = Book.read(1)

Ordenación por defecto a nivel de clase y en las asociaciones:
class Book {
String title
static mapping = {
sort "title"
}
}
class Author {
static hasMany = [books:Book]
static mapping = {
books sort:"title"
}
}

Obtención por lotes a nivel de clase y en asociaciones:
class Book {
String title
static mapping = {
batchSize 15
}
}

Mejoras en los finders dinámicos. Se podrá utilizar el sufijo InList, cachear queries y usar bloqueo pesismista:

def books = Book.findByAuthorInList(['Dierk Koenig', 'Graeme Rocher'])
def book = Book.findByTitle("Groovy in Action", [cache:true] )
def book = Book.findByTitle("Groovy in Action", [lock:true] )

Relaciones uno a muchos unidireccionales con mapeo heredado, usando joinTable:
class Book {
String title
static belongsTo = Author
static hasMany = [authors:Author]
static mapping = { authors joinTable:[name:"mm_author_books", key:'mm_book_id' ] }
}
class Author {
String name
static hasMany = [books:Book]
static mapping = { books joinTable:[name:"mm_author_books", key:'mm_author_id'] }
}

Los tipos Enum pueden especificar un método getId() que GORM llamará para persistir el estado del enum
enum Country {
AUSTRIA('at'),
UNITED_STATES('us'),
GERMANY('de');
final String id
Country(String id) { this.id = id } }

Plugins:

Plugins globales, para instalar en todas las aplicaciones
grails install-plugin webtest -global

Múltiples repositorios de plugins:
grails.plugin.repos.discovery.myRepository="http://svn.codehaus.org/grails/trunk/grails-test-plugin-repo"
grails.plugin.repos.distribution.myRepository="https://svn.codehaus.org/grails/trunk/grails-test-plugin-repo"

Resolución transitiva de depndencias entre plugins.

Se puede definir un ámbito y el entorno donde un plugin se cargará o empaquetará
def environments = ['dev', 'test']
def scopes = [excludes:'war']

Desarrollo modular de aplicaciones usando plugins, sin necesidad de instalarlos y pudiendo estar en cualquier lugar del sistema de ficheros. Muy útil para probar un plugin propio en una aplicación real(esto antes resultaba incómodo), o para unir en una aplicación funcionalidades repartidas en plugins.

Testing:

Se ha añadido testing plugin como framework de tests que mejora el de las versiones 1.0.x

Data Binding:

Se pueden definir de qué propiedades se hace el binding:
person.properties["firstName","lastName"] = params

Es posible hacer binding de colecciones de objetos, Grails se encarga de instanciar los objetos y los índices:
<g:textField name="books[0].title" value="the Stand" />
<g:textField name="books[1].title" value="the Shining" />
<g:textField name="books[2].title" value="Red Madder" />

Scaffolding:

El scaffolding dinámico también generará las vistas usando los templates generados(y personalizados) con install-templates.

El scaffolding ahora soporta relaciones muchos a muchos y asociaciones uno a muchos unidireccionales.

Controllers:

Manejo de submits duplicados o invalidos usando el patrón Synchronizer Token:
//en el gsp
<g:form useToken="true">...</g:form>
//controlador
withForm {
// good request
}.invalidToken {
// bad request
}

Además de redireccionar ya es posible hacer forward de una petición:
forward controller:"home", action:"index"

Groovy Server Pages:

Ya es posible utilizar librerías de tags JSP, de igual forma que cualquier librería de tags GSP:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:formatNumber value="${10}" pattern=".00"/>
${fmt.formatNumber(value:10, pattern:".00")}

Un namespace propio para usar templates, tmpl:
//template _tableRow.gsp
<tr>
<td class="prop">${label}</td>
<td class="value">${value}</td>
</tr>
//Otro gsp
<tmpl:tableRow label="one" value="two" />

Es posible hacer includes de la respuesta de otro controlador, acción o vista en la vista actual:
<g:include controller="book" action="list"/>

Posibilidad de renderizar templates de los plugins:
<g:render template="pathToTemplateFile" plugin="miplugin"/>

Ahora los gsp se renderizan más rápido, evitando el uso de StringBuffer y StringWriter.

Infraestructura:

Grails viene con un plugin de Maven y un arquetipo:
mvn grails:create-pom

Integración con Ivy y Ant, crea el build.xml y el ivy.xml para construir la aplicación Grails sin que sea necesario que Grails esté instalado en el servidor.

BeanBuilder (el DSL de Spring), ahora soporta los namespaces de Spring pudiendo utilizar así el soporte de AOP.

Nuevo API para acceder al entorno de ejecución y a los meta datos de la aplicación:
switch(Environment.current) {
case Environment.DEVELOPMENT:
configureForDevelopment()
break
case Environment.PRODUCTION:
configureForProduction()
break
}
def metadata = grails.util.Metadata.current
println metadata.applicationName
println metadata.applicationVersion

Nuevo DSL para configurar Log4j

La configuración de los builds se ha flexibilizado pudiendo configurar diferentes aspectos en el nuevo BuildConfig

Posibilidad de encriptar las contraseñas del DataSource

--
Veremos qué añadidos/mejoras más aparecen en las RC y hasta que esté disponible Grails 1.1

Acceder al ApplicationContext en un HttpSessionListener