Playing with Ubiquity

I have been playing with Firefox Ubiquity this afternoon, and here is the result: A translation command for Word Reference. If you have Ubiquity installed, you should be able to install directly from this page.

Get the source code here

ANTLR Tutorial - Dependency injection language

It’s been a while since the last time I wrote something here. It turns out that I have been tinkering with ANTLR for the last nine months as part of my new job. So my idea is to write a series of posts to teach you how to create your own languages with ANTLR.

ANTLR is a pretty good top-down LL(*) lexer and parser that allows us to define languages/DSLs without the restrictions of developing it inside a host language, as Java. As a drawback, writting a language with a parser is much more complicated that hosted DSLs.

I really think that the best way of learning any technology is to practice. That is why I am going to do it in a practical way, building a small language: a dependency injection language.

We are going to implement a language to define beans and give values to its attributes via setters or contructors. The value types allowed for attributes will be:

  • References to other beans
  • Basic types: String, Integer, Long, boolean.
  • Lists
  • Maps

In addition, it will allow us to define a default prefix package for beans that will ease the declaration of the bean type. So for example, we might define a bean type as “dao.UserDAO” instead of the more verbose “com.centuryminds.tutorial.dao.UserDAO”.

# This is a comment
default package prefix com.centuryminds.tutorial

def bean userDAO1 of type dao.UserDAO as
   tableName: "test"
   cacheSize: 200
end

def bean userDAO2 of type dao.UserDAO as
   init "test", 200 # constructor params
   otherAttribute: "other"
end

def bean userManager of type manager.UserManager as
   userDAO: userDAO1
end

def bean myBean of type com.nodefaultpackage.bean.Mybean as
   listVar: ["test", "othertest"]
   mapVar: {"test": 3, "another": 4}
end

ANTLR basics

A parser constructed with a tool like ANTLR needs to be splitted into several phases. In this way each part keeps simpler. These phases generally are the following:

  • Lexer: It reads a character stream and generates a sequential list of recognized tokens.
  • Parser: It receives a list of tokens and identifies the structure of the sentences according to the grammar. Once we have identified the structure we can generate two kinds of outputs: 1) Simply generate the final compiler output or 2) Go further and generate an Abstract Syntax Tree (AST henceforth) for later validations/manipulations.
  • AST Semantic Validation Phase: Once we’ve finished validating the source structure, we have to validate it semantically. A semantic error means something is grammatically correct but completly meaningless. This phase can be invoked plenty of times and/or work in association with a pre-semantic phase, depending on the grammar complexity.
  • AST Manipulation Phases: Once we know that what the source code “says” is correct and meaningful, we can pass it through a set of AST manipulation phases that transform the tree representing the code into something more specialized, optimized, etc. For example, removing unused variables, adding extra functionality, static check for nulls, and so forth.
  • Output Generation Phase: This is the last phase of a compiler, in which we generate the output: x86 code, Java code, bytecode, xml, whatever you want.

Do we need all the phases? Of course not, it depends totally on the complexity of the grammar. The mandatory ones are lexer and parser.

As for our small language, we’ll implement the following phases:

  • Lexer/Parser: With ANTLR you can define both in the same grammar file.
  • Pre-semantic phase: We are going to identify all the beans present in a file and its associated class types. This will permit us to not depend on the order the beans are defined (without this phase we wouldn’t be able to reference another bean that is defined below in the file, since we haven’t parsed that bean yet).
  • Semantic validation: Validation of all the types of the code. Has UserManager a field “dao” that is of type UserDAO? Does UserDAO has a field named “table” of type string that we can assign the literal “myTable”?
  • Output generation phase: In our case it is going to be a Java object structure ready to be accessed by our DI framework. Other options comprise the generation of a Spring XML file, Guice code, etc.

Basic ANTLR Examples

To develop with ANTLR I recommend ANTLRWorks. This tool is a specialized IDE that supports the definition of ANTLR based languages. Furthermore, with it (and with its built-in debugger!) we’ll be able to test our lexer/parsers.

