Dilema
He estado leyendo muchos libros de mejores prácticas sobre prácticas orientadas a objetos, y casi todos los libros que he leído tienen una parte donde dicen que las enumeraciones son un olor a código. Creo que se han perdido la parte en la que explican cuándo las enumeraciones son válidas.
Como tal, estoy buscando pautas y / o casos de uso donde las enumeraciones NO son un olor a código y, de hecho, una construcción válida.
Fuentes:
"ADVERTENCIA Como regla general, las enumeraciones son olores de código y deben refactorizarse a clases polimórficas. [8]" Seemann, Mark, Dependency Injection en .Net, 2011, p. 342
[8] Martin Fowler et al., Refactoring: Improving the Design of Existing Code (Nueva York: Addison-Wesley, 1999), 82.
Contexto
La causa de mi dilema es una API comercial. Me dan una secuencia de datos de Tick enviándome a través de este método:
void TickPrice(TickType tickType, double value)
dónde enum TickType { BuyPrice, BuyQuantity, LastPrice, LastQuantity, ... }
Intenté hacer un envoltorio alrededor de esta API porque romper los cambios es la forma de vida de esta API. Quería hacer un seguimiento del valor de cada último tipo de tick recibido en mi contenedor y lo hice usando un Diccionario de tipos de tick:
Dictionary<TickType,double> LastValues
Para mí, esto parecía un uso adecuado de una enumeración si se usan como claves. Pero estoy teniendo dudas porque tengo un lugar donde tomo una decisión basada en esta colección y no puedo pensar en cómo podría eliminar la declaración de cambio, podría usar una fábrica, pero esa fábrica aún tendrá un cambiar la declaración en alguna parte. Me pareció que solo estaba moviendo cosas, pero todavía huele.
Es fácil encontrar los DON'T de las enumeraciones, pero los DO no son tan fáciles, y agradecería que las personas puedan compartir su experiencia, los pros y los contras.
Segundos pensamientos
Algunas decisiones y acciones se basan en estos TickType
y parece que no puedo pensar en una forma de eliminar las declaraciones enum / switch. La solución más limpia que se me ocurre es usar una fábrica y devolver una implementación basada en TickType
. Aún así, tendré una declaración de cambio que devuelve una implementación de una interfaz.
A continuación se enumera una de las clases de muestra donde tengo dudas de que podría estar usando una enumeración incorrecta:
public class ExecutionSimulator
{
Dictionary<TickType, double> LastReceived;
void ProcessTick(TickType tickType, double value)
{
//Store Last Received TickType value
LastReceived[tickType] = value;
//Perform Order matching only on specific TickTypes
switch(tickType)
{
case BidPrice:
case BidSize:
MatchSellOrders();
break;
case AskPrice:
case AskSize:
MatchBuyOrders();
break;
}
}
}
enums as switch statements might be a code smell ...