2010-12-10 15 views
8

Estoy tratando de diseñar siguiendo los principios SÓLIDOS. Lo que he descubierto es que cuando utiliza el "Principio de responsabilidad única" (el S de SOLID), generalmente debe dividir las clases entre los contenedores de datos y los procesadores de datos. Por ejemplo, si tengo una persona de clase con 5 propiedades que se leen desde DB en lugar de poner todo dentro de una clase, creo una clase Persona con las propiedades y otra clase PersonReader que lee esa información de la base de datos y crea la Persona.Usando el "Principio de Responsabilidad Individual" obliga a mis contenedores a tener incubadoras públicas

Si hago eso, tengo que abrir las propiedades de Person para que PersonReader pueda acceder a ellas, pero luego tengo menos encapsulado que poner todo dentro de un recuadro negro y hacer que las propiedades sean solo legibles.

¿Me falta algo o es un inconveniente de este principio?

Gracias de antemano

EDIT: He cambiado el escritor persona a un lector de persona, porque no había necesidad de hacer los emisores de propiedad pública al principio.

+0

¿Por qué tener un PersonWriter requiere que sus Person setters sean públicos? – Marcie

+0

@Marcie: gracias, fue mi maldad. He editado la pregunta. –

Respuesta

3

La mayoría de las estrategias de acceso a los datos (técnicas de ORM) implican compromisos del tipo que está describiendo. Los menos intrusivos usan la reflexión (o introspección, etc.) para poblar sus entidades cuando lo necesitan (cuando no existen organismos públicos, por ejemplo).

Dicho esto, si sus entidades son solo contenedores de datos (como en el anemic domain model), el principio de responsabilidad única no debería preocuparle mucho, ya que sus objetos no tienen una lógica compleja que sería estropeada por (o interferir con) el código de acceso a datos.

+0

Gracias Jeff, pero no creo que sea un modelo de dominio anémico porque no estoy dividiendo la lógica comercial del modelo de dominio, estoy eliminando la persistencia del modelo de dominio. Todo lo que he leído me lleva por ese camino, solo lea el ejemplo aquí http://p2p.wrox.com/content/articles/design-and-test-driven-development –

+0

@SoMoS - lo siento, quise decir que obtuve la impresión de que ya estaba dividiendo la lógica comercial del modelo de dominio (ya que describió los objetos como meros contenedores). Si ese fuera el caso, no sería demasiado quisquilloso con el SRP. Como no es el caso, es una preocupación justa. –

0

Estás pensando demasiado granularmente. Una clase específica debe leer la base de datos, pero no necesita una clase cuyo único trabajo es crear una Persona. Eso es un desperdicio Un solo lector de base de datos debe ser capaz de crear cualquier clase que provenga de la base de datos, porque ese es su trabajo. Para leer desde la base de datos.

No hay problemas de encapsulación al abrir las propiedades de la persona para que DatabaseReader pueda acceder a ellas, ya que Person es redundante si ninguna clase es capaz de crearlo. Es una parte inherente de la responsabilidad de cualquier clase ser creativo y destructible.

+0

La apertura de una clase permite a otros modificar sus datos cuando no se supone que lo hagan (incluso peor cuando son clases públicas que pueden ser utilizadas por terceros que no saben que tienen una propiedad pública que no deberían tener). úselo. –

+0

De todos modos lo siento, pero su respuesta no tiene nada que ver con mi pregunta. Podría estar de acuerdo en que un lector podría leer todo, el problema sigue ahí, usted tiene instaladores públicos cuando solo tendría captadores si el lector dentro de la clase Person. –

+1

@SoMoS: la mayoría de los lenguajes proporcionan un control más detallado. En C++ puedes usar clases "amigas" y en C# puedes hacer que las propiedades sean internas y tengan clases anidadas. Creo que Java también puede tener un equivalente. , protegido, privado no son los únicos controles de acceso. – Puppy

1

Definitivamente estoy de acuerdo con usted que a veces se encuentra con este problema. Lo he experimentado con la serialización, que es similar a ORM. En mi caso, necesitaba escribir el estado de un objeto en un archivo (binario).

En algunos casos, puede ser apropiado crear una interfaz a través de la cual se pueda escribir y leer el estado interno. Entonces su clase de persona obtendría dos metheds "guardar" y "cargar" (o "escribir" y "leer" o lo que sea que considere apropiado). Estos métodos se pasan un "IPropertyWriter" y "IPropertyReader", respectivamente. (En mi caso los llamé InStream y OutStream).

persona :: save (IPropertyWriter escritor) sería luego hacer

writer.writeProperty("name", this.name); 
writer.writeProperty("age", this.age); 

Se puede argumentar que todavía se está violando el principio de responsabilidad individual, pero yo diría que nadie más debe conocer el funcionamiento interno de la persona. (Especialmente en mi caso de Serialización, tuve que almacenar el estado interno que en parte no es accesible a través de getters). El punto principal es que Person no está acoplado a ningún código de Base de Datos. Su IPropertyWriter puede ser todo. Además, la responsabilidad de "conocer sus propias propiedades" no es realmente una propiedad nueva, sino que se adjunta a todos los objetos de todos modos.

También puede hacer la pregunta qué tan probable es que la persona cambie. Si es muy poco probable, creo que las clases friend como C++ son una buena manera, pero si es probable que cambie, prefiero tener los métodos de serialización en el lugar donde se declaran las propiedades para que no se olvide de actualizar el código dependiente

+0

Mmmm, es un poco complejo, pero de todos modos una solución de trabajo. Definitivamente lo intentaré en mi código. ¡Gracias! –

3

Tal vez me falta algo, pero ¿por qué no escribes un constructor para la clase Persona que acepta todas sus propiedades? De esta forma, el PersonReader podrá crear una persona sin que usted abra las propiedades de la persona.

Otra opción es marcar el colocador de las propiedades de la persona como internas (y hacer que las partes internas del conjunto sean visibles para el ensamblaje del PersonReader, si está en un ensamblaje diferente). Esto le permitirá acceder a las propiedades de la persona, pero evitará que alguien las cambie fuera del ensamblaje.

+0

Tienes razón, pero este fue un ejemplo simple, la situación real es sobre objetos con algunos atributos que no se pueden conocer en el momento de la construcción. –

Cuestiones relacionadas