2009-11-06 12 views
6

Esta pregunta ha estado en mi mente por un tiempo, lo siento si parece subjetiva. Hay algunas desventajas en el uso de bool en propiedades públicas y constructores para objetos de datos. Considere el siguiente código como un ejemplo.Enumeración de dos miembros vs. valor booleano

Usando bool:

public class Room 
{ 
    public string Name { get; set; } 
    public bool Bookable { get; set; } 

    public Room(string name, bool bookable); 
} 

y el uso de esta clase

Room r = new Room ("101", true); 

Este es adecuadamente funcional, no es sin embargo otra manera de ponerla en práctica:

Usando enum :

public enum BookingStatus 
{ 
    Bookable, 
    NotBookable 
} 

public class Room 
{ 
    public string Name { get; set; } 
    public BookingStatus Bookable { get; set; } 

    public Room(string name, BookingStatus bookable); 
} 

y el uso de esta clase

Room r = new Room ("101", BookingStatus.Bookable); 

Para mí los dos aparecen funcionalmente equivalente, hay algunas ventajas y desventajas de cada uno, sin embargo:

  • Al configurar las propiedades del método de enumeración es más verboso (puede inferir el uso de la enumeración solo del código)
  • Las enumeraciones se pueden ampliar para admitir otros estados (particularmente útiles para una API)
  • Las enumeraciones requieren considerablemente más tipeo (aunque lo reduce considerablemente)
  • Las enumeraciones no se pueden usar en condicionales (es decir if (r.bookable)), aunque aprecio que esto es trivial de resolver.

¿Me falta algo, totalmente fuera de lugar? No estoy seguro de por qué esto me molesta tanto, ¡quizás yo también soy TOC por mi propio bien!

+0

Opinión: esto parece que no es el mejor ejemplo - si se trata de una verdadera pregunta de sí/no, luego los booleos son apropiados. Aunque debe nombrar sus propiedades correctamente de acuerdo con la convención (es decir, "IsBookable"): un mejor ejemplo es una pregunta que no es sí o no, como por género o unidades de medida, etc., incluso si solo reconoce dos estados (pulgadas vs cm, o masculino vs. femenino), debe usar una enumeración, porque definitivamente estas no son preguntas de "sí o no" (aunque podría convertirlas en preguntas de sí/no, no, y podrían ser ampliado para admitir más estados). – BrainSlugs83

Respuesta

2

En su libro Refactoring, Martin Fowler explica por qué cree que las enumeraciones son un olor a código, y yo solo puedo estar de acuerdo. En su ejemplo, un mejor enfoque sería hacer un resumen de clase habitación:

public abstract class Room 
{ 
    public string Name { get; set; } 

    public abstract bool Bookable { get; } 
} 

entonces usted puede hacer que las clases derivadas BookableRoom y NonBookableRoom.

public class BookableRoom : Room 
{ 
    public override bool Bookable 
    { 
     get { return true; } 
    } 
} 

public class NonBookableRoom : Room 
{ 
    public override bool Bookable 
    { 
     get { return false; } 
    } 
} 
+0

Punto fuerte, y un método que he usado en otros lugares. Supongo que esto no funcionaría muy bien con algo como Entity Framework. Sin embargo, sin duda se correlacionaría muy bien con algo así como una lista de SharePoint. –

+10

¿Por qué afirmas que este es un mejor enfoque? Para mí, parece aumentar la complejidad. Creo que el principio de KISS es apropiado aquí. – nightcoder

+0

El libro proporciona una descripción completa :) –

5

Ih hay alguna posibilidad de que en el futuro puede haber más de las dos opciones iniciales, la adición de una tercera opción para una enumeración es mucho menos trabajo a continuación, cambiando todo bool a ENUM.

+0

Eso es lo que ya dijo en su respuesta (segundo punto en la lista de viñetas). –

+0

a excepción del aspecto de "plan para el futuro". – fforw

8

Simplemente por la legibilidad y la comprensión del código, buscaré enum en lugar de boolean.

Comparar BookingStatus.Bookable y true, por supuesto, usted entendería más leyendo BookingStatus.Bookable.

También como lo mencionado anteriormente, en caso de que en el futuro necesites agregar más opciones, enum sería más fácil de cambiar.

+0

¿Qué pasa con la seguridad tipo? Una enumeración evitaría que cualquier valor booleano antiguo caiga en un parámetro enum. – weberc2

+1

Esto también es mejor mantener. Los cambios son menores cuando se usa enum si se inventa un nuevo tipo de BookingStatus –

4

Para una propiedad, probablemente estaría de acuerdo. Sin embargo, en 'Código limpio', se indica (correctamente) que bool s ocultar intento cuando se utilizan como parámetros.Por ejemplo, un método de formato podría ser:

public void Format(bool pBold, bool pItalic, bool pUnderline) 
{ ... } 

Cuando llamó a este aspecto:

Format(true, false, true); 

En cambio, sería mucho más fácil de leer como:

public enum BOLD { BOLD, NOT_BOLD } 
public enum ITALIC { ITALIC, NOT_ITALIC } 
public enum UNDERLINE { UNDERLINE, NOT_UNDERLINE } 

public void Format(BOLD pBold, ITALIC pItalic, UNDERLINE pUnderline) 
{ ... } 

Que a su vez hace que el llamar al:

Format(BOLD.BOLD, ITALIC.NOT_ITALIC, UNDERLINE.NOT_UNDERLINE); 

(Recuerde que este es solo un ejemplo de cómo los parámetros de bool ocultan la intención; . Hay probablemente mejores formas de implementar el código anterior)

En su caso particular, notan la diferencia entre los dos constructor llama:

// enum; intent is clear 
Room r = new Room ("101", BookingStatus.Bookable); 

// bool; true what? 
Room r = new Room("101", true); 
+2

Además, no se puede poner una variable que contenga el valor en negrita en el espacio del parámetro 'cursiva' cuando se usan enumeraciones. :) Escriba seguridad. – weberc2

+0

'// cadena; "101" ¿Qué? 'Agregue unas cuantas cuerdas más y se encontrará en la misma posición que con un bool. Entonces, ¿Qué haces? Miras la definición del método. – Stijn

+0

@Stijn de acuerdo. No leer la firma de un método no es una excusa para no entender la firma de un método. – Dan