¿Es una mala idea enumerar cada argumento de función / método en una nueva línea y por qué?

22

Trabajo con alguien que, cada vez que llaman a una función, ponen los argumentos en una nueva línea, por ejemplo

aFunction(
    byte1,
    short1,
    int1, 
    int2,
    int3,
    int4,
    int5
) ;

Esto me resulta muy molesto, ya que significa que el código no es muy compacto, por lo que tengo que escanear más y más para entender la lógica. Me interesa saber si esto es realmente una mala práctica y, de ser así, ¿cómo puedo convencerlos de que no lo hagan?

Daniel Ball
fuente
25
+1, no sé lo suficiente para responder a tu pregunta, pero también odio esto. Sin embargo, si tiene tantos argumentos en una función, su función probablemente esté haciendo demasiado.
maple_shaft
28
Más concretamente, ¿por qué todavía tenemos que ver las preferencias de los demás sobre esto? ¿Por qué nuestros IDEs no pueden presentarlo automáticamente en el estilo que queramos?
Alex Feinman
55
Mike, me gusta que el código ocupe un espacio mínimo en la pantalla. Pero es un compromiso. Puse {en una línea separada porque facilita la coincidencia con el cierre} y entiendo correctamente el alcance del bloque. Vale la pena el compromiso de perder una línea de bienes raíces de pantalla.
Brian Schroth
2
@ Alex: Tienes toda la razón. Creo que lo correcto sería tener un lenguaje donde el árbol de análisis del código se almacene en el disco y se muestre de acuerdo con las preferencias del usuario.
Neil G
1
@maple_shaft Desprecio declaraciones como esa. No porque no haya ninguna verdad, sino porque muchas personas siguen esos consejos sin dejar lugar a matices.
Stijn

Respuestas:

38

Es solo una guía de codificación que puede gustarle o no. Lo importante es que usted y sus colegas acuerden usarlo o no.

Obviamente, la mejor manera de aumentar la legibilidad es limitar el número de argumentos.

Martin Wickman
fuente
24
Demasiadas personas reducen los argumentos al volcarlos en una matriz. Prefiero ver un desastre feo que un código de aspecto más limpio con complejidad oculta.
Satanicpuppy
18
Las matrices no son el camino a seguir. Puede haber una estructura oculta en los argumentos, o tal vez la función está haciendo demasiado y debería dividirse.
Michael K
44
Me parece que el uso de varias líneas ayuda a hacer que los parámetros IF legibles por código sean expresiones largas o demasiados. De lo contrario, es molesto.
PedroC88
3
Ponerlos en un objeto de transferencia de datos simplemente mueve el problema. Si se requieren todos los argumentos, todos deben ser argumentos obligatorios del constructor del DTO, lo que significa que todavía tiene tantos argumentos.
Scott Whitlock
21

Es una cuestión de preferencia. Para llamadas a funciones complicadas donde desea documentar cada parámetro, o donde las variables son bastante largas y hay muchas, esto puede ser bueno.

Por ejemplo:

do_complex_op(
      0, //Starting state, always 0, ask Joe why
      X, //X-coord of thingy
      y, //Y-coord of thingy
      73, //in this case, we don't want to use Z but want constant 
      dlogMessageTitle, //message for dialogue title
      dlogMessageText, //message for dialogue contents, don't care about this.
      SomethingIP, //IP of something-or-other server, can be NULL, won't crash.
      someObject.childObject.getValue(key1).HVAL, //very long path to HVAL
      someObject.childObject.getValue(key1).LVAL, //very long path to LVAL
      this.parentWindow.owner.mainTextBox.text.value.trim, //get the trimmed text, untrimmed text causes weird output
      pvrMainSettingForLongBlahs.getObjectByPath(somePath),
      pvrMainSettingForLongBlahs.K_TCA_UPPER_LIMIT,
      pvrMainSettingForLongBlahs.K_ENDPOINT_COMPLIANCE_LEVEL,
 );

Con lenguajes que permiten parámetros con nombre, esto es más común si usa los nombres de los parámetros (el ejemplo está en PL / SQL):

PKG_SOME_TEST_CODE.FN_DO_SOMETHING( in_text => 'test text',
                                    in_id => v_id,
                                    in_ref_id => v_ref_id,
                                    out_array_for_storage => v_bArray); 

