Sobre el infravalorado y aleatorio uso del paso de parámetros en las funciones.

Manu Pijierro
5 min readNov 19, 2017

--

Una de las principales características del código limpio viene dada por el número de parámetros que reciben las funciones que lo describen. Al intentar hacer que nuestras clases sean fáciles de entender, utilizar y reutilizar hay que dedicar atención al número de argumentos que tienen los métodos o funciones que definen su comportamiento. A más parámetros escribiremos métodos más complejos ya que tendrán una configuración más complicada , por otro lado, tenemos el caso contrario en el que cero parámetros sería siempre lo deseable.

Dicho esto, ¿conocemos los tipos de parámetros que existen, cómo y cuándo usarlos? ¿pensamos en el significado y utilidad de cada uno de los parámetros que reciben nuestras funciones? ¿son todos necesarios o nos sobra alguno? ¿cuál es el número correcto de parámetros que recibe una función? veamos si llegamos a alguna conclusión.

Operandos y opciones

Los argumentos o parámetros de una rutina pueden ser de dos tipos: operandos y opciones.

  • Un operando representa un artefacto sobre el cual va a actuar la rutina.
  • Una opción representa un modo de funcionamiento.

Un parámetro es una opción si cuando el cliente que llama a la rutina no le proporciona un valor concreto dicha rutina es capaz de hallar un valor por defecto razonable. Esto implica que si hubiera información tratada como opciones, lo mejor sería que estas estuvieran en la propia clase, inicializadas con un valor válido y coherente. Para configurar o dar un valor distinto a las opciones que modifican el comportamiento de una clase es conveniente tener métodos específicos (setters) para establecer los valores apropiados.

De modo general, si tenemos un método que utiliza parámetros catalogados como opciones es contraproducente porque lo más probable es que se esté violando el Principio de Responsabilidad Única. Hay que tener en cuenta que un parámetro como opción implica que una función puede estar haciendo al menos dos cosas, una cuando se cumple el valor de la opción y otra cuando no se cumple. Este ‘una cosa u otra’ indicarían que tenemos dos procesos distintos. Implementar dos procesos distintos en una misma función no es correcto ya que la función solo debería hacer una cosa y hacerla bien. La solución a este problema suele estar en implementar ambos procesos por separado y después, el cliente que los quiera utilizar, sea el que decida entre uno u otro en función de su necesidad. Es decir, la decisión sobre que se hace o que no se hace se toma antes de llamar a la función, no dentro de ella a partir del valor de una parámetro que indica una opción.

El Principio de operandos (Bertrand MeyerConstrucción de Software Orientado a Objetos), nos dice que, de modo general:

Los argumentos de una rutina deberían incluir solamente operandos (y no opciones).

Este principio proporciona varios beneficios:

  • Solo se especifica lo que difiere de los resultados.
  • Es más sencillo conocer el funcionamiento de una clase porque solo es configurable lo esencial de la misma, es decir, los parámetros que recibe.
  • Mantiene la extensibilidad y el principio abierto-cerrado ya que es posible añadir más opciones sin modificar la interfaz de la rutina que especifica los operandos.

Excepciones del Principio de Operandos

Aunque este principio es de aplicabilidad universal, hay algún caso en el que conviene relajar su uso como, por ejemplo, en rutinas de creación de objetos (factory) en las que podremos facilitar la tarea del cliente al ofrecer diferentes formas para dar a los objetos valores por defecto distintos de los que hubiera por defecto.

Número de argumentos

Según el Clean Code de Robert C. Martin,

“el número ideal de argumentos para una función es cero. Después uno (monádico) y dos (diádico). Siempre que sea posible evite la presencia de tres argumentos (triádico). Más de cuatro argumentos (polidiádico) requiere una justificación especial y no es muy habitual”.

Hay que tener en cuenta que los argumentos o parámetros suelen estar a un nivel de abstracción distinto al del nombre de la función. Si el nombre de esta está bien definido y con un ‘naming’ correcto será fácil de leer e interpretar mientras que los parámetros, además del nombre, llevan un tipo especificado que muchas veces suelen complicar la interpretación ya que no lo conocemos. A más parámetros, aumentan la carga cognitiva que necesitamos para su comprensión.

Además, los parámetros complican el testing. Hay que tener en cuenta que una buena cobertura de tests debería comprobar el funcionamiento de la rutina teniendo en cuenta los diferentes valores de cada uno de los parámetros y las diferentes combinatoria entre estos. A más parámetros, más complicado de probar.

Es evidente, pero hay que utilizar todos los argumentos de una función. Yo mismo más de una vez me he encontrado con código que define una función con parámetros que luego no utiliza. Deberíamos ser cuidadosos en no caer en este tipo de prácticas oscuras de la programación que no tienen nada de bueno. Si un parámetro no se usa, elimínalo.

Cuando una rutina recibe varios parámetros es muy probable que estos puedan representar un concepto y agruparse en una clase que los defina de manera apropiada. Esto facilita mucho la legibilidad del código y su uso. Por ejemplo, hay un caso bastante extendido que suele ser el paso de coordenadas geográficas. En vez de usar dos parámetros para especificar la latitud y la longitud, lo correcto es agruparla en una clase Coordinate y que sea de este tipo el parámetro que pasemos. Ejemplo:

Código regulero:

public function centerMap (string $latitude, string $longitude)

Mejor así:

public function centerMap (Coordinate $position){
//...
}

Más sobre argumentos

  • Si hay varias rutinas que usan parámetros, deberíamos ponerlos de forma similar en un orden consistente, de esta forma facilitaremos la interpretación del código y la relación entre diferentes partes del mismo.
  • Relacionado con el punto anterior, es una buena práctica poner los parámetros en el siguiente orden: entrada-modificación-salida. Este orden, además, puede implicar una secuencia en el orden de uso de los mismos. No obstante, estas son indicaciones que deberían acordarse con el equipo de trabajo en base a las convenciones que se utilicen.
  • Sobre las convenciones, si el equipo de desarrollo cree que es necesario diferenciar de modo más concreto los parámetros de entrada, modificación y salida, puede crear estándares de codificación que establezca sufijos o prefijos para los mismos.
  • Los argumentos de salida por lo general suelen complicar la comprensión de lo que hace una rutina ya que estamos más acostumbrados a interpretar información de entrada. En el caso de tener que devolver información lo que se recomienda retornar un valor, bien un tipo primitivo o un objeto.
  • Personalmente, prefiero un paso de argumentos tipado. PHP, lenguaje en el que programo, al ser un lenguaje débilmente tipado no es estrictamente necesario especificar el tipo de los parámetros. Esto último aparte de hacer el código más complicado de seguir y entender creo que incrementa las probabilidades de generar errores. En internet hay bastante teoría sobre tipar o no tipar los argumentos de una función. Basta hacer una búsqueda del tipo ‘type hinting vs duck typing’ para ver una pequeña muestra.

Esto es todo.

Chimpún

Bibliografía

Bertrand Meyer. Object-Oriented Software Construction (Book/CD-ROM) 2nd Edition

Steve McConnel. Code Complete 2

Robert C. Martin — Clean Code

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response