¿Son útiles los parámetros opcionales o un obstáculo para el mantenimiento de la aplicación? [cerrado]

14

Como se indica en el título, ¿son útiles los parámetros opcionales, como los utilizados en C #, o son un obstáculo para el mantenimiento de la aplicación y deben evitarse ya que pueden dificultar la comprensión del código?

rjzii
fuente
3
Descargo de responsabilidad: se puede abusar de cualquier función de idioma en las manos equivocadas. Si un idioma implementa esto de una manera inteligente, y esta función de idioma no se superpone demasiado con una función de idioma existente de una manera aburrida, entonces están bien, de hecho son bastante útiles. Python tiene algunos "trucos" de parámetros / empaquetado y otros parámetros (trucos en un buen sentido, no en sentido Perl).
Trabajo
Intente escribir una aplicación en C # que interactúe con Excel sin usar parámetros opcionales. Eso debería responder a su pregunta más allá de cualquier duda razonable.
Dunk

Respuestas:

22

Los parámetros opcionales, en mi experiencia, han sido algo bueno. Nunca los he encontrado confusos (al menos no más confusos que la función real), ya que siempre puedo obtener los valores predeterminados y saber cómo se llama.

Un uso para ellos es cuando tengo que agregar otro parámetro a una función que ya está en uso general, o al menos en la interfaz pública. Sin ellos, tendría que rehacer la función original para llamar a una que tenga otro argumento, y eso puede volverse realmente viejo si termino agregando argumentos más de una vez.

David Thornley
fuente
1
+1 Y es valioso con métodos sobrecargados que agregan un argumento como new Circle(size, color, filled, ellipseProportions)dónde sizey colorse requieren y el resto son predeterminados.
Michael K
15

En general, si necesita muchos parámetros / opcionales con frecuencia, sus funciones están haciendo demasiado y deben dividirse. Es probable que esté rompiendo el SRP (Principio de responsabilidad única).

Busque los parámetros que se pueden agrupar, por ejemplo (x e y, se convierten en un punto).

¿Son estos parámetros opcionales indicadores con un valor predeterminado? Si usa banderas, la función debe dividirse.

Eso no quiere decir que nunca debe tener parámetros opcionales, pero en general, más de uno o dos parámetros sugieren un olor a código.

También podría ser una pista de que la función, en realidad, debería ser una clase, con los parámetros opcionales cambiados a propiedades, y los parámetros necesarios forman parte del constructor.

CaffGeek
fuente
1
+1 por tener cuidado. Cualquier característica, por buena que sea, puede ser abusada.
Michael K
3
Este es un gran consejo para producir código de raviolis de ingeniería excesiva donde los usuarios de su API tienen que usar al menos 6 clases y 15 funciones para que suceda incluso lo más simple.
dsimcha
1
@dsimcha, ¿cómo obtienes eso de lo que escribí? Guau. ¿Por favor explique? Sería un diseño igualmente malo tener una "superfunción", que es lo que obtienes cuando tienes muchos parámetros opcionales. Lea acerca de los principios de diseño SOLID y escriba código comprobable. Preferiblemente usando TDD. Luego regrese e intente explicarme que reducir los parámetros en las funciones es algo malo.
CaffGeek
1
El código comprobable es bueno, pero también lo es una API limpia y utilizable que no es excesivamente detallada o detallada y no calza las clases en situaciones donde una función es la abstracción adecuada. Creo en el principio de responsabilidad única con responsabilidades definidas en un alto nivel de abstracción. Si las responsabilidades se definen a un nivel demasiado bajo, las unidades individuales se simplifican demasiado, de modo que sus interacciones son demasiado complejas.
dsimcha
1
@dsimcha, te estás perdiendo el punto. Las unidades individuales deben seguir siendo unidades individuales y no agruparse en una sola función. Eso tampoco significa que todas sean funciones de acceso público. Su API es la puerta de entrada al código, y debe ser limpia y concisa. Una función con varios parámetros opcionales no es limpia ni concisa. Sin embargo, sobrecargar una sola función con parámetros lógicos es mucho más claro. Por ejemplo, hay funciones en muchas API donde, dos parms son opcionales, pero se requiere uno u otro. ¿Qué tiene de claro eso cuando ambos están marcados como opcionales?
CaffGeek
4

Los parámetros opcionales están bien

Por lo general, la justificación es que a) sabes que tienes muchos argumentos posibles para tu método, pero no quieres sobrecargarlo por miedo a agrupar tu API, o b) cuando no conoces todos los argumentos posibles pero no quiere obligar a su usuario a proporcionar una matriz. En cada caso, los parámetros opcionales vienen al rescate de una manera ordenada y elegante.

Aquí hay unos ejemplos:

1. Desea evitar la sobrecarga y no desea especificar una matriz

Eche un vistazo a printf () de C, Perl, Java, etc. Es un gran ejemplo del poder de los parámetros opcionales.

Por ejemplo:

printf("I want %d %s %s",1,"chocolate","biccies");

printf("I want %d banana",1);

Sin sobrecarga, sin matrices, simple e intuitivo (una vez que haya captado los códigos de formato de cadena estándar). Algunos IDEs incluso le dirán si su cadena de formato no coincide con sus parámetros opcionales.

2. Desea permitir el uso de valores predeterminados y mantenerlos ocultos para el usuario del método.

sendEmail ("[email protected]");

El método sendEmail detecta que faltan varios valores esenciales y los completa utilizando valores predeterminados definidos (asunto, cuerpo, cc, bcc, etc.). La API se mantiene limpia, pero flexible.

Una nota sobre demasiados parámetros

Sin embargo, como han dicho otros, tener demasiados parámetros obligatorios para un método indica que probablemente tenga algo mal con su diseño. Esto es particularmente cierto si comparten el mismo tipo, ya que el desarrollador puede cambiarlos por accidente y dar lugar a resultados extraños en tiempo de ejecución:

String myMethod(String x, String y, String z, String a, int b, String c, int d) {}

es un candidato ideal para la refactorización del objeto Introducir parámetro para crear

String myMethod(ParameterObject po) {}

class ParameterObject {
  // Left as public for clarity
  public String x;
  public String y;
  ... etc

}

Esto a su vez puede conducir a un mejor diseño basado en un patrón Factory con una especificación proporcionada como objeto de parámetro.

Gary Rowe
fuente
1
Las funciones de formato de cadena como printf son la excepción a la regla, se podría argumentar que si bien usan una lista ilimitada de parámetros opcionales, es más como si el argumento fuera una matriz que parámetros opcionales, a pesar de cómo se implementa.
CaffGeek
@Chad Ajusté mi respuesta para diferenciar mejor entre parámetros opcionales y cuándo hacen la transición a un olor a código (como mencionó en su respuesta).
Gary Rowe
@Gary Rowe, demasiados parámetros opcionales también son malos en la mayoría de los casos.
CaffGeek
@Chad Estoy de acuerdo, pero la mayoría de los idiomas no proporcionan una forma de especificar un límite en el número de argumentos opcionales, por lo que es un enfoque de todo o nada. Se ve obligado a dejar que su método lo aplique y, obviamente, si su método trata con 500 variables, definitivamente será necesario refactorizarlo.
Gary Rowe
@Gary Rowe, ¿qué quiere decir con "la mayoría de los idiomas no proporcionan una forma de especificar un límite en el número de argumentos opcionales"? En la mayoría de los idiomas, los marca como tales o no les proporciona valores al llamar a la función, pero el encabezado de la función todavía tiene los parámetros definidos. De acuerdo, en algunos idiomas puedes agregar tantos parámetros como desees después de haber completado los definidos, pero no creo que ese sea el tipo de parámetros opcionales de los que estamos hablando aquí. (aparte de la excepción de formato de cadena)
CaffGeek
2

Uno de los problemas con los parámetros predeterminados en C # (estoy pensando que DoSomething nulo (int x = 1)) es que son constantes. Eso significa que si cambia el valor predeterminado, tendrá que volver a compilar cualquier consumidor de esa llamada al método. Si bien esto es bastante fácil de hacer, hay ocasiones en que esto es peligroso.

Po-ta-toe
fuente
1

Depende de lo que esté haciendo tu código. Si hay valores predeterminados razonables, debe usar parámetros opcionales, pero si no hay valores predeterminados razonables, agregar parámetros opcionales hará que su código sea más complicado. En muchos casos, los parámetros opcionales son una forma ordenada de eludir las comprobaciones nulas y eliminar la lógica de ramificación. Javascript no tiene parámetros opcionales, pero hay una manera de emularlos con || (lógico o) y lo uso todo el tiempo cuando hago cosas relacionadas con la base de datos porque si el usuario no proporciona algún valor, entonces sustituyo mis propios valores con la ayuda de || lo que me ahorra la molestia de escribir un montón de declaraciones if if.

davidk01
fuente
1

Los parámetros opcionales son una excelente manera de hacer que las cosas simples sean simples y que las cosas complicadas sean posibles simultáneamente. Si hay un valor predeterminado razonable razonable que la mayoría de los usuarios querrán, al menos en casos de uso rápido y sucio, entonces no deberían tener que escribir repeticiones para especificarlo manualmente cada vez que llaman a su función. Por otro lado, si las personas pueden tener una buena razón para querer cambiarlo, entonces debe exponerse.

Usar una clase es, en mi humilde opinión, una solución terrible, ya que es detallado, ineficiente e inconsistente con el modelo mental típico de lo que hace una clase. Una función es la abstracción perfecta para un verbo, es decir, hacer algo y regresar. Una clase es la abstracción correcta para un sustantivo, es decir, algo que tiene estado y puede manipularse de varias maneras. Si el primero debe ser el modelo mental del usuario API, entonces no lo convierta en una clase.

dsimcha
fuente
1

El problema con los argumentos opcionales es que las personas tienden a meter más y más (y más) argumentos en la función en lugar de extraer código relevante en una nueva función. Esto se lleva al extremo en php . Por ejemplo:

bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
                      [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Martin Wickman
fuente
1

Los parámetros opcionales son básicamente una forma diferente de sobrecargar una función. ¿Entonces esto básicamente se reduce a: "está sobrecargando una función incorrecta"?

Pieter B
fuente
1

Inicialmente me encantó esta característica en Python, y la usé para 'extender' los métodos ya utilizados. Y se veía agradable y fácil, pero retrocedió pronto; porque cuando agregué un parámetro opcional, esto estaba modificando el comportamiento de un método existente en el que confiaba el antiguo cliente y de una manera que no fue captada por los casos de prueba de unidad existentes. Básicamente, hacer esto es romper el Principio Abierto Cerrado; el código está abierto para extensión pero cerrado para modificación. Así que creo que usar esta función para modificar el código existente no es una buena idea; pero está bien si se usa desde el principio

Alex Punnen
fuente
0

Creo que sería mejor sobrecargar una función con firmas diferentes (es decir, parámetros) que usar parámetros opcionales.

Código difícil
fuente
¿Por qué? Creo que es más limpio si puedes combinar un montón de métodos sobrecargados en un método usando parámetros predeterminados si todos los métodos tienen la misma funcionalidad básica
Amit Wadhwa
Puedes pensar eso. No creo que Microsoft haga todo de la manera correcta, pero si fuera exacto, nunca vería sobrecargas al usar .NET Framework, solo una firma de función enorme, como en el antiguo VB6.
HardCode