with smells refactor patterns pattern method guru code c# oop refactoring

c# - patterns - refactoring guru code smells



¿Está bien tener una clase con solo propiedades para refactorizar? (12)

¿Tal vez los parámetros opcionales y nombrados de C # 4.0 sean una buena alternativa a esto?

De todos modos, el método que está describiendo también puede ser útil para resumir el comportamiento de los programas. Por ejemplo, podría tener una función estándar SaveImage(ImageSaveParameters saveParams) en una interfaz donde ImageSaveParameters también es una interfaz y puede tener parámetros adicionales según el formato de la imagen. Por ejemplo, JpegSaveParameters tiene una Quality propiedad, mientras que PngSaveParameters tiene una BitDepth BitDepth -property.

Así es como lo hace el diálogo Guardar guardar en Paint.NET, por lo que es un ejemplo de vida muy real.

Tengo un método que toma 30 parámetros. Tomé los parámetros y los puse en una clase, para poder pasar un parámetro (la clase) al método. ¿Está perfectamente bien en el caso de la refactorización pasar un objeto que encapsula todos los parámetros, incluso si eso es todo lo que contiene?


30 parámetros es un desastre. Creo que es mucho más bonito tener una clase con las propiedades. Incluso podría crear múltiples "clases de parámetros" para grupos de parámetros que encajan en la misma categoría.


Como se dijo antes: es el paso correcto, pero considere lo siguiente:

  • su método puede ser demasiado complejo (debería considerar dividirlo en más métodos, o incluso convertirlo en una clase separada)
  • si crea la clase para los parámetros, immutable
  • Si muchos de los parámetros pueden ser nulos o podrían tener algún valor predeterminado, es posible que desee utilizar el patrón del generador para su clase.

Es un buen comienzo. Pero ahora que tienes esa clase nueva, considera convertir tu código al revés. Mueva el método que toma esa clase como parámetro en su nueva clase (por supuesto, pasando una instancia de la clase original como parámetro). Ahora tiene un gran método, solo en una clase, y será más fácil separarlo en métodos más pequeños, más manejables y comprobables. Algunos de esos métodos podrían regresar a la clase original, pero es probable que una buena parte permanezca en su nueva clase. Se ha movido más allá de Introducir parámetro de objeto en Reemplazar método con Objeto de método .

Tener un método con treinta parámetros es una señal bastante fuerte de que el método es demasiado largo y complicado. Demasiado difícil de depurar, demasiado difícil de probar. Así que deberías hacer algo al respecto, y Presentar Objeto de parámetro es un buen lugar para comenzar.


Esa es una excelente idea y una solución muy común al problema. Los métodos con más de 2 o 3 parámetros se vuelven exponencialmente más difíciles de entender.

Encapsular todo esto en una sola clase hace que el código sea mucho más claro. Como sus propiedades tienen nombres, puede escribir código de auto-documentación como este:

params.height = 42; params.width = 666; obj.doSomething(params);

Naturalmente, cuando tienes muchos parámetros, la alternativa basada en la identificación posicional es simplemente horrible.

Otro beneficio adicional es que puede agregar parámetros adicionales al contrato de interfaz sin forzar cambios en todos los sitios de llamadas. Sin embargo, esto no siempre es tan trivial como parece. Si diferentes sitios de llamadas requieren valores diferentes para el nuevo parámetro, entonces es más difícil cazarlos que con el enfoque basado en parámetros. En el enfoque basado en parámetros, al agregar un nuevo parámetro se fuerza un cambio en cada sitio de llamadas para suministrar el nuevo parámetro y puede dejar que el compilador haga el trabajo de encontrarlos todos.


Esa es una gran idea. Por lo general, los contratos de datos se realizan, por ejemplo, en WCF.

Una ventaja de este modelo es que si agrega un nuevo parámetro, el consumidor de la clase no necesita cambiar solo para agregar el parámetro.

Como menciona David Heffernan, puede ayudar a auto documentar el código:

FrobRequest frobRequest = new FrobRequest { FrobTarget = "Joe", Url = new Uri("http://example.com"), Count = 42, }; FrobResult frobResult = Frob(frobRequest);



Puede ser razonable utilizar una clase de datos antiguos sin formato , ya sea que esté refactorizando o no. Tengo curiosidad de por qué pensaste que podría ser.


Si bien la refacturación a un Objeto de parámetro no es en sí misma una mala idea, no se debe utilizar para ocultar el problema de que una clase que necesita 30 datos proporcionados desde otra parte podría ser algo así como un olor a código. La refactorización de Introducir parámetro de objeto probablemente debería considerarse como un paso en el camino en un proceso de refactorización más amplio en lugar del final de ese procedimiento.

Una de las preocupaciones que realmente no aborda es la de Feature Envy. ¿El hecho de que la clase que se pasa el Objeto de parámetro está tan interesada en los datos de otra clase no indica que tal vez los métodos que operan en esos datos deberían trasladarse a donde residen los datos? Es realmente mejor identificar los clústeres de los métodos y los datos que pertenecen juntos y agruparlos en clases, lo que aumenta la encapsulación y hace que su código sea más flexible.

Después de varias iteraciones de comportamiento de separación y los datos en los que opera en unidades separadas, debería descubrir que ya no tiene clases con enormes cantidades de dependencias, lo que siempre es un mejor resultado final porque hará que su código sea más flexible.


Si bien otras respuestas aquí indican correctamente que es mejor pasar una instancia de una clase que pasar 30 parámetros, tenga en cuenta que una gran cantidad de parámetros puede ser un síntoma de un problema subyacente.

Por ejemplo, muchas veces los métodos estáticos crecen en su número de parámetros, porque deberían haber sido siempre métodos de instancia, y está transfiriendo mucha información que podría mantenerse más fácilmente en una instancia de esa clase.

Alternativamente, busque maneras de agrupar los parámetros en objetos de un nivel de abstracción más alto. Vaciar un grupo de parámetros no relacionados en una sola clase es un último recurso de OMI.

Ver ¿Cuántos parámetros son demasiados? para algunas ideas más sobre esto.


También podría considerar usar una estructura en lugar de una clase.

¡Pero lo que estás tratando de hacer es muy común y una gran idea!


Tantas buenas respuestas aquí. Me gustaría agregar mis dos centavos.

El objeto de parámetro es un buen comienzo. Pero hay más que se puede hacer. Considere lo siguiente (ejemplos ruby):

/ 1 / En lugar de simplemente agrupar todos los parámetros, ver si puede haber una agrupación significativa de parámetros. Es posible que necesite más de un objeto de parámetro.

def display_line(startPoint, endPoint, option1, option2)

podría convertirse

def display_line(line, display_options)

/ 2 / El objeto de parámetro puede tener un número de propiedades menor que el número de parámetros original.

def double_click?(cursor_location1, control1, cursor_location2, control2)

podría convertirse

def double_click?(first_click_info, second_click_info) # MouseClickInfo being the parameter object type # having cursor_location and control_at_click as properties

Tales usos lo ayudarán a descubrir posibilidades de agregar un comportamiento significativo a estos objetos de parámetros. Descubrirás que sacuden su olor inicial de la Clase de Datos más rápido para tu comodidad. : -)