¿Se produce una excepción desde una forma incorrecta de propiedad?

13

Siempre he tenido la mentalidad de que las propiedades (es decir, sus operaciones de configuración / obtención) deberían ser rápidas / inmediatas y sin fallas. Nunca debe tener que intentar / captar para obtener o establecer una propiedad.

Pero estoy buscando algunas formas de aplicar la seguridad basada en roles en las propiedades de algunos objetos. Por ejemplo, una propiedad Employee.Salary. Algunas de las soluciones que he encontrado que otras han probado (una en particular es el ejemplo de AOP aquí ) implica lanzar una excepción si el usuario no tiene los permisos adecuados, pero esto va en contra de una regla personal que tengo desde hace mucho tiempo.

Entonces pregunto: ¿estoy equivocado? ¿Han cambiado las cosas? ¿Se ha aceptado que las propiedades deberían poder lanzar excepciones?

    
pregunta Steven Evers 04.11.2010 - 00:52

7 respuestas

14

cuando configura el valor de una propiedad, lanzar una excepción a un valor no válido está bien

obtener el valor de una propiedad debería (casi) nunca lanzar una excepción

para el acceso basado en roles, use interfaces / fachadas diferentes / más complejas; ¡No dejes que la gente vea cosas que no pueden tener!

    
respondido por el Steven A. Lowe 04.11.2010 - 01:52
5

Considero que en su mayor parte es una mala forma, pero incluso Microsoft recomienda usar excepciones a veces. Un buen ejemplo es la propiedad abstracta Stream.Length . Según las pautas, me preocuparía más evitar los efectos secundarios en los captadores y limitar los efectos secundarios en los establecedores.

    
respondido por el ChaosPandion 04.11.2010 - 01:24
3

Definitivamente argumentaría que hay una falla en el diseño si sientes la necesidad de lanzar excepciones desde un establecedor de propiedades o un captador.

Una propiedad es una abstracción que representa algo que es solo un valor . Y debería poder establecer un valor sin temer que hacerlo podría generar una excepción. *

Si establecer los resultados de la propiedad en un efecto secundario, eso debería implementarse como un método. Y si no produce ningún efecto secundario, no se debe lanzar ninguna excepción.

Un ejemplo ya mencionado en una respuesta diferente es Stream.Position propiedad. Esto produce efectos secundarios, y puede lanzar excepciones. Pero este establecedor de propiedades es básicamente un envoltorio alrededor de Stream.Seek a los que podrías llamar en su lugar.

Personalmente, creo que la posición no debería haber sido una propiedad de escritura.

Otro ejemplo en el que podría verse tentado a lanzar una excepción desde un establecedor de propiedades es la validación de datos:

public class User {
    public string Email {
        get { return _email; }
        set { 
            if (!IsValidEmail(value)) throw InvalidEmailException(value);
            _email = value;
        }
    }

Pero hay una mejor solución a este problema. Introduzca un tipo que represente una dirección de correo electrónico válida:

public class Email {
    public Email(string value) {
        if (!IsValidEmail(value)) throw new InvalidEmailException(value);
        ...
    }
    ...
}

public class User {
    public Email Email { get; set; }
}

La clase Email garantiza que no puede contener un valor que no sea una dirección de correo electrónico válida, y las clases que necesitan almacenar correos electrónicos no tienen la obligación de validarlos.

Esto también conduce a una mayor cohesión (un indicador del buen diseño del software): el conocimiento sobre qué es una dirección de correo electrónico y cómo se valida, solo existe en la clase Email , que tiene solo esa preocupación.

* ObjectDisposedException es la única excepción válida (no se pretende hacer un juego de palabras) que se pueda imaginar en este momento.

    
respondido por el Pete 07.01.2015 - 15:50
2

Sé que tu pregunta es específica de .NET , pero como C # comparte algo de historia con Java, pensé que podrías estar interesado. No estoy de ninguna manera implicando que porque algo se hace en Java, debe hacerse en C #. Sé que los dos son muy diferentes, especialmente en la forma en que C # tiene un mejor nivel de soporte de idioma para las propiedades. Solo estoy dando un poco de contexto y perspectiva.

De la especificación de JavaBeans :

  

Propiedades restringidas A veces, cuando se produce un cambio de propiedad, algunos   otro frijol puede desear validar el   cambiarlo y rechazarlo si es   inapropiado. Nos referimos a las propiedades.   que se someten a este tipo de comprobación como   propiedades restringidas. En Java Beans,   métodos de establecimiento de propiedades restringidas   son necesarios para apoyar el   PropertyVetoException. Estos documentos   a los usuarios de lo restringido   propiedad que intentó actualizaciones puede ser   vetado Así que un simple constreñido   propiedad podría verse como:

PropertyType getFoo();
void setFoo(PropertyType value) throws PropertyVetoException;

Toma todo esto con un grano de sal, por favor. La especificación de JavaBeans es antigua, y las propiedades de C # son (IMO) una gran mejora con respecto a las propiedades basadas en "convenciones de nombres" que tiene Java. Solo estoy tratando de dar un poco de contexto, ¡eso es todo!

    
respondido por el Mike Clark 04.11.2010 - 01:42
2

El punto de una propiedad es el Principio de acceso uniforme , es decir, que un valor debe ser accesible a través de la misma interfaz si Implementado por almacenamiento o computación. Si su propiedad está lanzando una excepción que representa una condición de error más allá del control del programador, del tipo que se supone que debe capturarse y manejarse, está obligando a su cliente a saber que el valor se obtiene a través del cálculo.

Por otra parte, no veo ningún problema con el uso de aserciones o excepciones de tipo aserción que pretenden señalar el uso incorrecto de la API al programador en lugar de ser capturado y manejado. En estos casos, la respuesta correcta desde la perspectiva del usuario de la API no es manejar la excepción (por lo tanto, preocuparse de manera implícita sobre si el valor se obtiene mediante cálculo o almacenamiento). Es para corregir su código para que el objeto no termine en un estado no válido o hacer que usted corrija su código para que la afirmación no se active.

    
respondido por el dsimcha 04.11.2010 - 01:41
1

AFAIK, esta guía proviene principalmente del proceso de pensamiento de que las propiedades pueden terminar usándose en el momento de diseño . (Por ejemplo, la propiedad de texto en un cuadro de texto) Si la propiedad lanza una excepción cuando un diseñador intenta acceder a ella, VS no tendrá un buen día. Obtendrá un montón de errores al intentar usar el diseñador y, para los diseñadores de IU, no se procesarán. También se aplica al tiempo de depuración también, aunque lo que verás en un escenario de excepción es solo "xxx Exception" y no contagiará a VS IIRC.

Para los POCO, realmente no hará ningún daño, pero sigo teniendo miedo de hacerlo yo mismo. Me imagino que la gente querrá acceder a las propiedades con más frecuencia, por lo que normalmente deberían ser de bajo costo. Las propiedades no deben hacer el trabajo de los métodos, solo deben obtener / establecer cierta información y hacerse con ella como una regla general.

    
respondido por el MIA 04.11.2010 - 01:35
0

Aunque mucho dependerá del contexto, en general evitaría poner en las propiedades cualquier tipo de lógica rompible (incluidas las excepciones). Solo como un ejemplo, hay muchas cosas que usted (o alguna biblioteca que está usando) podría hacer, que utilizan la reflexión para iterar sobre las propiedades que resultan en errores que no anticipó en el momento del diseño.

Digo, en general, ya que puede haber ocasiones en las que, absolutamente, definitivamente, quieras bloquear algo sin preocuparte demasiado por las consecuencias. Supongo que la seguridad sería el caso clásico allí.

    
respondido por el FinnNk 04.11.2010 - 14:04

Lea otras preguntas en las etiquetas