Pero estoy de acuerdo con usted en que si la llamada a la función es simple y no tiene demasiados parámetros, esto podría ser molesto, como por ejemplo:

setColour (
    r,
    g,
    b
 );

Me resulta mucho más fácil de leer como

 setColour(r,g,b);

Para @ammoQ:

rc=a(b,c(d,e(f)))

rc=a(
     b,
     c(
       d,
       e(
         f
        )
      )
    )
FrustratedWithFormsDesigner
fuente
11
El primer ejemplo es una respuesta incorrecta a un problema real. ¿Por qué no usar anmes explícitas variables en primer lugar?
deadalnix
@deadalnix: Buen punto, lo limpié un poco.
FrustratedWithFormsDesigner
1
Cierto. Sin embargo, no siempre es un problema con los nombres de variables. Tiene más que ver con nombres largos de variables, argumentos con valores predeterminados, etc.
inspectorG4dget
44
Yo diría que la mejor solución al problema es refactorizar do_complex_op () para que tome una estructura como parámetro. Entonces puede hacerlo do_complex_op(new paramStruct { StartingState = 0, XCoord = xcoord }), luego se vuelve autodocumentado y mucho más fácil de leer
KallDrexx
1
@KallDrexx: estoy de acuerdo, pero a veces cambiar el código no es una opción, como cuando es una función en la biblioteca de otra persona. Claro, podría hacer una envoltura, pero aún tendré que llamar a su función original en algún momento.
FrustratedWithFormsDesigner
10

En mi opinión, todo lo que es poco común es una mala práctica, a menos que se pueda demostrar positivamente su superioridad sobre el estilo habitual. "La cuestión del gusto" es una excusa pobre para escribir código que es más difícil de leer de lo necesario para la mayoría de los programadores, porque un día, un alma pobre, no acostumbrada a ese estilo, tendrá que mantener ese código.

Probar que es poco común es relativamente fácil, muestre la fuente de ejemplos en MSDN o sitios similares, muestre grandes bases de código abierto, etc. Muestre la salida de los embellecedores de código. En última instancia, muestre cómo todos los demás en su equipo lo están haciendo. No aceptes un mal estilo solo porque alguien es demasiado terco.

usuario281377
fuente
Hm ... con ese enfoque, ¿cómo podríamos introducir una nueva mejor práctica (o, gramaticalmente correcta: una mejor práctica )?
Treb
2
Treb: Claro, solo demuestre que la mejor práctica es de hecho mejor , no solo diferente .
user281377
44
Pero "más difícil de leer" es, en sí mismo, subjetivo y una cuestión de opinión. Para mí, un argumento por línea es más fácil de analizar visualmente que dos, tres o cuatro argumentos por línea. Y siempre divido una llamada en varias líneas si se extiende más allá de aproximadamente la marca de 100 caracteres en el editor.
Toby
2
Meh "Más difícil de leer" se puede medir objetivamente. Simplemente no suele ser así. Discutir sobre eso es más divertido.
JasonTrue
1
se puede medir objetivamente pero no independientemente de la persona que lee.
jk.
9

Bueno, aquí hay un cebo de votos negativos. Nunca me han acusado de hacer lo popular. Claramente, si las cosas encajan en una línea, entonces bien, ajústelas en una línea.

Pero mi principal preocupación no es si el código es "feo" o "bonito". Mi principal preocupación es lo fácil que es comprender y realizar cambios sin cometer errores.

Si los argumentos son largos y hay muchos, ¿por qué no ponerlos en líneas separadas? En mi opinión, eso hace que sea más fácil ver qué son, y más fácil cambiarlos si es necesario. También me da espacio para adjuntar un comentario a cada argumento si lo deseo.

También quiero minimizar la posibilidad de cometer un error si agrego o elimino un argumento a una función, lo que es más probable que ocurra al final de una lista de argumentos que al principio. Por esa razón, prefiero poner la coma (,) al principio de una línea, que al final. Entonces, si, por ejemplo, quiero eliminar o agregar un argumento al final de la lista, es una edición de una línea. No tengo que jugar con la coma que debe ir al final de todas las líneas sino a la última, donde la última tiene que terminar con un paréntesis.

Entonces (chico, me van a echar por esto) lo escribo así:

nameOfFunction(firstArgument
    , secondArgument // optional comment
       ...
    , lastArgument   // optional comment
    );

Cuando hay una función con de cinco a veinte argumentos, la función no fue así de una vez. Creció con el tiempo, lo que significa que hubo muchas ediciones. Cualquier edición no completada es un error de sintaxis o un error. Así que no digo que esto sea bonito. Afirmo que ayuda a hacer las ediciones correctas.

(Y para aquellos que dicen que debería pasar una estructura en su lugar, todo lo que hace es desplazar el problema, porque necesita un montón de líneas de código para completar la estructura, sin mencionar el código adicional para declararlo y asignarlo).

Mike Dunlavey
fuente
1
Personalmente, creo que esta es una gran respuesta porque explicaste muy bien tu razonamiento. Buen trabajo Mike.
Jordania
8

Yo tampoco lo llamaría. La mejor práctica en la que he trabajado ha sido que las llamadas a funciones se realicen en una sola línea, a menos que tenga que desplazarse horizontalmente cualquier cantidad significativa para ver toda la llamada. Es una decisión, pero definitivamente diría que poner todas las funciones como esta está fuera de línea a menos que ese sea el estándar establecido por su organización.

Esta es la razón por la cual es una buena práctica para una organización establecer un conjunto de guías que todos los programadores deben cumplir. Se trata de consistencia y legibilidad.

Ortigas Jarrod
fuente
5

Hace que sea más fácil:

  • Reordenar argumentos.
  • Comente o deshabilite los argumentos.
  • Vea exactamente qué argumento ha cambiado cuando ve diferencias en su sistema de control de versiones
  • Evite volver a sangrar y ajustar todo al agregar o quitar un argumento, o al cambiar el nombre de la función. (Incluso si su editor sangra automáticamente, todavía está creando muchos cambios de espacio en blanco inútiles que hacen que sea más difícil seguir los cambios en su sistema de control de versiones).
Graham Borland
fuente
4

Yo diría que las llamadas a funciones deben estar todas en una línea a menos que excedan significativamente el ancho de código estándar (a menudo 80 caracteres, a menudo causa de argumentos :-).

No veo ninguna ventaja en este estilo. Se ve subjetivamente feo, y me resulta doloroso cuando busco código. Por ejemplo, es posible que desee buscar rápidamente y ver si alguna vez se llama a la función con un cierto parámetro pasado como NULL. Esto es fácil visualmente cuando todos los parámetros están en una línea, y más difícil cuando se dividen así.

Luke Graham
fuente
Esta cosa de 80 caracteres tiene que desaparecer, ya no hay razones técnicamente válidas para ello. Ahora vivimos en una era de monitores 19xx X 16xx y fuentes ajustables Y tamaños de fuente.
anon
44
@anon: ¿razones válidas para ello? ¿Por qué crees que el texto se imprime en columnas y los libros son más angostos de lo que podrían ser? Porque el ojo humano pierde la pista cuando lee a través de líneas muy largas.
Zan Lynx
44
@anon: También me gusta usar mi pantalla panorámica para tener dos o tres archivos abiertos en una división horizontal que vuelve a 80-100 caracteres en una línea.
Zan Lynx
44
@anon: Técnicamente no, prácticamente: demonios SÍ. Zan Lynx tiene toda la razón, además de que hay razones adicionales: fusión, diff, uso de utilidades de línea de comandos ... Ah, y buena suerte, centrándose en la fuente 8p a medida que envejece: o)
MaR
3

Con frecuencia he visto ese estilo en declaraciones o definiciones de funciones , pero nunca en una llamada (hasta ahora). Allí tiene sentido a veces, ya que le permite agregar un comentario para parámetros individuales con mayor claridad. Parece que copió ese estilo a las llamadas sin saber realmente las razones subyacentes. Usted tiene un buen argumento en contra y él no parece tener uno bueno, así que tiene mi voto, pero no soy a quien tiene que convencer.

Karl Bielefeldt
fuente
Veo ambos en las llamadas. Si la lista de parámetros es demasiado larga, debe dividirse en varias líneas. Si los parámetros no se agrupan normalmente dentro de los límites de ancho, espero que estén en líneas separadas. Si los nombres de las funciones y los parámetros se ajustan bien en una línea, a menudo los veo organizados de esa manera.
BillThor 01 de
2

