¿Cuál es el beneficio de tener modelos POCO puros?

15

¿Cuál es el principal beneficio de tener modelos POCO puros? Entiendo que los Modelos deben ser limpios y simples, pero me gusta mantener el mantenimiento de los objetos secundarios dentro de las clases de modelos. Por ejemplo si tengo un ClassAy ClassBdefinido de la siguiente manera:

public class ClassA
{
    public string MyProp { get; set; }
    public IEnumerable<ClassB> Children { get; }

    public void AddChild(ClassB newChild) { /*... */ }
    public void RemoveChild(ClassB child) { /* ... */ }
}

public class ClassB
{
    public string SomeProp { get; set; }
} 

¿Hay algo inherentemente malo en tener los métodos de agregar y quitar? ¿Debería simplemente exponer la lista y permitir que el código del cliente agregue lo que pase la responsabilidad de validaciones de datos simples como no nulo y no duplicar a otra clase?

Cualquier ayuda es apreciada. Gracias.

Jesse
fuente
Quitaría los métodos Agregar / Eliminar a menos que agreguen algún valor, como traducir un argumento nulo de Clase B en una versión de patrón NullObject del objeto:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham
Si alguna vez ha lidiado con el dolor de cabeza de las clases de ActiveRecord con cientos de métodos que pueden o no ser lo que desea en un momento dado, creo que sería más fácil entender la apelación.
Casey
La razón principal para evitar este diseño en particular es porque va en contra de las pautas de diseño de .net. Es completamente arbitrario, pero la gente espera que la colección tenga los métodos de mutación.
Frank Hileman
@Casey No estoy usando el patrón Active Record, el método de agregar simplemente está haciendo una validación de datos menor. El método remove está ahí porque la colección no está expuesta, simplemente agregan y eliminan de una lista interna. Sin embargo, lo he cambiado para usar un tipo de colección diferente que me permite hacer la validación mientras sigo usando los métodos incorporados Agregar / Eliminar.
Jesse

Respuestas:

42

Sus dos preguntas no están relacionadas.

¿Cuál es el beneficio de tener modelos POCO puros?

Un POCO puro no depende de algún marco empresarial, convención, [] cosita, o está íntimamente conectado a algún objeto que sea igualmente dependiente. En otras palabras, el mundo puede cambiar completamente alrededor de un POCO y simplemente sigue haciendo lo que hace sin importarle. No puede romperlo actualizando un marco, moviéndolo a un nuevo sistema o viéndolo divertido. Simplemente sigue funcionando. Las únicas dependencias son las cosas que pide explícitamente.

POCO no es más que la idea de POJO. La J se cambió a una C porque las personas te miran divertido cuando explicas un concepto que tiene Java en su nombre si esas personas usan C #. La idea no depende del lenguaje. Podrían haberlo llamado simplemente Objetos antiguos simples. ¿Pero quién quiere presumir de usar POO?

Dejaré que Fowler explique los orígenes:

El término fue acuñado mientras Rebecca Parsons, Josh MacKenzie y yo nos estábamos preparando para una charla en una conferencia en septiembre de 2000. En la charla estábamos señalando los muchos beneficios de codificar la lógica de negocios en objetos Java normales en lugar de usar Entity Beans. Nos preguntamos por qué las personas estaban tan en contra del uso de objetos regulares en sus sistemas y concluimos que era porque los objetos simples carecían de un nombre elegante. Así que les dimos uno, y se puso muy de moda.

martinfowler.com: POJO

En cuanto a su otra pregunta:

¿Hay algo inherentemente malo en tener los métodos de agregar y quitar?

No me gusta Asaberlo directamente B. Pero eso es una cosa DIP , no una cosa POJO .

