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

About these ads

6 Responses to Anemic Domain Model Antipattern

  1. juanfri says:

    Hola Rubén,

    Muy bueno el post (y el blog en su conjunto!), voy a aprovechar que escribes en castellano :) para responder y para pegar un enlace al post de Martin Fowler que me parece que inició un poco el tema del Antipatrón: http://www.martinfowler.com/bliki/AnemicDomainModel.html

    En mi opinión el post de Fowler es desde una perspectiva purista con la Orientación a Objetos, esa perspectiva llevaría a incluir la lógica de negocio e incluso la de persistencia en las clases de dominio, lo que sería contraproducente para el desarrollo de las aplicaciones por el acoplamiento, dependencia tecnológica,… aunque la orientación a aspectos puede hacer que acabemos tirando por ahí.

    Tu enfoque me parece más práctico con las tendencias actuales en el desarrollo java, ese tipo de validaciones de negocio que tendemos a poner en los managers estaría muy bien aportándole algo de chicha a los objetos de dominio sin poner en peligros los beneficios de la separación en capas.

    Un Saludo.

  2. Juanfri, solo decirte que el que ha escrito el post no he sido yo, sino Mikel. Luego cuando tenga un rato seguimos con la discusion de todas formas.

    Un saludo!

  3. Jesus says:

    Maaaaadre, un blog de frikies .. voy a dar cania (maldito teclado english).
    Bueno, a mi me hace mucha gracia cuando alguien fomenta los frameworks, las arquitecturas por capas con sus Controllers, sus Managers,
    sus DAOs, sus DTOs y luego se queja de que el modelo esta anemico. ?pero como no va a estar anemico??. Usamos frameworks que definen modelos
    procedurales sacando toda la logica del modelo y poniendola en otras clases … es que no sus dais cuenta que los propios nombres:
    CONTROLLER, MANAGER estan diciendo: ‘dadme objetos lo mas tontos posibles, que yo me encargo de todo’.
    Hay patrones como el Central Controller o como se llame que son totalmente anti OO … pero molan.
    Lo de la Orientacion a Objetos esta muy bien, pero hay que asumir que cuando vendemos nuestro alma a un framework tenemos que pagar un precio,
    y parte de ese precio es volvernos procedurales, asi de claro. Por ejemplo, ?vas a meter una operacion transaccional en una clase de tu modelo?:
    pues no, para eso tienes un Manager. Hombre, puedes ser generoso y dejar a tu objeto del modelo que haga alguna cosita sencilla,
    pero cuando hablamos de transacciones o persistencia nos pasamos la OO por el forro.
    Y que quieres que te diga, puede que los frameworks sean un tanto embrutecedores, pero te hacen la vida mas facil.
    Disculpad acentos, enies y demas carencias

  4. black_mamba says:

    Is this gonna Kill You? No i Dont Think so !

  5. Mikeharvey says:

    New here, from Toronto, Canada

    Just a quick hello from as I’m new to the board. I’ve seen some interesting comments so far.

    To be honest I’m new to forums and computers in general :)

    Mike

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: