Estoy tratando de adherirme al Principio de Responsabilidad Única (SRP) tanto como sea posible y me acostumbré a un cierto patrón (para el SRP en los métodos) confiando en gran medida en los delegados. Me gustaría saber si este enfoque es sólido o si hay problemas graves con él.
Por ejemplo, para verificar la entrada a un constructor, podría presentar el siguiente método (la Stream
entrada es aleatoria, podría ser cualquier cosa)
private void CheckInput(Stream stream)
{
if(stream == null)
{
throw new ArgumentNullException();
}
if(!stream.CanWrite)
{
throw new ArgumentException();
}
}
Este método (posiblemente) hace más de una cosa.
- Comprueba las entradas
- Lanzar diferentes excepciones
Para cumplir con el SRP, por lo tanto, cambié la lógica a
private void CheckInput(Stream stream,
params (Predicate<Stream> predicate, Action action)[] inputCheckers)
{
foreach(var inputChecker in inputCheckers)
{
if(inputChecker.predicate(stream))
{
inputChecker.action();
}
}
}
Lo que supuestamente solo hace una cosa (¿lo hace?): Verifique la entrada. Para la comprobación real de las entradas y el lanzamiento de las excepciones, he introducido métodos como
bool StreamIsNull(Stream s)
{
return s == null;
}
bool StreamIsReadonly(Stream s)
{
return !s.CanWrite;
}
void Throw<TException>() where TException : Exception, new()
{
throw new TException();
}
y puede llamar CheckInput
como
CheckInput(stream,
(this.StreamIsNull, this.Throw<ArgumentNullException>),
(this.StreamIsReadonly, this.Throw<ArgumentException>))
¿Es esto mejor que la primera opción o introduzco una complejidad innecesaria? ¿Hay alguna manera de que aún pueda mejorar este patrón, si es viable?
CheckInput
todavía está haciendo varias cosas: está iterando sobre una matriz y llamando a una función de predicado y llamando a una función de acción. ¿No es eso una violación del SRP?