Ventajas de tener identificado y aislado el dominio

El dominio de una app es todo aquello relacionado con la lógica de negocio.

Si tienes una persona de negocio dentro de tu proyecto, piensa que son aquellas cosas que solo hablarías con esa persona de negocio, esto me ayuda a identificarlo mejor.

Si no se tiene experiencia con testing, código testable o arquitectura de software, una de las cosas que más suele costar es identificar conceptos de dominio o negocio.

El dominio de una app es como Matrix aunque no sepamos verlo esta por todas partes.

Si estos conceptos están dispersos por ejemplo en la capa de presentación o incluso en la capa de datos resulta bastante complicado el mantenimiento de la aplicación.

Vamos a repasar la ventajas que nos aporta tener bien identificado y aislado el dominio, consiguiendo así que sea el core de nuestra app.

Aisla el Dominio

Identificar el dominio es el principio pero para aprovechar todas las ventanas de tener el dominio bien identificado es necesario ocultar los detalles de implementación de sus dependencias.

Esto significa que no dependa de la base de datos, librerías de terceros ni de ninguna tecnología concreta.

Para conseguir que el dominio no dependa de cosas que cambian más frecuentemente y que son menos importantes es necesario hacer uso de la inversión de dependencia.

Estructura

Cuando no tenemos el dominio bien identificado es difícil viendo la estructura del proyecto saber que hace una aplicación.

A mi me ha sucedido tener que hacer una tarea y preguntar donde tengo que tocar porque la estructura del proyecto no me ayuda a identificarlo.

Existen arquitecturas orientadas al dominio como la que propone Eric Evans en su libro.

El libro de Eric Evans de lo que menos habla es de arquitectura, se basa mucho en la importancia de la colaboración creativa entre técnicos y expertos de dominio, pero deja unas pinceladas de una posible arquitectura para aprovechar las ventajas de DDD.

Uncle Bob en su artículo sobre Clean Architecture habla de principios que deben seguir una arquitectura, y al igual que otras arquitecturas como Onion Arquitecture el dominio es el core y debe estar aislado.

Yo particularmente utilizo Clean Architecture y en este artículo conté mis motivos.

Por ejemplo esta aplicación del google I/O 2016 tiene una estructura donde cuesta bastante hacerte una idea de lo que hace echando un vistazo a la estructura.

Esta aplicación del cliente Android de Github no utiliza ninguna de las arquitecturas que he mencionado, sin embargo si tiene bien identificados los conceptos de dominio y es fácil ver conceptos como commit, search, issue etc.. dentro del paquete core.

De este modo si tenemos que añadir una feature o editar una existente es mucho más fácil saber por donde empezar a tocar si el dominio esta bien identificado y sobre todo si esta cubierto por tests.

Testing

Si tenemos bien identificado y aislado el dominio esto quiere decir que tenemos un código testable.

Esto nos va a permitir crear diferentes tipos de test contra el dominio que además de validarlo van a servir de documentación viva.

En estos test vamos a poder simular diferentes escenarios gracias a tener el dominio aislado utilizando dobles de test.

Reutilización de código

Cuando tenemos lógica de dominio mal identificada solemos caer en obsesión por los tipos primitivos y acabamos duplicando esta lógica de negocio al no reconocerla como tal.

public IHttpActionResult Get(string userName)  
{
    if (string.IsNullOrWhiteSpace(userName))
        return this.BadRequest("Invalid user name.");

    var user = this.repository.FindUser(userName.ToUpper());
    return this.Ok(user);
}

[HttpPost]
public IHttpActionResult Register(string candidate)  
{
    if (string.IsNullOrWhiteSpace(candidate))
        return this.BadRequest("Invalid user name.");

    ...
}

Sin embargo si observamos bien nuestro código y sobre todo si entendemos el negocio de nuestra app es interesante crear nuevos tipos como Address, ZipCode, UserName que encapsulan la lógica de negocio.

public IHttpActionResult Get(string candidate)  
{
    UserName userName;
    if (!UserName.TryParse(candidate, out userName))
        return this.BadRequest("Invalid user name.");

    var user = this.repository.FindUser(userName);
    return this.Ok(user);
}

[HttpPost]
public IHttpActionResult Register(string candidate)  
{
    UserName userName;
    if (!UserName.TryParse(candidate, out userName))
        return this.BadRequest("Invalid user name.");

    ...
}

De esta forma reutilizamos la lógica de negocio encapsulada en estas clases de dominio evitando duplicar código.

Escalabilidad

Otra de las ventajas de tener el dominio bien aislado y sin conocer los detalles de implementación de sus dependencias es que vamos a poder sustituir estas dependencias sin que el dominio se vea afectado.

Es fácil pensar que raramente cambiamos SQL Server por Oracle pero hay situaciones mucho menos drásticas que nos darán muchos dolores de cabeza si no ocultamos detalles de implementación.

Todos conocemos el caso de Parse, imaginad los problemas que habrán tenido las aplicaciones que llevaron la dependencia de Parse hasta la capa de presentación.

Otro ejemplo puede ser estar utilizando un SDK en Android y este utiliza una librería de event bus como Otto. Después en una versión superior pasa a utilizar RxJava.

Estos casos suceden más habitualmente de lo que a priori podemos esperar.

Modificaciones en dominio

Si tenemos localizado el dominio y no distribuido por las capas de la aplicación va a ser mucho más sencillo hacer modificaciones, nuevas features etc... que afectan a la lógica de dominio.

Situaciones habituales si no se tiene aislado el dominio es hacer una modificación y olvidarnos también de cambiar eso mismo en otro sitio donde se hacía lo mismo, se hace complicando así cualquier tarea de modificaciones de lógica de negocio.

Conclusiones

Hemos repasado alguna de las ventajas que nos puede aportar tener identificado y aislado el dominio de nuestra aplicación

¿Sueles identificar bien el dominio y aprovechas todas sus ventajas? Ponme un comentario y abrimos el debate :)