¿Cuál es la mejor práctica para ordenar parámetros en una función?

45

Algunas veces (rara vez), parece que crear una función que tome una cantidad decente de parámetros es la mejor ruta. Sin embargo, cuando lo hago, siento que a menudo elijo el orden de los parámetros al azar. Normalmente voy por "orden de importancia", con el parámetro más importante primero.

¿Hay una mejor manera de hacer esto? ¿Existe una forma de "mejores prácticas" para ordenar parámetros que mejore la claridad?

    
pregunta Casey Patton 16.08.2011 - 03:32

13 respuestas

47

En general: utilízalo .

Escriba una prueba para su función, una prueba del mundo real.
Algo que realmente te gustaría hacer con esa función .

Y vea en qué orden los colocó.

A menos que ya tenga (o conozca) algunas funciones que hagan algo similar.
En ese caso: cumple con lo que ya hacen, al menos para los primeros argumentos.

por ejemplo ¿Todos ellos toman un documento / objeto / archivo-puntero / serie de valores / coordenadas como el primer argumento (s)? Por el amor de Dios, cumpla con esos argumentos .

Evita confundir a tus compañeros de trabajo y tu futuro yo .

    
respondido por el ZJR 16.08.2011 - 03:43
26

Normalmente voy con estas reglas, aunque no siempre con la misma prioridad. Supongo que ahora es un proceso de pensamiento automático, y no pienso demasiado en ello, excepto en el diseño de API pública .

Embudo de selección

  1. Semántica
  2. Importancia / Relevancia
  3. Frecuencia de uso
  4. problemas de E / S

1. La semántica primero

Especialmente en OOP, selecciona parámetros en función de su significado semántico para la acción o el mensaje. La firma de un método bien nombrado con un parámetro bien nombrado debe:

  • siento natural llamar,
  • sea auto-descriptivo en términos de intención y comportamiento.

(Por estos motivos, a veces el uso de tipos o alias personalizados en lugar de primitivos puede aumentar la expresividad de su firma).

2. Entonces la importancia

El parámetro más "significativo" es el primero (o el siguiente ...)

3. Luego Frecuencia

La frecuencia también es importante, especialmente en un idioma en el que no tiene parámetros con nombre, pero puede tener valores predeterminados en los parámetros de posición. Eso implica que el orden de los parámetros no varía y que, obviamente, no puede establecer los parámetros N + 1 si desea forzar el valor predeterminado del parámetro Nth (excepto si su idioma tiene un concepto de parámetro de marcador de posición). ).

La buena noticia para usted es que, por lo general, la frecuencia se relaciona con la importancia, por lo que va de la mano con el punto anterior. Y entonces probablemente depende de usted elaborar su API para que tenga la semántica adecuada.

4. No olvidemos la E / S

si su método / función toma alguna entrada y produce una salida, y la última no debe ser "devuelta" (a través de una declaración de retorno) o "lanzada" (utilizando un sistema de excepción), entonces queda con el Opción para devolver los valores a la persona que llama usando sus otros parámetros (o el parámetro de entrada). Eso se relaciona con la semántica, y en la mayoría de los casos tendrá sentido que los primeros parámetros definan la salida, y los últimos parámetros reciban la salida.

Además, otro enfoque para tener menos parámetros y maximizar la semántica sería utilizar un enfoque funcional, o definir un patrón de generador , para que pueda apilar claramente sus entradas, definir sus salidas y recuperarlas cuando sea necesario.

(Tenga en cuenta que no menciono las variables globales, porque ¿por qué usaría una, verdad?)

Algunas cosas a considerar

  • Utilidad

    La mayoría de los anteriores se mostrarán de forma natural si sigues los consejos de ZJR: ¡Úsalo!

  • Considere refactorizar

    Si te preocupa el orden de los parámetros, tal vez esta preocupación encuentre su raíz en lo anterior y en el hecho de que tu API está mal diseñada. Si tiene demasiados parámetros, es probable que algo pueda ser componente / modularizado y refactorizado .

  • Considera el rendimiento

    Tenga en cuenta que las implementaciones de algunos lenguajes incurrirán en impactos muy importantes en la administración de la memoria en tiempo de ejecución cuando use parámetros. De ahí la razón por la que los libros de estilo de muchos idiomas recomiendan mantener la lista de parámetros simple y corta . En 4 parámetros máximo, por ejemplo. Lo dejo como un ejercicio para que averigües por qué.

  • Bevan's responda y mencione las recomendaciones de Clean Code ¡son definitivamente relevantes también!