Let’s start off with a basic example:

grammar Injector;
options {
 output=AST;
}
tokens{
 BEANS;
 BEAN;
 PACKAGE_LIST;
}
@header {
package com.centuryminds.injector;
}
@lexer::header
{
package com.centuryminds.injector;
}

beans	:	beanDef+ -> ^(BEANS beanDef+)
;

beanDef: 'def' Identifier 'of' 'type' packageName -> ^(BEAN Identifier packageName)
;

packageName
	: Identifier ('.' Identifier)*	-> ^(PACKAGE_LIST Identifier+)
;

Identifier    : LETTER ( LETTER | '0'..'9' | '_' )*
;

fragment
LETTER: ('a'..'z' | 'A'..'Z')
;

WS  :  (' '|'\t') {$channel=HIDDEN;}
    ;
NEWLINE : ('\n'|'\r' ) {$channel=HIDDEN;}
    ;

LINE_COMMENT
    : '#' ~('\n'|'\r')* '\r'? NEWLINE {$channel=HIDDEN;}
    ;

This grammar recognizes this kind of source code:

def bean1 of type one.example.Example
def bean2 of type another.example
def bean3 of type NoPackage

This is the AST generated one the code above has been parsed using our grammar:
simplebeans.png

But, let’s take a look at each statement in the grammar file:

First of all, we define the grammar name:

grammar Injector;

It’s vital that the grammar file is named accordingly to the grammar name. In this case the file would be named “Injector.g”

In the next line we define that the output of the parser will be an AST:

options {
 output=AST;
}

These lines:

tokens{
 BEANS;
 BEAN;
 PACKAGE_LIST;
}

describe tokens that have not been read from the input -aka virtual tokens, but generated by the parser. In the example, we create three virtual tokens, one for the Beans list, one for each bean definition and one for a Java package definition.

The following lines set the Java package for the generated Lexer and Parser:

@header {
package com.centuryminds.injector;
}
@lexer::header
{
package com.centuryminds.injector;
}

After this header code, we have two kinds of statements: token definitions and rules definitions. Tokens are recognized by the lexer. Rules are applied by the parser to identify the structure of the source code.

Tokens can be defined in two ways:

  • As a named token:
    WORD: ('a'..'z' | 'A'..'Z')+

    It might be referenced by other Tokens/Rules as to avoid repeated code. The name of the tokens must start with an upper case letter. E.g. “Word” is a valid token identifier, “word” is not ( It will be identified as an action).

  • As an anonymous token inside a rule:
    rule: 'define' 'alias' WORD 'as' WORD

    where ‘define’, ‘alias’ and ‘as’ are anonymous tokens.

We can also define fragment tokens. These are not really tokens by themselves, but fragments to avoid repetition. For example, LETTER fragment in the following code:

Identifier    : LETTER ( LETTER | '0'..'9' | '_' )*
;

fragment
LETTER: ('a'..'z' | 'A'..'Z')
;

Oftentimes, we don’t want some tokens to be visible for the parser, so that it doesn’t have to deal with them. In this case, we can ignore them or locate them inside a different token channel. There is a special channel named HIDDEN that maintains the information but hides it to the parser. In our example we hide the whitespaces, new lines and comments.

WS  :  (' '|'\t') {$channel=HIDDEN;}
    ;
NEWLINE : ('\n'|'\r' ) {$channel=HIDDEN;}
    ;

LINE_COMMENT
    : '#' ~('\n'|'\r')* '\r'? NEWLINE {$channel=HIDDEN;}
    ;

Finally, we define the rules:

beans	:	beanDef+ -> ^(BEANS beanDef+)
;

beanDef: 'def' Identifier 'of' 'type' packageName -> ^(BEAN Identifier packageName)
;

packageName
	: Identifier ('.' Identifier)*	-> ^(PACKAGE_LIST Identifier+)
;

