Pregunta

¿Qué pasos y medidas puedo tomar para prevenir hendiduras profundas en mi código?

¿Fue útil?

Solución

hendidura profunda es general no es un problema si cada función / método en su programa hace una y sólo una cosa. En ocasiones, podría que sea necesario condicionales nido unos niveles de profundidad, pero honestamente puedo decir que sólo he escrito código profundas aberturas un puñado de veces en más de 12 años de codificación.

Otros consejos

Lo mejor que puede hacer es extracto de métodos:

int Step1(int state)
{
    if (state == 100)
    {
        return Step2(state);
    }
    else
    {
        return Step3(state);
    }
}

int Step2(int state)
{
    if (state != 100)
    {
        throw new InvalidStateException(2, state);
    }

    // ....
}

Tal vez usted podría considerar cláusulas de guardia ?

en lugar de

public void DoSomething(int value){
    if (someCondition){
           if(someOtherCondition){
                if(yetAnotherCondition){
                       //Finally execute some code
                }
           }
    }
} 

Do

public void DoSomething(int value){
    if(!(someCondition && someOtherCondition && yetAnotherCondition)){
        return;
        //Maybe throw exception if all preconditions must be true
    }
    //All preconditions are safe execute code
}

Si alguna vez tienes la oportunidad me gustaría que recomiendo leer el código completo de Steve McConnell. Él tiene un montón de buenos consejos sobre estos temas.

http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/ dp / 0735619670 / ref = pd_sim_b_6

Para más información sobre "cláusulas de guardia" ver: https: // sourcemaking .com / refactorización / replace-anidado-condicional-con-guardia-cláusulas

Invertir sus ifs.

En lugar de:

if (foo != null)
{
    something;
    something;
    if (x)
    {        
       something;
    }
    something;
}
else
{
    boohoo;
}

Me gustaría escribir:

if (foo == null)
{
    boohoo;
    return;
}
something;
something;
if (x)
{        
   something;
}
something;

Lo mismo se aplica a los bloques if-else. Si else es más corto / menos anidada, a continuación, revertirlas.

Comprobar los valores de los parámetros en un solo lugar

Comprobar todos los parámetros para los valores ilegales en cuanto introduce su método, a continuación, proceder a sabiendas de que estás a salvo. Se convierte en un código más legible, pero también le ahorra apilando bloques condicionales más adelante y la difusión de estos controles en todo el subprograma.

Por lo general, he visto que el código profundas aberturas suele código problemático. Si se enfrentan a este problema, a continuación, dar un paso atrás y evaluar si su función es hacer demasiadas cosas.

Al mismo tiempo, para responder a su pregunta, si hay una necesidad de una hendidura que en el fondo, sugeriría que usted permite que sea allí. Por la sencilla razón de que en dicho código, la sangría le ayudará, ya que probablemente será un largo trozo de código es.

Salto de componentes (especialmente repetidas unos) hacia fuera en funciones separadas (esto es más fácil si sus Apoya lengua cierres) anidado o reemplazar una serie de bucles anidados con una recursividad.

Además, guión dos espacios en lugar de cuatro.

No veo hendiduras profundas como un problema categórica a ser eliminado (ni veo refactorización como la verdadera respuesta para todo).

Por lo general en lugar de ifs anidados, me gusta escribir los enunciados lógicos:

if (foo && bar && baz) 

en lugar de

if foo 
 if bar
   if baz

Yo no lo creía yo, pero de acuerdo con el Código Completa este es un lugar apropiado para su uso break (si su equipo está a bordo). Me imagino que esto es más aceptable con los programadores de C ++, sin embargo, cuando se utiliza en break declaraciones switch lo que es con los programadores de Delphi, donde break sólo se utiliza cuando no se siente como escribir un bucle while.

La sangría es realmente una lucha a pensar, en efecto. Lo que he aprendido a hacer es dividir el método en pedazos en primer lugar, a continuación, utilizar un truco raro para saltar cada siguientes piezas si una pieza no. He aquí un ejemplo:

En lugar de:

 {if (networkCardIsOn() == true)
     {if (PingToServer() == true)
        {if (AccesLogin(login,pass) == true)
             {if (nextCondition == true)
                ...
         }
     }
 }

Actualmente escribo:

 {vbContinue = true;

 if (vbContinue) {
       vbContinue = networkCardIsOn();
       if (vbContinue == false) {
             code to Handle This Error();
       } 
 }

 if (vbContinue) {
       vbContinue = PingToServer();
       if (vbContinue == false) {
             code to HandleThisError2();
       } 
 }

 if (vbContinue) {
       vbContinue = AccesLogin(login,pass);
      if (vbContinue == false) {
             HandleThisErrorToo();
       } 
 }
 ...

Esto tiene parecer extraño para mí en un principio, pero desde que uso esto, el costo de mantenimiento se ha dividido por la mitad, y mi cerebro es más fresco al final del día.

De hecho, la ganancia introducida por esta "técnica" es que la complejidad del código está muy dividida porque el código es menos denso.

Mientras lee el código, usted no tiene que recordar nada acerca de las últimas condiciones:. Si su son en ese punto X en el código, los pasos anteriores se pasan y han tenido éxito

Otra ganancia es que "ruta de escape y la condición" de todos aquellos anidada "if-else" se simplifica.

Licenciado bajo: CC-BY-SA con atribución
scroll top