respondido por el haylem 16.08.2011 - 04:12
19

Respetaría respetuosamente que preocuparse por el orden de los parámetros es preocuparme por lo incorrecto.

En el libro del Tío Bob " Clean Code " aboga, persuasivamente, esos métodos nunca deben tener más de dos argumentos, y la mayoría debe tener solo uno, si es que tiene alguno. Cuando este es el caso, el pedido es obvio o no importante.

Sin embargo, de manera imperfecta, estoy tratando de seguir el consejo del tío Bob, y está mejorando mi código.

En los casos raros en los que un método requiere más información, introduce un objeto de parámetro es una buena idea. Por lo general, encuentro que este es el primer paso hacia el descubrimiento de un nuevo concepto (objeto) que es clave para mi algoritmo.

    
respondido por el Bevan 16.08.2011 - 05:52
10

Intento poner primero los parámetros IN, luego los parámetros OUT. También hay algún orden natural, por ejemplo. createPoint(double x, double y) es altamente preferible a createPoint(double y, double x) .

    
respondido por el quant_dev 16.08.2011 - 04:01
6

Nunca he visto una "mejor práctica" documentada con respecto a este tema en particular, pero mi estándar personal es enumerarlos en el orden en que aparecerán en el método para el que se están utilizando o si el método es más de un paso a una capa de datos, los enumeraré en el orden en que aparecerían en el esquema de db o en los métodos de capa de datos.

Además, cuando hay varias sobrecargas de un método, observo que la manera típica es enumerarlas comenzando con parámetros que son comunes a todos (o la mayoría) de los métodos con cada método diferente que se agrega al final para cada uno método de sobrecarga como:

void func1(string param) { }
void func2(string param, int param2) { }
void func3(string param, string param3) { }
void func3(string param, int param2, string param3) { }
    
respondido por el Joel Etherton 16.08.2011 - 03:42
6

Orden: entrada (s), salida (s), parámetros opcionales.

    
respondido por el Jonathan Khoo 16.08.2011 - 05:19
3

A menudo sigo la convención de C / C ++ de colocar primero los parámetros const (es decir, los parámetros que se pasan por valor) y luego los que se pasan por referencia. Es posible que este no sea necesariamente el método correcto para llamar a las funciones pero, si está interesado en cómo cada compilador maneja los parámetros, eche un vistazo a los siguientes enlaces para conocer las reglas que gobiernan y / o el orden en que se insertan los parámetros en la pila.

enlace

enlace

    
respondido por el Bill 16.08.2011 - 04:11
1

Por lo general, sigo con el orden de los parámetros "lo que parece menos cíclico". Cuantas menos veces necesite ir a la definición de método / función, mejor. Y es bueno tener parámetros con nombre que sean descriptivos en cuanto a para qué se usan, de esa manera, cuando aparece la pequeña información sobre herramientas (VS), eso lo hace aún más fácil.

Si tiene líneas y líneas de parámetros, es posible que desee considerar un diseño diferente. Retroceda y vea cómo puede dividir eso en más funciones / métodos. Solo una idea, pero cuando tengo una docena de parámetros en mi función, casi siempre no es un problema de parámetros, sino un problema de diseño.

    
respondido por el user29981 16.08.2011 - 05:01
1

Pídelo de la forma que creas que probablemente se beneficiará con el curry. Por ejemplo, los parámetros de la función primero.

    
respondido por el alternative 08.03.2012 - 23:14
1
  

A veces (rara vez), parece que crear una función que tome una cantidad decente de parámetros es la mejor ruta.

El uso de varios parámetros suele ser un indicador claro de que viola el SRP en este método. Es poco probable que un método que necesite muchos parámetros haga solo una cosa. Excpetion puede ser una función matemática o un método de configuración, donde de hecho se necesitan varios parámetros como tales. Evitaría múltiples parámetros ya que el diablo evita el agua bendita. Cuantos más parámetros utilice dentro de un método, mayor será la posibilidad de que el método sea (también) complejo; más complejidad significa: más difícil de mantener y eso es menos deseable.

  