A rule has the following syntax for AST generation:

ruleName : ruleAction  -> ^(ROOT_ELEMENT child1 child2 ...);

For example:

beanDef: 'def' Identifier 'of' 'type' packageName -> ^(BEAN Identifier packageName);

Here you are a rule named beanDef that recognizes “def myBean of type a.b.c”-like strings. In order to recognize the package name it invokes a sub-rule called packageName that in turn returns a sub-AST. Once we parse the structure, we build its corresponding AST with the virtual token BEAN as root, Identifier as the first child and packageName sub tree as the second one.

Of course a rule can have more options: rule parameters, return types, init blocks, etc. I recommend to take a look at the documentation, or await the next tutorial :).

Arbitrary Java code can be attached at any moment of the parsing:

beanDef: 'def' {System.out.println("after def");}
              Identifier  {System.out.println("Identifier: "+ $Identifier.text);}
              'of' 'type' packageName  {System.out.println("end of the rule");}
               -> ^(BEAN Identifier packageName);

The ANTLR tokens and rules can be accessed from this Java code: 1) The token text can be retrieved in the form $Identifier.text. 2) The AST corresponding to the sub-rule using $packageName.start

I’m wrapping it up. In the second part of this tutorial we will see the complete grammar file and the pre-semantic phase. Meanwhile, you can try to complete the grammar as an exercise.

Links:

Weak and Soft References in Java

Types of References in Java

Before I get to the point, let me introduce you a couple of classes we’ll count on when going through examples later.

The first one is Item:

package com.centuryminds.softreferences;

/**
 * An item
 */
class Item
{
  //class members
}

And here comes Group:

package com.centuryminds.softreferences;

import java.util.ArrayList;
import java.util.List;

/**
 * A group of {@link Item}
 */
public class Group<T extends Item>
{
  private final List<T> items = new ArrayList<T>();

  public void add(T item)
  {
    items.add(item);
  }

  // other methods
  // ...
}

Let’s start the ball rolling. This is the most common way to create a reference to an object from another one (okay, forget about the factories, IoC and such for a while):

Item item = new Item();

The item element is called a strong reference. Why is regarded as strong? A new well-kown player named Garbage Collector -GC from now on- comes up , which is responsible of taking care (i.e. freeing) of the memory resources. When an object Client, holding a reference to item:

A strong reference

decides to not use item anymore:

Not needed anymore

after an undetermined time, the GC might decide to dispose of the instance formerly referenced by item.

To illustrate a dime a dozen problem associated to strong references, let’s suppose we have an object Group, referencing a bunch of Item elements through its internal items list member.

Items in a Group

As we can see in the figure, there are a couple of external references to the Items. What happens when these references are not needed anymore and stop pointing at those Items?

No more external references

At this point in time, the logic of our application might require us to remove the references to the Items in our Group instance, since they are not used anymore. That’s a burden every now and then. Actually, what we are doing is duplicating efforts, since this should be the main responsibility of the GC.

WeakReferences

A WeakReference is a reference which does not prevent an object to be reclaimed by the Garbage Collector. A WeakReference allows you to pass the GC the buck when determining the reachability of an object for you.

A weak reference

Here is how a WeakReference is created:

package com.centuryminds.softreferences;

/**
 * Creating a WeakReference
 */
class A
{
  private final WeakReference<B> b = new WeakReference<B>(new B());

  public B getB()
  {
    return b.get();
  }
}

A small hint here: the method getB() might return null if there are no strong references to the internal reference b. As a matter of fact, the previous is an awful example, since the first call to getB() could return null in case the GC decided to reclaim b and release the memory assigned to it before that method call. Not good.

SoftReferences

Another far more interesting type of reference we may take advantage of is the SoftReference. In short, this type of reference is like a WeakReference, but tells the GC to not reclaim the wrapped object if there is enough free memory. In other words, if the the GC needs more free memory after reclaiming the objects reachable through strong and weak references, then it will reclaim the instances only reachable through soft references. This, as we will see, makes an excellent candidate for becoming a smart invalidation policy within a cache.

