viernes, 3 de junio de 2011

Extensión de clases en Scala

En algunos lenguajes de programación dinámicos como ruby se permite añadir funcionalidad a clases ya existentes. Cuando esto ocurre, se dice que las clases en ese lenguaje son 'abiertas'.

Un lenguaje de programación con clases abiertas añade mucha flexibilidad para el programador, sin embargo, esta flexibilidad hace que sea más difícil auditar el código.

La principal ventaja de esta técnica es poder aumentar la funcionalidad de las clases que proporciona en lenguaje. Al tener unos tipos básicos con una interfaz más rica, el código comienza a ser más sencillo y se reduce el número de líneas de código para desarrollar una funcionalidad.

En Scala, las clases no son abiertas, sin embargo, tiene un mecanismo similar con el que se pueden llegar a resultados no muy distintos.

Ejemplo:

class RomanNumber(val number:Int){
def toRoman:String = {
if(number == 1) return "I";
else if(number == 2) return "II";
else if(number == 3) return "III";
else if(number == 4) return "IV";
else if(number == 5) return "V";
else return "Unknown";
}
}

object Main extends Application{
implicit def intRomanNumber(x:Int) = new RomanNumber(x);

override def main(args: Array[String]){
println(1.toRoman);
println(3.toRoman);
println(5.toRoman);
println(6.toRoman);
}
}

En este ejemplo se crea una clase 'RomanNumber' que contiene la funcionalidad que necesitamos añadir a los enteros 'toRoman'.

El código resultaría muy redundante si cada vez que queremos usar el método 'toRoman' necesitamos crear una instancia de la clase y pasarle como argumento el entero. Algo como: new RomanNumber(4).toRoman.

Para este tipo de casos, Scala provee del mecanismo de conversión implícita, en el ejemplo el método 'intRomanNumber'.
Al definir un método como 'implicit' se llamará para hacer el correspondiente cambio de tipos como se le indique, en este caso creando una instancia de 'RomanNumber'.

El resultado final es el que aparece en el ejemplo, parece que los métodos añadidos mediante conversión implícita pertenezcan a la clase original, muy similar al caso de los lenguajes dinámicos y las clases abiertas.

sábado, 16 de abril de 2011

attr_accessor_with_default

Un pequeño tip sobre los atributos en ruby on rails, normalmente en cualquier clase se pueden declarar atributos con attr_accessor, pero, si lo que se necesita es un atributo que tenga un valor por defecto, existe una función menos conocida attr_accessor_with_default.

Un ejemplo

class Example
attr_accessor_with_default :attr, 'default message'
end

e = Example.new
e.attr
=> 'default message'

domingo, 20 de marzo de 2011

Propagación de eventos en jQuery

La primera aproximación de asignación de eventos a los elementos del DOM es la más sencilla, simplemente se establece el callback a ejecutar en el elemento que posee el evento.

$('#element').click(function(){alert('hello');})

Usando este método se disparará el evento del elemento con id 'element', después su padre, y así sucesivamente.

La segunda posibilidad es usar 'live', de esta forma todos los elementos futuros que cumplan con el selector dispararán el evento.

$('#element').live('click', function(){alert('hello');})

Esta aproximación asigna el callback a la raíz del DOM (document) de tal forma que cada vez que se dispara un evento si coincide tanto en tipo como en su selector, se dispara el callback.
Esta implementación, aún siendo muy útil puede dar lugar a comportamientos inesperados, el callback establecido con 'live' se ejecutará el último en la jerarquía de propagación del evento.

'live' no es más que una particularización de 'delegate'. 'delegate' se puede usar para hilar más fino en el establecimiento de la respuesta a eventos.

$('#parent').delegate('#element', 'click', function() { alert("hello") });

En este caso, establecemos el callback en 'parent' en lugar de en document, por lo demás el funcionamiento es similar a 'live'.
Cada vez que el evento llegue a 'parent' se comprobará si coincide tanto en tipo como en el selector, de ser cierto se dispara el callback.

