Tengo esta función API:
public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d,
string e, string f, out Guid code)
No me gusta Porque el orden de los parámetros se vuelve innecesariamente significativo. Se hace más difícil agregar nuevos campos. Es más difícil ver lo que se pasa. Es más difícil refactorizar el método en partes más pequeñas porque crea otra sobrecarga al pasar todos los parámetros en las subfunciones. El código es más difícil de leer.
Se me ocurrió la idea más obvia: tener un objeto encapsulando los datos y pasarlos en lugar de pasar cada parámetro uno por uno. Esto es lo que se me ocurrió:
public class DoSomeActionParameters
{
public string A;
public string B;
public DateTime C;
public OtherEnum D;
public string E;
public string F;
}
Eso redujo mi declaración de API a:
public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)
Agradable. Parece muy inocente, pero en realidad introdujimos un gran cambio: introdujimos la mutabilidad. Porque lo que habíamos estado haciendo anteriormente era pasar un objeto inmutable anónimo: parámetros de función en la pila. Ahora creamos una nueva clase que es muy mutable. Creamos la capacidad de manipular el estado de la persona que llama . Eso apesta. Ahora quiero que mi objeto sea inmutable, ¿qué hago?
public class DoSomeActionParameters
{
public string A { get; private set; }
public string B { get; private set; }
public DateTime C { get; private set; }
public OtherEnum D { get; private set; }
public string E { get; private set; }
public string F { get; private set; }
public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d,
string e, string f)
{
this.A = a;
this.B = b;
// ... tears erased the text here
}
}
Como puede ver, en realidad volví a crear mi problema original: demasiados parámetros. Es obvio que ese no es el camino a seguir. ¿Que voy a hacer? La última opción para lograr tal inmutabilidad es usar una estructura "de solo lectura" como esta:
public struct DoSomeActionParameters
{
public readonly string A;
public readonly string B;
public readonly DateTime C;
public readonly OtherEnum D;
public readonly string E;
public readonly string F;
}
Eso nos permite evitar constructores con demasiados parámetros y lograr la inmutabilidad. En realidad soluciona todos los problemas (ordenamiento de parámetros, etc.). Todavía:
- Todos (incluidos FXCop y Jon Skeet) están de acuerdo en que exponer los campos públicos es malo .
- Eric Lippert et al dicen que confiar en campos de solo lectura para la inmutabilidad es una mentira .
Fue entonces cuando me confundí y decidí escribir esta pregunta: ¿Cuál es la forma más directa en C # para evitar el problema de "demasiados parámetros" sin introducir mutabilidad? ¿Es posible usar una estructura de solo lectura para ese propósito y, sin embargo, no tener un mal diseño de API?
Aclaraciones
- Suponga que no hay violación del principio de responsabilidad única. En mi caso original, la función simplemente escribe los parámetros dados en un solo registro DB.
- No estoy buscando una solución específica para la función dada. Estoy buscando un enfoque generalizado para tales problemas. Estoy específicamente interesado en resolver el problema de "demasiados parámetros" sin introducir mutabilidad o un diseño terrible.
ACTUALIZAR
Las respuestas proporcionadas aquí tienen diferentes ventajas / desventajas. Por lo tanto, me gustaría convertir esto a una wiki comunitaria. Creo que cada respuesta con código de muestra y Pros / Contras sería una buena guía para problemas similares en el futuro. Ahora estoy tratando de averiguar cómo hacerlo.
DoSomeActionParameters
es un objeto desechable, que se descartará después de la llamada al método.