naranja confitada
fuente
Tenía la dependencia directa de, Bpor simplicidad, idealmente ambos implementarían interfaces. Pero Aaún tiene una lista de IInterfaceB. ¿Hay algún problema con el AddChildmétodo si los elementos secundarios se acoplan libremente mediante referencias de interfaz?
Jesse
66
Puedo hacer muchas cosas tontas por simplicidad. Lo que no me gusta es que A sepa de B. A no usa B, por lo que no es necesario definir una interfaz propia de A para hablar con B. Por lo que puedo decir, A es una colección. Entonces, A debería tratar con B a través de un <T> para que no tenga que saber nada al respecto.
candied_orange
2
También he visto "PODO" para "simple objeto de datos antiguo" para evitar cualquier tipo de especificador de lenguaje en el acrónimo. PODO suena un poco tonto (para mí, suena como un epíteto que escucharías en Tatooine), más que POJO o POCO, supongo, pero significativamente menos tonto que POO.
KRyan
2
Me pregunto qué tan bien hubiera sido la presentación de Fowler si los hubiera llamado POO.
Oliver
3

Con Agregar y quitar, está implementando Collection<T>características. Pregúntese por qué está utilizando en IEnumerable<T>lugar de List<T>o alguna otra clase mutable? Aparentemente no es porque su colección sea de solo lectura.

La única razón por la que puedo pensar es que desea controlar qué métodos de acceso desea publicar. En ese caso, sería mejor crear su propia clase de colección, encapsular una lista, implementar sus métodos de selección Agregar y Eliminar e implementar IEnumerable<T>. Luego use eso en lugar de IEnumerable<T>para el tipo de colección de sus hijos.

Pero me parece List<ClassB>que probablemente solo te sirva bien.

Martin Maat
fuente
0

¿Qué AddChildagrega y RemoveChildquita de? Si es de la base de datos (o del almacén de persistencia de cualquier tipo), tienes un registro activo. No siempre es necesariamente algo malo, pero definitivamente te acerca a tener que preocuparte por los marcos, las convenciones, las dependencias, etc., como menciona @CandiedOrange.

Al mismo tiempo, ¿cuál sería el punto de evitar una dependencia de ClassA a ClassB (o al menos InterfaceB) si todos están en la misma aplicación? En el dominio del mundo real que modela su aplicación, las cosas dependen unas de otras. Objetos del mundo real lo tienen colecciones de otros objetos que "pertenecen" a ellos. Es completamente apropiado representar esas relaciones en su código.

La única razón por la que se vuelve incluso un poco complicado es porque parece que tiene la necesidad de administrar exactamente cómo un ClassB se asocia y se disocia de ClassA. Entonces tienes un pequeño comportamiento para implementar. Puede implementarlo dentro de la clase (que es totalmente "legal"; consulte /programming//a/725365/44586 ), o puede tener algún tipo de clase separada que contenga ese comportamiento. Haga lo que tenga más sentido para sus circunstancias individuales.

En cualquier caso, POJO / POCO es realmente solo POO como debe ser, sin adornos y sin gravámenes. Siga los principios de OOP y estará a salvo.

John M. Gant
fuente
Realmente AddChild solo está buscando duplicación y nulo, y tampoco lo permite. RemoveChild está ahí porque para evitar que se agreguen puertas traseras, la colección se expone como un IEnumerable. Sin embargo, solo realizaría la eliminación estándar de la colección.
Jesse
1
Gracias por la explicación. Sí, eso suena exactamente como el tipo de comportamiento que debería estar en un POCO, y definitivamente mejor que simplemente exponer su IEnumerable subyacente para que las personas que llaman modifiquen o reemplacen a voluntad.
John M Gant
Creo que Active Record es solo un mal patrón.
Casey
1
@Casey, no tendrás ninguna discusión de mi parte sobre eso. Pero tampoco discutiría si alguien quisiera usarlo. El punto principal era que si Jesse tenía la intención de usar un patrón como Active Record que integrara la persistencia con la definición del modelo, tendría todos los problemas destacados de CandiedOrange y realmente no calificaría como POCO, por lo que vale. Pero eso no es lo que está haciendo de todos modos.
John M Gant