An all-dancing cache

We are going to build up a cache of objects using soft references. Motivation for a cache:

  1. There are some elements which are very expensive to retrieve
  2. Those elements are used frequently
  3. The number of such elements (or the number of the most frequently used) is limited

In our particular case, the expected behavior of our cache will be:

The objects stored in the cache will be discarded if they are referenced by the cache only AND more free memory is required.

The Garbage Collector will be in charge of that. The ball is in its court now.

A code snippet is worth a thousand words:

package com.centuryminds.softreferences;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

/**
 * Generic cache based on SoftReference's
 */
public class Cache<T>
{
  private final Map<String, SoftReference<T>> cache = new HashMap<String, SoftReference<T>>();

  /**
   * Look an element up by its id
   */
  public T get(final String id)
  {
    T elem = null;

    if (cache.containsKey(id))
    {
      SoftReference<T> ref = cache.get(id);
      elem = ref.get();
    }

    // elem could value null here in two cases:
    // (1) it was not stored in the cache
    // (2) it was garbage collected
    if (elem == null)
    {
      elem = getElemFromExternalService(id);
      cache.put(id, new SoftReference<T>(elem));
    }

    return elem;
  }
}

This cache manages elements of unknown types at compile-time, which are retrieved by their ids through calls to getElemFromExternalService(id). This method may be a private member of the cache, a callback or whatever. The key point here is that the elements are stored as soft references. When an external entity asks the cache for an element, it is linked to it through a strong reference:

// returns the wrapped object
elem = ref.get();
...
// a strong reference for the callee
return elem;

Bear in mind this is vital to our purposes, since the existence of a strong reference whilst the object is being used will prevent it from being garbage-collected.

Extra goodies

  • WeakHashMap is a Map whose keys are stored using weak references. Refer to the Javadocs for further information.
  • A wrapped object by a WeakReference becoming rubbish does not imply that the WeakReference itself defuncts. We thus have to perform some kind of cleanup of those references. WeakReference has got a contructor which accepts a ReferenceQueue, which is used to track stale references to WeakReferences objects. Take a look at the Javadocs to get more information on how to use it.
  • There is another type reference named phantom reference, but it is not worth the hassle explaining it for the purposes of this post.
  • An open question: if WeakHashMap exists, what happened to SoftHashMap? I don’t want to make a mountain out of a molehill, but this class would be at least as useful as WeakHashMap, if not more.

Java static imports + Fluent interfaces + Builder pattern= DSL

After having written nothing for a long time I am back to talk about an interesting bunch of java features. I am talking about DSL in Java, not as clean and powerful as in Ruby but, I think, very interesting for Java developers.

Static import

So, let’s start with static import, a nice Java feature introduced in its 5th version. Until Java 5, we could only import classes for using in our code, so that, instead of using something as ugly as java.util.List list= new java.util.ArrayList() we could simplify by importing the List and ArrayList classes and omit the package class in the creation and usage of the objects.

But, what happens when we want to use static methods or properties of other classes?

MyFunnyClass.myMoreFunnierMethod(param)
MyFunnyClass.NotSoFunnyMethod(param)

Our code gets cluttered by retyping the class part, when this shouldn’t be necessary. Wouldn’t it be nice if we were able to express ‘I want to use the following static methods in my class, and then use them as methods defined in our class’ ?

We are lucky, Sun engineers introduced the static import feature in Java5. So how do we use it? This is a piece of cake:

import static mypackage.MyClass.interestingMethod
...
interestingMethod("Look ma, I don't need referencing to MyClass!")

or we can use wildcards instead:

import static mypackage.MyClass.*
...
interestingMethod("Look ma, I don't need referencing to MyClass!")
otherInterestingMethod("Look ma, I don't need referencing to MyClass!")