'delegate' es mucho más eficiente que 'live' puesto que solo comprueba los eventos tomando como raíz el elemento que le indicamos en lugar de todo el documento como es el caso de 'live'. Aún así el problema en el orden de propagación aparece al igual que en 'live'.

jueves, 3 de febrero de 2011

Generar proyectos ruby on rails con versiones anteriores

Después del cambio de versión de ruby on rails de la rama 2 a la 3, surge un caso muy típico, tener instalado rails 3 y querer generar un proyecto con la versión 2.

Para generar un proyecto de ruby on rails con una versión anterior que tengamos instalada tan solo hay que ejecutar lo siguiente:

rails _VERSION_ proyecto

Donde VERSION es la numeración específica de la versión de rails, por ejemplo, para crear un proyecto con la versión 2.3.8 (actualmente la última de la rama 2).

rails _2.3.8_ proyecto

jueves, 20 de enero de 2011

Depuración android por red

Hay dispositivos android que no permiten la depuración a través del conector USB, aún así, es posible usarlos para desarrollo usando la conectividad por Wi-Fi.

Simplemente hay que conectar el dispositivo a la misma red Wi-Fi que el PC desde el que estamos desarrollando y ejecutar el comando:

adb connect ip:5555

Donde ip es la dirección IP del dispositivo en la interfaz Wi-Fi.
A partir de ahí se puede usar adb igual que cuando está conectada la depuración USB, se puede usar la shell, la transferencia de ficheros, etc, incluso el android SDK sin necesidad de cables.

viernes, 7 de enero de 2011

Conocer el método desde el que una función es llamada en Java

El lenguaje de programación Java en sus últimas versiones tiene algunas construcciones que permiten introspección.

Como ejemplo en el siguiente trozo de código la función 'print' tiene un comportamiento u otro dependiendo de que método le llama. En general esto no es una buena práctica de programación pero sirve como ejemplo ilustrativo.

public class Ejemplo{
public static void print(){
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement e;
String str = stackTraceElements[2].getMethodName();

if(str.equals("other")){
System.out.println("Other message!");
}
else{
System.out.println("Hello world!");
}
}

public static void other(){
print();
}

public static void main(String[] args){
print();
other();
}
}

La llamada 'Thread.currentThread().getStackTrace()' devuelve un array de elementos 'StackTraceElement', cada uno de estos elementos representa una llamada de la pila de llamadas a funciones.

En el ejemplo anterior se consulta el nombre del método, pero se pueden extraer más datos, más información en el javadoc de StackTraceElement.

sábado, 25 de diciembre de 2010

Javascript orientado a objetos

Debido al gran auge de la web, últimamente han surgido numerosas librerías y tutoriales acerca de como programar javascript orientado a objetos.

No es difícil encapsular código javascript simulando que se está trabajando con clases.

function Article(title, body){
this.title = title;
this.body = body;
}

var a = new Article('titulo', 'noticia')

Incluso se puede conseguir visibilidad privada para los atributos de la 'clase' que elijamos.

function Article(title, body){
this.body = body;
var _title = title;
this.getTitle = function(){
return _title;
}
this.setTitle = function(title){
_title = title;
}
}

Sin embargo, en mi opinión todas estas aproximaciones conducen a escribir código javascript poco natural. Javascript fue pensado como un lenguaje de programación basado en prototipos y su flujo principal de ejecución es orientado a eventos.

Está basado en prototipos, la encapsulación, las 'clases' se obtienen a partir de la clonación de objetos y no de una estructura tan rígida como la orientación a objetos. Esto hace al lenguaje mucho más propicio para las tareas que fue pensado.

De la orientación a eventos del lenguaje han surgido proyectos muy interesantes como node.js, hay que tratar de aprovechar las bondades del lenguaje, no cambiarlas a través de capas de abstracción.