2009-10-20 14 views
20

¿Qué enfoques toman las personas (si corresponde) en la gestión de explosión de guard clause en sus clases? Por ejemplo:Refactoring Guard Clauses

public void SomeMethod<T>(string var1, IEnumerable<T> items, int count) 
{ 
    if (string.IsNullOrEmpty(var1)) 
    { 
     throw new ArgumentNullException("var1"); 
    } 

    if (items == null) 
    { 
     throw new ArgumentNullException("items"); 
    } 

    if (count < 1) 
    { 
     throw new ArgumentOutOfRangeException("count"); 
    } 

    ... etc .... 
} 

En el proyecto que estoy trabajando actualmente hay muchas clases que tienen un conjunto similar de cláusulas de guardia en los métodos públicos.

Conozco los contratos de código de .NET 4.0, pero esta no es una opción para nuestro equipo en este momento.

Respuesta

39

una gran cantidad de proyectos que he visto usar una clase estática Guard.

public static class Guard { 
    public static void ArgumentIsNotNull(object value, string argument) { 
     if (value == null) 
      throw new ArgumentNullException(argument); 
    } 
} 

Se hace el código mucho más limpio, en mi opinión.

Guard.ArgumentIsNotNull(arg1, "arg1"); 
+1

Estaba publicando lo mismo. El único problema es que coloca este método en la parte superior del seguimiento de pila frente al método de origen en la parte superior, aunque no es tan grande. Este patrón obviamente se podría usar para diferentes tipos para verificar un rango de valores, etc ... –

+0

Sí, ese es el único problema que he tenido con él.Aunque es bastante fácil encontrar el método de llamada original. –

+1

Esto es esencialmente lo mismo que las clases que imitan los contratos de código. –

5

Si no desea seguir el camino de Code Contracts, una forma de simplificarlo es eliminar los apoyos:

public void SomeMethod<T>(string var1, IEnumerable<T> items, int count) 
{ 
    if (string.IsNullOrEmpty(var1)) 
     throw new ArgumentNullException("var1"); 

    if (items == null) 
     throw new ArgumentNullException("items"); 

    if (count < 1) 
     throw new ArgumentOutOfRangeException("count"); 

    ... etc .... 
} 

Aparte de eso, hay algunas maneras que usted puede simular Code Contracts , si su objeción es que .Net 4.0 no es hora de máxima audiencia aún:

http://geekswithblogs.net/Podwysocki/archive/2008/01/22/118770.aspx

+0

¡Por el amor de Dios, no hagas esto! Si las declaraciones sin llaves son una excelente manera de causar problemas en el futuro. – EricRRichards

+1

@EricRRichards: * [encogimiento de hombros] * Francamente, si los programadores no pueden mantener su código correcto sin llaves (especialmente un código nada especial como este), probablemente deberían volver a la escuela. –

3

Un enfoque para reducir (no eliminar completamente) Número de cláusulas de guardia es comprender la causa de su existencia. Muy a menudo, resulta que protegemos contra valores que son válidos para el tipo de argumento, pero no son válidos para el método que los acepta. En otras palabras, el método se define en un subconjunto del dominio definido por el tipo de argumento.

La solución a esta categoría de casos es intentar definir un subtipo (por ejemplo, una interfaz más restrictiva) y aceptar ese tipo como el argumento. Puede encontrar un ejemplo ilustrativo en este artículo: Why do We Need Guard Clauses?

Por supuesto, esta técnica no se aplica a todos los casos. Todos los tipos de referencia permiten al menos referencias nulas. En consecuencia, la mayoría de nuestros métodos se definirán en una parte del dominio, que a su vez requiere una cláusula de guardia contra nulo.

Pero, en el lado positivo, esta técnica ayuda a aumentar la conciencia de los métodos que reciben argumentos que son más generales de lo deseado. Fontanería de ese agujero ayuda a mejorar el diseño en general.