¿Es el uso de interfaces uno a uno con entidades de dominio una buena o mala práctica? ¿Por qué?


Una cosa que veo en algunas aplicaciones empresariales DDD en las que trabajo, es el uso de interfaces que son idénticas a las entidades de dominio, con un mapeo uno a uno de propiedades y funciones. De hecho, un objeto de dominio siempre se usa a través de su interfaz uno a uno, y todas las entidades de dominio tienen una interfaz uno a uno en este estilo.

Por ejemplo:

Cuenta de objeto de dominio:

public class Account : IAccount
{
     public string Name {get;set;}
     //...some more fields that are also in IAccount
     public decimal Balance {get;set;}
}

Y su interfaz coincidente

public interface IAccount
{
   string Name {get;set;}
   //... all the fields in Account
   decimal Balance {get;set;}
}

Pero últimamente me he vuelto cada vez más convencido de que esto es, de hecho, un anti-patrón.
Lo dirigí por algunos arquitectos en la comunidad de código abierto, y dicen que esto se basa en errores o fallas de diseño, en algún lugar de la cadena de diseño.

Así que les digo a mis colegas que deberían dejar de crear interfaces para los objetos de Dominio. Porque no hay ningún propósito para ellos, y usted tiene que actualizar la interfaz cada vez que actualice las entidades de dominio.

Primero se hizo la afirmación de que estas interfaces proporcionan 'desacoplamiento', pero contrarresto que debido a que las interfaces tienen una relación uno-a-uno con las entidades de dominio que realmente no proporcionan ningún desacoplamiento, un cambio en la interfaz significa un cambio en la entidad de dominio y viceversa.

La siguiente afirmación es que necesitamos las interfaces para fines de prueba. Mi contador es que Rhino-mocks proporciona la burla y el stubbing de clases concretas. Pero afirman que Rhino-burles tiene problemas con las clases de concreto. No se si compro eso, incluso si rhino-mocks tiene problemas con clases concretas, eso no significa necesariamente que debamos usar interfaces para las entidades de dominio.

Así que tengo curiosidad:

¿Por qué tendría interfaces uno a uno para sus entidades de dominio?

¿Por qué no?

¿Por qué es una buena o mala práctica?

Gracias por leer!

EDIT : Debo tener en cuenta que uso interfaces todo el tiempo, y creo que si se llama para que voy a utilizar una interfaz en la gota de Hat. Pero me refiero específicamente a las entidades de dominio con interfaces uno a uno.

Author: Mark Rogers, 2009-05-05

6 answers

Es una mala práctica como se describe, pero...

No hay ninguna razón específica para que sus interfaces necesiten ser diferentes a las entidades de su dominio; a veces realmente es la asignación correcta. Pero es sospechoso que siempre sea así. El punto de preocupación es la cuestión de si las interfaces fueron realmente diseñadas o no, o si simplemente se lanzaron en su lugar por falta de tiempo / pereza.

Para usar su ejemplo, la interfaz de iAccount que describe expone getters y setters en el objeto Account; parece un poco extraño y poco probable que todo lo que usa una Cuenta tenga la necesidad de establecer el saldo en la cuenta, y que ese permiso implícito se especifique en ese nivel de interfaz. ¿No hay ningún lugar en su sistema en el que desee simplemente verificar pero no establecer el saldo de la cuenta?

 8
Author: Paul Sonier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 17:13:22

La mayor razón para especificar siempre los objetos de dominio como interfaces en lugar de directamente como clases es para darle un grado de libertad en la implementación. En su ejemplo solo tiene un tipo de iAccount, por lo que es un poco redunant.

Pero qué pasaría si tuvieras, por ejemplo:

public class Account : IAccount { ... }       // Usual account, persistent
public class MockAccount : IAccount { ... }   // Test mock object
public class TransAccount : IAccount { ... }  // Account, not persistent
public class SimAccount : IAccount { ... }    // Account in a performance sim

Y así sucesivamente?

Al definir los objetos de dominio como interfaces, puede reemplazar las implementaciones sin alterar la definición de su dominio.

 7
Author: Charlie Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 17:31:10

En general, si mis clases no van a ser parte de un patrón de diseño como Estrategia o Visitante yo no agregar interfaces.

Agregar interfaces es realmente útil para patrones de diseño como Estrategia y Visitante, pero en esos casos no copio los getters y setters de las clases de dominio. En su lugar, creo interfaces que son específicas para las interfaces de patrón de diseño que creo.

interface SomeStrategy {
   void doSomething(StrategyData data);
}

interface StrategyData {
   String getProperty1();

   String getProperty2();
} 

Que me permite permitir que las clases de dominio implementen esas interfaces, o usar Patrón de adaptador. Me parece que este es un enfoque mucho más limpio que simplemente la creación de interfaces por el bien de la misma.

El diseño siempre debe reducir la incertidumbre. La creación de interfaces por el bien de ella no reduce la incertidumbre, de hecho, probablemente aumenta la confusión, ya que no tiene ningún sentido.

 5
Author: Steven Devijver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 17:31:21

Las interfaces Uno a uno en las entidades son un anti-patrón

James Gregory lo puso mejor que yo aquí .

 3
Author: Mark Rogers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-12 19:10:45

Estoy de acuerdo contigo. Las interfaces deben actuar como un contrato, por lo que no tiene valor tener interfaces uno a uno con entidades de dominio. Puede ser útil si desea abstraer un cierto comportamiento. Pero, esto funcionará en ciertos casos.

 1
Author: Memo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-17 00:48:24

¿Por qué este se ha esfumado?

Encuentro que tener una interfaz para un objeto de dominio, como dijo Charlie Martin, me permite elegir mi implementación.

Un ejemplo fundamental es el identificador (object.Id) para un objeto, esto será diferente dependiendo de dónde almacene ese objeto y la responsabilidad de crearlo puede o no recaer en la implementación de los datos más adelante. En SQL Server puede optar por un autonumber, pero en Azure table storage puede optar por un Guid, pero no quieres tener que cambiar la lógica de negocio de tu aplicación porque cambias dónde almacenas tus datos.

Puedo o no elegir que se mantenga mi objeto de dominio, o incluso usarlo en la capa de presentación; depende del alcance de mi aplicación cuál es el mejor. Pero agregar un conjunto de interfaces de dominio comunes en una capa común me permite escribir servicios en contra de ellos y reutilizarlos una y otra vez.

Repasaríamos el mismo argumento sobre lo que debería ser una dirección si si no tuviera IAddress, los nuevos programadores estarían reescribiendo cosas para tarjetas de crédito si no fuera por ICreditCard.

La etiqueta anti-patrón es un mal uso del lenguaje, es una simplificación excesiva para describir el valor de las soluciones a tareas complejas y variadas.

Hay un lugar para la mayoría de los patrones, incluso el Singleton difamado, lo que significa que no es un "anti-patrón", al menos en lo que el término sugiere.

 0
Author: Anthony Johnston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-26 07:35:36