It doesn’t look very useful for what we usually code, and used incorrectly, can derive in a fist of method calls that we don’t know where they come from. But this feature is going to be crucial for DSLs design in Java…

Fluent interfaces

Fluent interfaces are a way of designing interfaces that allows us to chain method calls, making our code more readable. So, what does it looks like?

Without fluent interfaces:

Person person= new Person();
person.setName("John");
person.setSurname ("Smith");
person.setPet(new Dog("Charly"));
person.setClothingStyle(ClothingStyle.CASUAL);

With a fluent interface API:

Person person = new Person().name("John").surname("Smith").pet(new Dog("Charly")).clothingStyle(ClothingStyle.CASUAL)

Fluent interfaces make our code look much better.

Using chained methods is as easy as returning the object instance (this) at the end of each fluent method:

public class Person{
...
  public Person name(String name){
     this._name=name;
     return this;
  }
...
}

Fluent interfaces are compatible with having accessor methods (set* and get*) in our classes. Basically, the goal is to ease the API usage and uplift the readability/expressivity of our code.
You can get more information about fluent interfaces in Martin Fowler Blog.

Builder Pattern

The previous two features look very interesting, don’t they? And it seems that both of them can be used to improve our code readability, and actually they do. But there is a last feature that takes advantage of them , we are talking about the Builder Pattern.

Quoted from the Wikipedia:

The Builder Pattern is a software design pattern. The intention is to separate the construction of a complex object from its representation so that the same construction process can create different representations.

In short, we are going to have an object that facilitates the construction of …other objects! This implies that such a pattern is only useful when we design interfaces for objects that we are going to build up many times with different parameterization or to designing interfaces.

I am the sort of person that prefers an example over loads of paragraphs explaining it , hence go carefully through the following code:

package test;

import java.util.Calendar;
import static java.util.Calendar.* ;
import java.util.Date;

public final class TimeUtil {

    public static DateEx now() {
        return new DateEx(new Date());

    }

    public static DateEx tomorrow() {
        DateEx date = new DateEx(new Date());
        return date.add(days(1));
    }

    public static DateEx yesterday() {
        DateEx date = new DateEx(new Date());
        return date.subtract(days(1));
    }

    public static TimeUnit months(int n) {
        return new TimeUnit(MONTH, n);
    }

    public static TimeUnit years(int n) {
        return new TimeUnit(YEAR, n);
    }

    public static TimeUnit days(int n) {
        return new TimeUnit(DAY_OF_MONTH, n);
    }

    public static DateEx date(Date date) {
        return new DateEx(date);

    }

    private static final class TimeUnit {
        private final int type;
        private final int size;

        public TimeUnit(int type, int size) {
            this.type = type;
            this.size = size;
        }
    }

    public static final class DateEx {

        private final Calendar date;

        public DateEx(Date date) {

            this.date = Calendar.getInstance();
            this.date.setTime(date);
        }

        public Date toDate() {
            return date.getTime ();
        }

        public DateEx add(TimeUnit unit) {
            date.add(unit.type, unit.size);
            return this;

        }

        public DateEx subtract(TimeUnit unit) {
            date.add(unit.type, -unit.size);
            return this;

        }

        public DateEx clearTime() {
            date.set(HOUR_OF_DAY, 0);
            date.clear(MINUTE);
            date.clear (SECOND);
            date.clear(MILLISECOND);
            return this;

        }

        public DateEx firstDayOfMoth() {
            date.set(DAY_OF_MONTH, 1);
            return this;
        }

        public String toString() {
            return date.getTime().toString();

        }
    }
}

No worries, I am going to explain each line of code, or at least the more interesting ones:

import static java.util.Calendar.* ;

This rings a bell, I hope. In this case, importing Calendar static fields allows us to use them as:

            date.set(HOUR_OF_DAY, 0);
            date.clear(MINUTE);
            date.clear (SECOND);
            date.clear(MILLISECOND);

We are building a date builder, so we need another class especialized in the construction of java.util.Date objects. This DateEx inner class for:

    public static final class DateEx {
    ...
   }

