2010-12-03 18 views
7

Tengo tres métodos de C# que casi funcionan de forma idéntica. Más específicamente, hay una gran cantidad de repetición de código, pero al final, realizan diferentes funciones.Cómo evitar la duplicación de código

Esto es obviamente muy ineficiente, entonces, ¿cuál es la mejor manera de reducir la duplicación de código? ¿Debo colocarlo todo en un método y usar un conmutador & enum para las diferentes funcionalidades al final? Alternativamente, ¿hay algún tipo de forma en que pueda tener 3 clases separadas y heredar el bit compartido de otro? He leído bastante sobre esto y, por lo que sé, esto solo se usa para obtener propiedades de una clase completamente diferente.

+1

(I sustituido "reutilización" => "duplicación", ya que parecía adaptarse a su significado más claramente) –

+0

"¿Debo colocarlo todo en un método y usar un interruptor y una enumeración para las diferentes funciones al final?" Por favor no hagas esto! – SingleNegationElimination

+0

No obtendrá una respuesta útil a esta pregunta, intente publicar una consulta que contenga el código de los 3 métodos, y es posible que las personas puedan ayudarlo. No hay una solución para el código de refactorización. –

Respuesta

5

Sin ver el código es difícil dar un ejemplo concreto, pero parece que quiere pasar una instancia de delegado en el método.

+0

mis pensamientos exactamente –

+0

Gracias Steven, resulta que eso es exactamente lo que estaba buscando. Disculpas por no haber proporcionado un ejemplo de código, me aseguraré de que la próxima vez. – Jonathan

4

Desde mi punto de vista, debe sentarse con un papel y un bolígrafo. Dibuje cada pieza de funcionalidad que realizan sus métodos. Recuerde que una función/método debe hacer una y solo una cosa.

Después de que haya desactivado todas las funciones, comenzará a ver cosas que se repiten, estas deben agruparse juntas en una función.

+1

+1 por mencionar el principio de responsabilidad única: las clases y las funciones deberían hacer pocas cosas, pero hágales bien. http://en.wikipedia.org/wiki/Single_responsibility_principle –

2

Puede usted hacer algo como lo siguiente:

public void MethodBase() 
    { 
     Console.WriteLine("1"); 
     Console.WriteLine("2"); 
     Console.WriteLine("3"); 
     Console.WriteLine("4"); 
     Console.WriteLine("5"); 
    } 

    public void Method1() 
    { 
     MethodBase(); 
     Console.WriteLine("Method 1"); 
    } 

    public void Method2() 
    { 
     MethodBase(); 
     Console.WriteLine("Method 2"); 
    } 

    public void Method3() 
    { 
     MethodBase(); 
     Console.WriteLine("Method 3"); 
    } 
+0

Gracias decyclone. Olvidé mencionar que MethodBase() está estableciendo una serie de variables, a todas las cuales se debe acceder desde Method1, Method2 y Method3. ¿Esto significa que necesito usar una instancia de delegado como Steven me ha aconsejado? – Jonathan

+0

Creo que sí, deberías. – decyclone

4

que tengo tres métodos en C# que en gran medida hacer cosas idénticas. Hay mucha repetición de código pero al final, ellos ambos realizan diferentes funciones.

Al leer esta línea, creo que sus tres métodos tienen una implementación diferente basada en algunos escenarios diferentes.

por lo que sugeriría ver el Patrón de Stratgey una vez que puede ser útil. See here

2

No hay ninguna solución que funcione en todos los casos, muéstrenos el código.

El problema es que cuando pones el código en una función y cambias una pequeña parte del comportamiento en algún lugar dentro, aumentas la complejidad del código, y a veces es mejor mantener un código duplicado que eso.

Casi el mismo argumento funciona para la herencia. Puede rellenar fácilmente el código común en una clase ancestral común, pero si comienza a utilizar de forma rutinaria la herencia como una herramienta de reutilización de código, su diseño puede caer en un mundo de dolor. La herencia significa que el código en una pieza de código puede afectar el comportamiento en otras partes del código y, antes de que te des cuenta, tendrás una bola de código entrelazada que es casi imposible de cambiar sin romper.

Por lo general, es mejor cuando puede extraer o abstraer un significativo parte común del código de esas tres funciones. Algo que tiene sentido, como un patrón de alto nivel, en lugar de solo unas pocas líneas comunes que no hacen un trabajo coherente. Una regla simple que puede ayudarlo es nombrar el código extraído: ¿existe una forma natural y obvia de nombrar el fragmento? ¿Obviamente encaja en una de tus clases? Si lo hace, podría ser una buena solución. Si tiene dificultades para nombrarlo y podría ir a cualquier lugar, es posible que desee pensar un poco más.

2

Puede intentar generalizar el método convirtiéndolo en una función de orden superior o genérica. Otros enfoques que vienen a la mente son los patrones de diseño como el método de plantilla, que le permite definir el esqueleto del algoritmo y dejar que las subclases redefinan ciertos pasos.

3

Es una buena señal de que te molesta.

Esto es obviamente muy ineficiente

La ineficiencia (un poco de uso de memoria adicional) es la parte menos importante en estos días. Lo que es cruciforme es que es una pesadilla de mantenimiento. Por ejemplo, si encuentra un error en la rutina y la soluciona, también debe recordar corregir el código duplicado. Definitivamente desea factorizar el código duplicado cuando pueda.

Alternativamente, ¿hay algún tipo de forma puede tener 3 clases separadas y heredar el bit compartido de otro? He leído bastante sobre esto y, por lo que sé, esto solo se usa para obtener propiedades de una clase completamente diferente.

Una subclase puede acceder directamente a todos los miembros públicos y protegidos de su superclase. Por ejemplo, si tenía una clase Animal con un método Poop(), las subclases Perro y Gato podrían compartir ese código de caca.

Pero hay mucho maneras de desollar a este gato. Es difícil decir lo mejor sin más detalles.

1
public MyCustomObject MethodBase(MyCustomObject myObj) 
{ 
    myObj.Name="FixedName"; 
    myObj.Surname="FixedSurname"; 
    myObj.Type = Types.Human; 
    return myObj; 
} 


public MyCustomObject SetOld(MyCustomObject myObj) 
{ 
    MethodBase(); 
    myObj.IsOld = True; 
    return myObj; 
} 

public MyCustomObject SetYoung(MyCustomObject myObj) 
{ 
    MethodBase(); 
    myObj.IsOld = False; 
    return myObj; 
} 

public MyCustomObject SetIsDead(MyCustomObject myObj) 
{ 
    MethodBase(); 
    myObj.IsDead = True; 
    return myObj; 
} 
public void MainMethod(enum OperationType) 
{ 
    MyCustomObject myObj = new MyCustomObject(); 
    switch(OperationType) 
    { 
     case OperationTypes.Old: 
      myObj = SetOld(myObj); 
      break; 
     case OperationTypes.Young: 
      myObj = SetYoung(myObj); 
      break; 
     case OperationTypes.Dead: 
      myObj = SetDead(myObj); 
      break; 
    } 
} 
0

Nadie mencionó lambda-funciones, que son debe saber para desarrolladores .NET 3.5:

public MyCustomObject SetYoung(MyCustomObject myObj) 
{ 
    GeneralMethod(myObj => myObj.IsOld = False); 
    return myObj; 
} 

public void GeneralMethod(Func<TSourceObjectType,TResultObjectType> func) 
{ 
    MyCustomObject myObj = new MyCustomObject(); // MyCustomObject implements 'TSourceObjectType' 
    TResultObjectType res = func(myObj); 
} 
Cuestiones relacionadas