Sin embargo, cuando lo hago, siento que a menudo estoy eligiendo el orden de los parámetros al azar. Normalmente voy por "orden de importancia", con el parámetro más importante primero.

En principio, está seleccionando al azar . Por supuesto, puede pensar que el parámetro A es más relevante que el parámetro B ; pero ese podría no ser el caso para los usuarios de su API, quienes piensan que B es el parámetro más relevante. Así que incluso si estuviera atento a la hora de elegir el pedido, para otros podría parecer aleatorio .

  

¿Hay una mejor manera de hacer esto? ¿Existe una forma de "mejores prácticas" para ordenar parámetros que mejore la claridad?

Hay varias maneras de salir:

a) El caso trivial: no utilice más de un parámetro.

b) Como no especificó, qué idioma ha elegido, existe la posibilidad de que elija un idioma con parámetros con nombre . Esto es bueno, azúcar sintáctica , que le permite aflojar el significado del orden de los parámetros: fn(name:"John Doe", age:36)

No todos los idiomas permiten tales detalles. ¿Entonces, qué?

c) Podría usar un Dictionary / Hashmap / Associative Array como parámetro: p.ej. Javascript permitiría lo siguiente: fn({"name":"John Doe", age:36}) que no está muy lejos de (b).

d) Por supuesto, si trabaja con un lenguaje estático como Java. podría usar un Hashmap , pero perdería la información de tipo (por ejemplo, cuando trabaje con HashMap<String, Object> ) cuando los parámetros tengan diferentes tipos (y deben ser emitidos).

El siguiente paso lógico sería pasar un Object (si está usando Java) con las propiedades apropiadas o algo más liviano como una struct (si escribe, por ejemplo, C # o C / C ++) .

Regla de oro:

1) Mejor caso: su método necesita el parámetro no en absoluto

2) Buen caso: su método necesita un parámetro

3) Caso tolerable: su método necesita dos parámetros

4) Todos los demás casos deben ser refactorizados

    
respondido por el Thomas Junk 09.02.2015 - 21:28
0

A menudo, un objeto complejo como parámetro es mejor: una versión pobre de los parámetros con nombre que funciona en la mayoría de las plataformas. Y abre la puerta a parámetros con comportamiento para arrancar.

Para un ejemplo de la mayoría de las cosas que no debes hacer, puedes intentar leer la documentación estándar de la biblioteca de PHP.

    
respondido por el Wyatt Barnett 16.08.2011 - 06:17
0

Por lo general, los ordeno con el requisito primero, que con alguna medida combinada de importancia y frecuencia de uso según un "sentimiento" (puede verse como ORDER BY required DESC, SOME_MAGIC_FEELING(importancy,frequency) ) y no de acuerdo con ninguna práctica específica.

Sin embargo, como han señalado otros, creo que el problema subyacente que hace que esto sea un problema es usar demasiados parámetros (IMHO, cualquier cosa, ygt; 3 es demasiado) y ese es el problema real al que deberías estar tratando. Hay un publicación interesante sobre eso en el blog de rebecca murphey.

Creo que cuando solo tienes 1-3 argumentos, el orden correcto es bastante obvio y simplemente "sientes" lo que es correcto.

    
respondido por el shesek 16.08.2011 - 14:24
0

Similar a la respuesta de @Wyatt Barnetts, algo más que unos pocos parámetros o parámetros muy explícitos para el método, recomiendo pasar un objeto en su lugar. Esto suele ser más fácil de actualizar / mantener, más claro de leer y elimina la necesidad de preocuparse por el pedido . Además, demasiados parámetros para un método es un olor de código y hay patrones de refactorización que puede seguir para ayudar a corregirlo.

Ejemplo explícito:

public int add(int left, int right)
{
  return left + right;
}

Ya que este es un ejemplo claramente definido y la adición es conmutativa (el orden no importa), simplemente siga con él.

Sin embargo, si agrega algo más complejo:

public SomeComplexReturnValue Calculate(int i, float f, string s, object o)
{
  // do work here
}

Se convertiría en:

public class SomeComplexInputForCalculation
{
  public int i; 
  public float f;
  public string s; 
  public object o;
}

public SomeComplexReturnValue Calculate(SomeComplexInputForCalculation input)
{
  // do work here
}

Espero que esto ayude ...

    
respondido por el longda 19.08.2011 - 03:16

Lea otras preguntas en las etiquetas