The key point here is that DateEx is a construction utility that uses fluent interfaces, so that we can chain methods calls to DateEx objects like:

DateEx dateBuilder= new DateEx(new Date()).firstDayOfMonth().clearTime()

and finally get the date object:

Date date= dateBuilder.toDate()

This code seems alright, yet did you notice what an ugly code we are using to note “now” ? new DateEx(new Date()) ??? What the hell is this? If I want to express “now” I want something that actually does it, and “new DateEx(new Date..” doesn’t at all. Luckily, we might define convenient methods for that sort of things:

    public static DateEx now() {
        return new DateEx(new Date());

    }

Now, if we import the now static method in our class we can rewrite the previous code as:

DateEx dateBuilder= now().firstDayOfMonth().clearTime()

This is the kind of code that makes me happy (Yes, I know…). Look at it, and at first glance, you realize “hey, he is clearing the time part of the first day of the current month”.

Furthermore, we can add a couple of convenient methods to our new little API:

    public static DateEx tomorrow();
    public static DateEx yesterday();

There is also a TimeUnit inner class that allows us to express time units in order to perform time operations to our DateEx objects. For example, what if we wanted to get 1 month and 10 days before the current date? We can do it with our TimeUnit classes and static util methods as:

dateBuilder.subtract(months(1)).subtract(days(10));

Cooler than using our good ol’ Calendar friend.

What kind of things can we do with this example API?

package test;

import static test.TimeUtil.*;
import java.util.Date;

public class Example {
    public static void main(String [] params){

        Date date= new Date();
        System.out.println (date(date).add(years(1)));

        System.out.println(now().toDate());
        System.out.println(now().add(days(2)).add(months(1)).subtract(years(1)).clearTime().toDate());
        System.out.println(yesterday()+" - "+now()+" - "+tomorrow());
        System.out.println(now().clearTime().firstDayOfMoth());
    }
}

Neat, it is not perfect, a lot of brackets are needed which only mess the code up, but as I see it, we have improved the expressivity of our code. In any case, my advice is to learn a new language like Ruby or Groovy, it opens your mind and teaches you different ways of doing things.

On the other hand, Java 7 specification is going to define closures for the Java language, so in the future we are going to be able to do more interesting things!

Paths absolutos

Voy a ser corto. Tatuaros en la frente: ¡NO UTILIZARÉ PATHS ABSOLUTOS EN MI APLICACIÓN!

Al resto del equipo no le gusta descargase una clase en la que lo primero que te encuentras es:
"D:\workspace\proyectox\drl\fichero.drl"

¡Usa el classpath y rutas relativas!

Sí, hay excepciones a la regla, pero generalmente aplican a sistemas de producción, no de desarrollo. Por ejemplo, el administrador puede querer que los logs vayan a /var/logs/aplicación, pero tu no quieres poner los logs en tu equipo en C:\Documents and Settings\bob\Mis Documentos\logs.

You can only have two

We are going to learn a bit about a useful tool to help us make decisions prioritizing some traits of our work over the remainder ones. Let me introduce you to the cost-time-quality triangle:

Cost-Time-Quality Triangle

The triangle itself is nothing new or recently discovered, I am sure every manager worldwide is aware of it, or at least should be! Basically, what we have is a set of three properties (quality, cost and time), and the point here is that, at a given point in time, you can only count on two of them. In other words, if we applied this to a wide range of ways to accomplish with a task, it tells us that we can´t wind up with a cheap and high-quality result in a short time. I will refer to the title of this post: you can only have two. With three elements at play, picking them two by two, we get three possibilities:

A) Quality & Time

High-quality solutions in short times. A steal? Uhmm, beware the available budget!

B) Cost & Time

Cheap and swift, then? The quality will suffer!

C) Quality & Cost

Cheap and good? Be sure you finish it in a realistic span of time! Crackin’ the whip would help …

