2010-03-16 19 views
5

Me gustaría saber su opinión sobre qué tan lejos llegar con los colorantes sin efectos secundarios.Enfoque para los emisores libres de efectos secundarios

Consideremos el siguiente ejemplo:

Activity activity; 
activity.Start = "2010-01-01"; 
activity.Duration = "10 days"; // sets Finish property to "2010-01-10" 

nota que los valores de fecha y duración se muestran sólo a título indicativo.

Así, utilizando setter para cualquiera de las propiedades Start, Finish y Duration por consiguiente va a cambiar otras propiedades y por lo tanto no puede considerarse lateral libre efecto. Lo mismo se aplica a las instancias de la clase Rectangle, donde setter para X está cambiando los valores de Top y Bottom y así sucesivamente.

La pregunta es dónde se trazaría una línea entre el uso de setters, que tienen efectos secundarios de valores cambiantes de propiedades lógicamente relacionadas, y el uso de métodos, que de todos modos no podrían ser mucho más descriptivos. Por ejemplo, definir un método llamado SetDurationTo(Duration duration) tampoco refleja que se modifique el Inicio o el Final.

Respuesta

8

Creo que está malinterpretando el término "efecto secundario" tal como se aplica al diseño del programa. Establecer una propiedad es un efecto secundario, no importa cuánto o qué tan poco estado interno cambie, siempre y cuando cambie algún tipo de estado. Un "colocador libre de efectos secundarios" no sería muy útil.

Los efectos secundarios son algo que desea evitar en la propiedad getters. Leer el valor de una propiedad es algo que la persona que llama no espera cambiar ningún estado (es decir, causa efectos secundarios), por lo que si lo hace, generalmente es incorrecto o al menos cuestionable (hay excepciones, como la carga diferida). Pero getters y setters son simplemente envoltorios de métodos de todos modos. La propiedad Duration, en lo que respecta al CLR, es solo azúcar sintáctico para un método set_Duration.

Esto es exactamente para lo que están destinadas las abstracciones, como las clases, proporcionando operaciones de grano grueso manteniendo un estado interno uniforme. Si deliberadamente intentas evitar tener múltiples efectos secundarios en una sola asignación de propiedad, tus clases terminarán siendo poco más que simples contenedores de datos.

Respondiendo la pregunta directamente: ¿Dónde dibujo la línea? En ninguna parte, siempre que el método/propiedad realmente haga lo que su nombre implica. Si la configuración del Duration también cambió el ActivityName, podría ser un problema. Si cambia la propiedad Finish, eso debería ser obvio; es debería ser imposible cambiar el Duration y tener el Start y el Finish permanecen iguales. La premisa básica de OOP es que los objetos son lo suficientemente inteligentes como para administrar estas operaciones por sí mismos.

Si esto te molesta a nivel conceptual, entonces no tienes propiedades de mutadores en absoluto: utiliza una estructura de datos inmutables con propiedades de solo lectura donde todos los argumentos necesarios se proporcionan en el constructor. Luego tiene dos sobrecargas, una que toma un Start/Duration y otra que toma un Start/Finish. O haga que solo una de las propiedades tenga capacidad de escritura, digamos Finish para mantenerla consistente con Start, y luego haga Duration de solo lectura. Use la combinación adecuada de propiedades mutables e inmutables para asegurarse de que solo haya una forma de cambiar un determinado estado.

De lo contrario, no se preocupe tanto por esto. Las propiedades (y los métodos) no deberían tener o no documentados efectos secundarios no documentados, pero esa es la única guía que usaría.

+0

Gracias, esto es lo que estaba buscando y nunca se me ocurrió el "efecto secundario" "setter libre" en realidad no es posible ya que cambiará el estado. Y como usted señaló, el CLR se traducirá al método de todos modos. – Martin

+0

Sí, el efecto secundario de un colocador es establecer * la variable miembro a la que se refiere *.Pero un efecto secundario adicional es modificar * otras * variables miembro. –

+0

Estaba pensando en lo mismo e incluso diría que la configuración de la variable miembro no es un efecto secundario, sino el efecto deseado del colocador. El cambio de otras variables miembro es un efecto secundario. – Martin

0

Siempre he trabajado con la regla general de no permitir public setters en propiedades que no tienen efectos secundarios, ya que las personas que llaman de sus organismos públicos no pueden estar seguros de lo que podría pasar, pero por supuesto, las personas que modifican el el montaje en sí debería tener una muy buena idea, ya que pueden ver el código.

Por supuesto, siempre hay momentos en los que tiene que romper la regla por el bien de la legibilidad, para hacer que su modelo de objeto sea lógico, o simplemente para que las cosas funcionen correctamente. Como dijiste, realmente es una cuestión de preferencia en general.

1

Personalmente, creo que tiene sentido tener un efecto secundario para mantener un estado constante. Como dijiste, tiene sentido cambiar los valores lógicamente relacionados. En cierto sentido, se espera el efecto secundario. Pero lo importante es aclarar ese punto. Es decir, debería ser evidente que la tarea que está realizando el método tiene algún tipo de efecto secundario. Entonces, en lugar de SetDurationTo, puede llamar a su función ChangeDurationTo, lo que implica que algo más está sucediendo. También podría hacer esto de otra manera al tener una función/método que ajuste la duración AdjustDurationTo y pase en un valor de delta. Sería útil documentar la función como un efecto secundario.

Creo que otra forma de verlo es ver si se espera un efecto secundario. En su ejemplo de un rectángulo, esperaría que cambie los valores de top o bottom para mantener un estado interno consistente. No sé si esto es subjetivo; parece que tiene sentido para mí. Como siempre, creo que la documentación gana. Si hay un efecto secundario, documente bien. Preferiblemente por el nombre del método y a través de la documentación de respaldo.

-2

Creo que es principalmente una cuestión de sentido común.

En este ejemplo en particular, mi problema no es tanto que tenga propiedades que ajusten las propiedades "relacionadas", sino que tiene propiedades que toman valores de cadena que luego está internamente analizando en DateTime (o lo que sea)) valores.

Me gustaría mucho ver algo como esto:

Activity activity; 
activity.Start = DateTime.Parse("2010-01-01"); 
activity.Duration = Duration.Parse("10 days"); 

Es decir, que de forma explícita en cuenta que está haciendo el análisis de cadenas.Permita que el programador especifique objetos de tipo fuerte cuando sea apropiado también.

+0

Como he mencionado "Tenga en cuenta que los valores de fecha y duración se muestran solo con fines indicativos". Entonces tu comentario realmente no aborda la pregunta, pero gracias de todos modos ... sabía que alguien apuntaría a esto ;-) – Martin

1

Una opción es hacer que su clase sea inmutable y tener métodos para crear y devolver nuevas instancias de la clase que tengan todos los valores apropiados modificados. Entonces no hay efectos secundarios o setters. Piense en algo como DateTime donde puede llamar a cosas como AddDays y AddHours que devolverá una nueva instancia de DateTime con el cambio aplicado.

Cuestiones relacionadas