Las rutinas pueden tener parámetros, eso no es noticia. Puede definir tantos parámetros como necesite, pero demasiados de ellos harán que su rutina sea difícil de entender y mantener.
Por supuesto, puede usar una variable estructurada como solución alternativa: poner todas esas variables en una sola estructura y pasarla a la rutina. De hecho, el uso de estructuras para simplificar las listas de parámetros es una de las técnicas descritas por Steve McConnell en Code Complete . Pero como él dice:
Los programadores cuidadosos evitan agrupar datos más de lo lógicamente necesario.
Entonces, si su rutina tiene demasiados parámetros o usa una estructura para disfrazar una gran lista de parámetros, probablemente esté haciendo algo mal. Es decir, no mantienes el acoplamiento suelto.
Mi pregunta es, ¿ cuándo puedo considerar una lista de parámetros demasiado grande? Creo que más de 5 parámetros, son demasiados. ¿Qué piensas?
Respuestas:
¿Cuándo se considera algo tan obsceno como algo que se puede regular a pesar de la garantía de la 1ra Enmienda a la libertad de expresión? Según el juez Potter Stewart, "lo sé cuando lo veo". Lo mismo vale aquí.
Odio hacer reglas duras y rápidas como esta porque la respuesta cambia no solo según el tamaño y el alcance de su proyecto, sino que creo que cambia incluso hasta el nivel del módulo. Dependiendo de lo que esté haciendo su método, o de lo que se supone que representa la clase, es muy posible que 2 argumentos sean demasiados y sea un síntoma de demasiado acoplamiento.
Sugeriría que al hacer la pregunta en primer lugar, y calificar su pregunta tanto como lo hizo, que realmente sabe todo esto. La mejor solución aquí es no confiar en un número duro y rápido, sino buscar revisiones de diseño y revisiones de código entre sus pares para identificar áreas donde tiene baja cohesión y acoplamiento estrecho.
Nunca tengas miedo de mostrar a tus colegas tu trabajo. Si tiene miedo, esa es probablemente la señal más grande de que algo está mal con su código y que ya lo sabe .
fuente
Una función solo puede tener demasiados parámetros si algunos de los parámetros son redundantes. Si se utilizan todos los parámetros, la función debe tener el número correcto de parámetros. Tome esta función de uso frecuente:
Son 12 parámetros (9 si agrupa los x, y, w y h como un rectángulo) y también están los parámetros derivados del nombre de la clase. ¿Cómo reducirías esto? ¿Desea reducir el número más al punto?
No deje que la cantidad de parámetros le moleste, solo asegúrese de que sea lógico y esté bien documentado y deje que intellisense * lo ayude.
* ¡ Hay otros asistentes de codificación disponibles!
fuente
En Clean Code , Robert C. Martin dedicó cuatro páginas al tema. Aquí está la esencia:
fuente
<algorithm>
lo haría actuar sobre un objeto de rango. Las colecciones serían rangos, pero no todos los rangos serían colecciones. Y de hecho, el impulso ya lo ha hecho. De todos modos, mi punto es que una biblioteca masivamente utilizado hace caso omiso de este consejo, por lo que el peor que ha garantizado que te ocurra si lo hace también, es que muchos de sus millones de usuarios va a jugar con simplificaciones menores en su interfaz ;-)Algunos códigos con los que he trabajado en el pasado usaban variables globales solo para evitar pasar demasiados parámetros.
¡Por favor no hagas eso!
(Generalmente.)
fuente
Si comienza a tener que contar mentalmente los parámetros en la firma y hacerlos coincidir con la llamada, ¡es hora de refactorizar!
fuente
Muchas gracias por todas sus respuestas:
Fue un poco sorprendente encontrar personas que también piensan (como yo) que 5 parámetros es un buen límite para la cordura del código.
En general, las personas tienden a aceptar que un límite entre 3 y 4 es una buena regla general. Esto es razonable ya que las personas suelen pasar un mal rato contando más de 4 cosas.
Como señala Milan , en promedio las personas pueden tener más o menos 7 cosas en su cabeza a la vez. Pero creo que no puedes olvidar que, cuando estás diseñando / manteniendo / estudiando una rutina, debes tener en cuenta más cosas que solo los parámetros.
Algunas personas consideran que una rutina debería tener tantos argumentos como sea necesario. Estoy de acuerdo, pero solo por unos pocos casos específicos (llamadas a API del sistema operativo, rutinas donde la optimización es importante, etc.). Sugiero ocultar la complejidad de estas rutinas agregando una capa de abstracción justo encima de estas llamadas siempre que sea posible.
Nick tiene algunas ideas interesantes sobre esto. Si no quieres leer sus comentarios, te lo resumo: en pocas palabras, depende de :
La moraleja aquí es no tener miedo de mostrar su código a sus compañeros, discutir con ellos e intentar "identificar áreas en las que tenga poca cohesión y un acoplamiento estrecho" .
Finalmente, creo que wnoise está muy de acuerdo con Nick, y concluye su contribución satírica con esta visión poética (ver comentarios más abajo) del arte de la programación:
fuente
Esta respuesta supone un lenguaje OO. Si no está usando una, omita esta respuesta (en otras palabras, esta no es una respuesta independiente del idioma).
Si está pasando más de 3 parámetros más o menos (especialmente tipos / objetos intrínsecos), no es que sea "Demasiados", sino que puede estar perdiendo la oportunidad de crear un nuevo objeto.
Busque grupos de parámetros que se pasan a más de un método; incluso un grupo pasado a dos métodos casi garantiza que debería tener un nuevo objeto allí.
Luego refactoriza la funcionalidad en su nuevo objeto y no creería cuánto ayuda tanto a su código como a su comprensión de la programación OO.
fuente
Parece que hay otras consideraciones además del mero número, aquí hay algunas que vienen a la mente:
relación lógica con el propósito principal de la función frente a configuraciones únicas
Si son solo indicadores del entorno, la agrupación puede ser muy útil
fuente
Uno de los conocidos epigramas de programación de Alan Perlis (relatado en ACM SIGPLAN Notices 17 (9), septiembre de 1982) afirma que "si tiene un procedimiento con 10 parámetros, probablemente se haya perdido alguno".
fuente
Según Steve McConnell en Code Complete , deberías
fuente
Para mí, cuando la lista cruza una línea en mi IDE, entonces es un parámetro demasiado. Quiero ver todos los parámetros en una línea sin romper el contacto visual. Pero esa es solo mi preferencia personal.
fuente
Generalmente estoy de acuerdo con 5, sin embargo, si hay una situación en la que necesito más y es la forma más clara de resolver el problema, entonces usaría más.
fuente
¿Siete cosas en la memoria a corto plazo?
fuente
En los peores 5 fragmentos de código , marque el segundo, "¿Es este un constructor". Tiene más de 37 ⋅ 4 ≈ 150 parámetros:
fuente
Uno más de lo necesario. No me refiero a ser simplista, pero hay algunas funciones que necesariamente necesitan bastantes opciones. Por ejemplo:
Hay 6 argumentos, y cada uno de ellos es esencial. Además, no existe un vínculo común entre ellos para justificar su agrupación. Tal vez podría definir "struct mmapargs", pero eso sería peor.
fuente
prot
yflags
podría haberse unido si el diseñador creyera que 5 era de alguna manera un número mágico que es mucho mejor que 6. Un poco como la forma en queopen
combina el modo de lectura / escritura con todas las otras banderas misceláneas. Y tal vez podría deshacerseoffset
especificando que la sección asignada comienza en la posición de búsqueda actual defiledes
. No sé si hay situaciones en las que puedes hacermmap
una región de la que no eres capazlseek
, pero si no es así, no es estrictamente necesario.mmap
es una buena ilustración del hecho de que algunos diseñadores y usuarios prefieren una larga lista de parámetros, mientras que otros prefieren seguir algunos pasos preparando un número menor de parámetros antes de hacer la llamada.Según las mejores prácticas de Perl , 3 está bien, 4 es demasiado. Es solo una guía, pero en nuestra tienda es a lo que tratamos de apegarnos.
fuente
Yo mismo dibujaría el límite para las funciones públicas en 5 parámetros.
En mi humilde opinión, las listas largas de parámetros solo son aceptables en funciones auxiliares privadas / locales que solo deben llamarse desde algunos lugares específicos del código. En esos casos, es posible que deba transmitir mucha información del estado, pero la legibilidad no es una gran preocupación ya que solo usted (o alguien que mantendrá su código y debe comprender los fundamentos de su módulo) debe preocuparse por llamando a esa función.
fuente
Una pregunta relacionada que debe considerar es qué tan cohesiva es la rutina. Una gran cantidad de parámetros puede ser un olor que le dice que la rutina en sí está tratando de hacer demasiado y, por lo tanto, su cohesión es sospechosa. Estoy de acuerdo en que un número rápido y difícil de parámetros es probablemente imposible, pero supongo que una rutina de alta cohesión implicaría un número bajo de parámetros.
fuente
97 suena a la perfección.
Menos y pierdes flexibilidad.
fuente
Me detengo en tres parámetros como regla general. Además, es hora de pasar una matriz de parámetros o un objeto de configuración, lo que también permite agregar parámetros futuros sin cambiar la API.
fuente
Una restricción de longitud en una lista de parámetros es solo una restricción más. Y restricción significa violencia aplicada. Suena divertido, pero puedes ser no violento incluso cuando estás programando. Simplemente deje que el código dicte las reglas. Es obvio que si tiene muchos parámetros, el cuerpo del método de función / clase será lo suficientemente grande como para utilizarlos. Y los fragmentos de código grandes generalmente se pueden refactorizar y dividir en fragmentos más pequeños. Por lo tanto, obtiene una solución contra tener muchos parámetros como bonificación gratuita, ya que se dividen entre los fragmentos de código refactorizados más pequeños.
fuente
Una cosa que señalaría desde una perspectiva de rendimiento es que, dependiendo de cómo pase los parámetros a un método, pasar muchos parámetros por valor ralentizará el programa porque cada parámetro debe copiarse y luego colocarse en la pila.
¡Usar una sola clase para abarcar todos los parámetros funcionaría mejor porque un solo parámetro pasado por referencia sería elegante, más limpio y más rápido!
fuente
Según yo, podría haber casos en los que exceda 4 o algún número fijo. Cosas a vigilar podrían ser
Desde el punto de vista de la facilidad de uso o la facilidad de lectura del código, creo que cuando necesita "ajustar" la firma de su método, eso debería hacer que se detenga y piense, a menos que se sienta impotente y todos los esfuerzos para hacer que la firma sea más pequeña conducen a sin resultados. Algunas bibliotecas muy buenas en pasado y presente usan más de 4-5 cochecitos.
fuente
Mi regla general es que necesito poder recordar los parámetros el tiempo suficiente para mirar una llamada y decir lo que hace. Entonces, si no puedo mirar el método y luego pasar a una llamada de un método y recordar qué parámetro hace qué, entonces hay demasiados.
Para mí eso equivale a aproximadamente 5, pero no soy tan brillante. Su experiencia puede ser diferente.
Puede crear un objeto con propiedades para mantener los parámetros y pasarlo si excede el límite establecido. Vea el libro de Refactorización de Martin Fowler y el capítulo sobre cómo hacer que las llamadas a métodos sean más simples.
fuente
Depende en gran medida del entorno en el que esté trabajando. Tome, por ejemplo, javascript. En javascript, la mejor manera de pasar parámetros es usar objetos con pares clave / valor, lo que en la práctica significa que solo tiene un parámetro. En otros sistemas, el punto óptimo será a las tres o cuatro.
Al final, todo se reduce al gusto personal.
fuente
Estoy de acuerdo con que 3 está bien, 4 es demasiado como guía. Con más de 3 parámetros, inevitablemente está haciendo más de una tarea. Más de una tarea debe dividirse en métodos separados.
Sin embargo, si mirara el último proyecto en el que he trabajado, las excepciones abundarían y la mayoría de los casos serían difíciles de reducir a 3 parámetros.
fuente
Si tengo 7-10 parámetros en una rutina, considero agruparlos en una nueva clase, pero no si esa clase no sería más que un montón de campos con captadores y establecedores: la nueva clase tiene que hacer algo más que mezclar valores y fuera. De lo contrario, preferiría soportar la larga lista de parámetros.
fuente
Es un hecho conocido que, en promedio, las personas pueden tener 7 +/- 2 cosas en su cabeza a la vez. Me gusta usar ese principio con los parámetros. Suponiendo que todos los programadores sean personas inteligentes superiores a la media, diría que todo 10+ es demasiado.
Por cierto, si los parámetros son similares de alguna manera, los pondría en un vector o lista en lugar de una estructura o clase.
fuente
Basaría mi respuesta en la frecuencia con que se llama la función.
Si se trata de una función init que solo se llama una vez, deje que tome 10 parms o más, a quién le importa.
Si se llama varias veces por fotograma, entonces tiendo a hacer una estructura y simplemente le paso un puntero, ya que eso tiende a ser más rápido (suponiendo que no esté reconstruyendo la estructura también cada vez).
fuente
Según Jeff Bezos, de la fama de Amazon, no se puede alimentar más de dos pizzas :
fuente