No combination is better than the others, it depends on your situation. Personally, I find the hardest part to find a balance between the three of them so that you feel sort of successful when you finish the task.

Anemic Domain Model Antipattern

Anemic ¿Qué!??

Hoy toca hablar de patrones, o mejor dicho, de anti patrones. Esas cosas que se deben evitar por norma general.

Mucha de la gente que venimos de lenguajes procedurales (vaya palabro…) tipo C, tendemos a pensar de esta forma a la hora de programar en Java. ¿Por qué? Por que C no es un lenguaje orientado a objetos. Para representar en C un dato usamos lo siguiente:

typedef struct point { int x,y; } point;
....
y usamos punto.x

Así que cuando vamos a un lenguaje orientado a objetos tendemos a hacer cosas de este tipo:

public class Casa{
private String nombre;
private boolean alquilada;
private boolean habitable;
public void setNombre()...
public String getNombre()...
public void setAlquilada()...
public boolean isAlquilada()...
....
}

public class Persona{
private String nombre;
private List casas;
public void setNombre()...
public String getNombre()...
public void setCasas()...
public List getCasas()...
}
..

List casasNoAlquiladas= new ArrayList();
for(Persona persona: personas){
for (Casa casa : persona.getCasas()){
if (! casa.isAlquilada() && casa.isHabitable()){
casasNoAlquiladas.add(casa);
}
}
}

….

¿Cuál es el problema con esto? Pues que estamos utilizando las clases de negocio como simples estructuras de datos. Hemos avanzado en la tecnología, ¡ Avancemos en su uso también! Vale, siempre lo has hecho así, te sientes cómodo con esta solución ¿Con qué problemas te vas a encontrar?

  • Lógica de negocio dispersa por toda la aplicación, seguramente incluso repetida.
  • Complejidad a la hora de hacer las clases controladoras
  • Estamos exponiendo la forma en que mantenemos las casas al exterior. Solo debemos exponer las entities, no los value objects! (esto daría para otro post)
  • ¿La lista de casas que devolvemos es inmutable? ¡Cuidado!
  • Sumando todo lo anterior: Más complejidad = más bugs, además de menos extensible

Bueno y ¿Cómo lo solucionaríamos? Muy fácil, introduciendo la lógica de negocio en las clases de negocio:

public class Casa{

….

private final String nombre;
private boolean alquilada;
private boolean habitable;
public String getNombre()...
public void setAlquilada()...
public boolean isAlquilada()...
public boolean isAlquilable(){
return (! casa.isAlquilada() && casa.isHabitable());
}

….
}

public class Persona{
private String nombre;
private List casas;
public void setNombre()...
public String getNombre()...
public void setCasas()...
public List getCasasAlquilables(){
List list= new ArrayList();
for (Casa casa: casas){
if (casa.isAlquilable()) list.add(casa);
}
return list;
}
}
..

List casasNoAlquiladas= new ArrayList();
for(Persona persona: personas){
casasNoAlquiladas.addAll(persona.getCasasAlquilables());
}

Más fácil ¿Verdad? Si no conocías este error común, seguro que ahora te vienen a la memoria un montón de casos en los que podrías ahorrar mucho en código y hacerlo mucho más extensible.

Otro ejemplo: En cierto cliente, hace un cierto tiempo y haciendo cierta aplicación :) De una clase muy importante en el modelo (Entity) sacabamos unos cuantos informes. En un momento dado, me pidieron que si se podía cambiar cierta lógica a la hora de generar los informes. Mi respuesta fue: tardo 2 segundos (y uno para pulsar ctrl+shif+T en Eclipse!! ). ¿Por qué? Porque mi clase de ese entity tan importante tenía lo siguiente:

List<Dato> getSubObjetosQueCumplenCiertaCondiciónDeNegocio(){
for....{
if (obj.condicion1() && obj.condicion2() && entity.....)

lista.add(...)

}
}