¿Va en contra de los estándares de codificación de la empresa?

Si no es así, inicie una discusión sobre los estándares y lo que a la gente le gustaría ver cambiada. Asegúrate de mencionar esto como una de las cosas que te gustaría cambiar.

Tenga una discusión completa sobre por qué no cree que esto sea útil y esperemos que gane el día. Nunca se sabe que su colega podría convencerlo de que su camino es el mejor después de todo;)

Una vez que tenga un estándar actualizado, se documenta lo que todos deberían codificar, por lo que si su colega persiste en hacerlo, puede mencionarlo en sus revisiones de código.

ChrisF
fuente
2

Puede parecer funky para ti, pero hace que trabajar en código sea más fácil. Mientras refactoriza, puede comentar argumentos individuales muy fácilmente y verificar su refactorización antes de eliminar cosas. También puede comentar y reemplazar temporalmente los tipos con bastante facilidad.

También es más fácil de leer que:

int f(int, int, int,
      char, double, int
      X const&, Y)
{}

No me he vuelto tan extremo como muestra (dado que no hay nombres en los parámetros, no es muy útil), pero me he acostumbrado a dividir cada parámetro en su propia línea o no dividirlo en absoluto.

La parte importante es que su código se puede imprimir o mostrar en pantallas estándar de 80col y seguir siendo legible.

Edward extraño
fuente
2

Raramente obtendrá una respuesta honesta de un programador para algo como esto. Todos responderán con lo que hacen o no prefieren. La verdad es que, a pesar de que todos luchamos con ella a veces, la única "mala práctica" aquí es su propia inflexibilidad.

Tienes que ser brutalmente honesto contigo mismo para poder distinguir entre cosas que son realmente malas y cosas que simplemente te molestan. La verdad es que en C / C ++ y lenguajes similares rara vez encontrará una práctica de sangría que tenga un efecto tangible en la comprensión del código. La mayoría de las discusiones sobre este tipo de cosas solo tienen a ambas partes apiladas con personas que hacen argumentos ridículos y falsos para tratar de justificar su propia preferencia personal.

Lo que para mi lectura ... es exactamente lo que está solicitando en esta pregunta: un argumento ridículo y falso para justificar su preferencia personal.

Dan Olson
fuente
0

Para ser honesto, depende de la persona. Diría que para funciones complejas como lo demuestra el primer ejemplo de FrustratedWithForms, luego sí; de lo contrario un gran NO. Por otra parte, esta es la razón por la que prefiero aplicar la funcionalidad IDE de código arbitrariamente.

Dark Star1
fuente
0

"Me interesa saber si esto es realmente una mala práctica ..."

Sí, es una mala práctica, excepto cuando la lista de variables es anormalmente larga. Pero en ese caso, el problema probablemente se deba al diseño de la función. ¿Por qué no pasar un objeto que encapsula muchos de los parámetros?

"... y si es así, ¿cómo puedo persuadirlos para que no lo hagan?"

Átalos y hazles cosquillas hasta que acepten detener esa basura.

ybakos
fuente
"¿Por qué no pasar un objeto que encapsula muchos de los parámetros?" OK, ahora has movido el problema a ese nuevo objeto. Todavía necesita la misma cantidad de parámetros (a través de su constructor, por ejemplo), por lo que aún tiene el mismo problema.
Stijn
-2

¿Por qué malgastas ciclos en una cuestión tan trivial? Simplemente inicie su IDE de confianza, abra el archivo y vuelva a formatear. Voila! Será en la forma que desee.

Ahora pasemos al tema realmente importante: vi o emacs, LOL.

SnoopDougieDoug
fuente
¿Y luego cuando vienes a comprobar eso en el control de fuente?
pdr
-2

Yo diría que si los argumentos encajan en una línea, hazlo. Si no, entonces un argumento por línea permite una gran legibilidad.

foo(arg1, arg2, arg3, arg4, arg5)

vs.

foo(
    arg1=arg1,
    arg2=arg2,
    arg3=arg3,
    arg4=arg4,
    arg5=arg5,
    arg6=arg6,
    arg7=arg7
)
usuario271413
fuente
3
esto no parece ofrecer nada sustancial sobre los puntos hechos y explicados en las respuestas anteriores 14
mosquito