Lo que me pedían era un cambio de negocio. Yo había entendido mál, un objeto de tipo Dato debía de cumplir obj.condicion() && obj.condicion3(), pero el cambio no suponía el menor esfuerzo. ¿Cuánto hubiese costado si hubiesemos tenido este código disperso por toda la aplicación?

Se puede discutir si incluir los DAO dentro del objeto de negocio es bueno o malo (Rails y Grails lo hacen), si algúna lógica concreta debería ir en los controladores, pero al menos este tipo de cosas creo que pueden ayudarte bastante.

Bueno, no se si ha quedado claro, hoy no he dormido mucho y estoy muuuuuy cansado :D

You Need Code Reviews

Look at this code:

(within a while body)

...
if (log.isDebugEnabled()) log.debug("Parsing line " + (lineNumber++));
...
lineNumber used here
...

You might be wondering: what´s wrong with it? Well, it turns out that this sort of construction it could become extremely difficult to spot in certain conditions. Imagine a hypothetical situation where this code is not working properly in the production environment, and meanwhile the developer in charge of this block of code -the guy as cool as a cucumber- is totally sure about the correctness of it. Okay, you got it, you may be thinking of me: “How noob this guy is!”; but Hey!, sometimes you are toiling late in the night and this kind of bugs pass unnoticed until you receive an email from your Development Manager muttering:

Subject: Potential bug

I have come across with this statement -incidentally- while surfing the code. Beware that the log will be printed out only if the log level is set to DEBUG, so the lineNumber variable won´t be incremented.

All the best,

Your Development Manager

Guess which level the Production Support had established in their environment? Fortunately, I started off saying “Imagine a hypothetical situation …“.

Share your knowledge

Thomas Jefferson said:

And no matter how many people share it, the idea is not diminished. When I hear your idea, I gain knowledge without diminishing anything of yours. In the same way, if you use your candle to light mine, I get light without darkening your. Like fire, ideas encompass the globe without lessening their density.

Sometimes, in this hectic world, you realise that your knowledge about a subject has increased considerably, and probably at that moment you are an expert on it. The “problem” now is how you ought to handle that situation in regards to your team mates. You can keep such expertise for your own benefit, considering them a sort of nuissance, if not worse. But that is not supportive. As I see it, helping your co-workers is a professional duty, no matter the reason. No matter the guy. You must do it because you must do it. And that´s all. There shouldn´t have to exist more reasons besides that one. Yeah, I know, there are lotsa situations where excuses arise in order not to help someone, but anyway I think it is a good principle to start with. Write it down in your tickler file.

Nonetheless, there are some important benefits of being supportive and willing to give others a hand:

  1. You can cause a great impact in the morale of your huddle, because your positive attitude might make them want to better themselves in turn. The overall competence of your team spikes. Betcha! That´s good for you as well. If this doesn´t work, pull out.
  2. You may think you are an expert. Believe me: even experts are requested to answer questions they don´t know about! IMHO, I consider this awesome. The search for those answers permits you to assimilate unexplored areas of the topic on discussion. Therefore, you are gaining more insight, which is always neat. For example, the other day someone asked me about subversion, and how this system performs the merging. I thought I had that under control. I explained to him the basics of the merging in subversion, the reason it should be called diff-and-apply instead of merging, how two revisions from the origin and destination trees are applied to the working copy, and so on. So far, so good. All the same, point in time, he asked me how a merge was actually applied to a specific file in the working copy. That was kinda going thorugh bad times, because I didn´t understand it seamlessly, hence I wasn´t able to provide him with an answer. Well, in fact, I had to look up that section in a subversion book, read it thoroughly, sink in all that stuff, and lastly give to him the right answer. I could have told him to grab a book and look it up. That would have been a lazy behaviour and, what it´s much worse, I would still be thinking I have that part under control now. It´s wonderful not to be an expert in nearly anything, isn´t it?
  3. Corollary: the rest of the team come to trust they can rely on you when they feel they´re dead in the water.

Corollary to the last Corollary: Be nice ;)