Cada vez que tengo una función que se ha vuelto lo suficientemente grande como para justificar la descomposición en funciones más pequeñas, siempre voy a crear las funciones más pequeñas como funciones anidadas del alcance de las funciones más grandes de la siguiente manera:
class Foo { fun bar() : Int { fun a() : Int { // Do a load of stuff return 1 } fun b() : Int { // Do a load of stuff return 1 } return a() + b() } }Hago esto porque proporciona la encapsulación de estas funciones que hasta el momento solo tienen un único sitio de llamada; la del alcance envolvente.
Sin embargo, con frecuencia me piden en el trabajo que refactorice estas funciones a funciones privadas de la clase adjunta de esta manera:
class Foo { fun bar() : Int { return a() + b() } private fun a() : Int { // Do a load of stuff return 1 } private fun b() : Int { // Do a load of stuff return 1 } }Mi argumento en contra de esto es que estas funciones solo tienen 1 sitio de llamada, y al elevarlas a funciones privadas de nivel de clase, estoy enturbiando la clase con métodos que solo se llaman en un lugar.
También se puede hacer un argumento menor adicional de que si las convierto en funciones privadas de la clase, alguien puede entrar más tarde y comenzar a insertar métodos entre esas funciones privadas y la función que las llama, de modo que podría haber cientos de líneas de código entre el sitio de llamada y las funciones mismas, lo que hace que se requiera gimnasia mental para comprender la función de llamada (ya que ahora necesita desplazar la función de llamada fuera de la pantalla para ver las funciones privadas).
Siempre cumplo y los muevo a funciones privadas de la clase después de que mi argumento no convenza al (los) revisor(es).
¿Es válido mi argumento o existen razones legítimas (rendimiento, legibilidad del código) que hacen que mi argumento no sea válido?
Encuentro muy confuso transformar funciones anidadas en funciones privadas dentro de la clase que contiene la función, ya que el único propósito es mejorar la legibilidad de la función principal. La cláusula privada solo protege contra el uso involuntario fuera de la clase, pero dificulta la legibilidad del código fuente de la clase.
En cuanto a la eficiencia no hay problemas, todo lo contrario, pero es irrelevante. En tiempo de compilación, la búsqueda de funciones válidas dentro de la clase es más ágil, ya que las funciones anidadas ni siquiera forman parte del diccionario de datos.
En términos de eficiencia, hay una pequeña sobrecarga al permitir que la función anidada vea parte del contexto de la función principal, que se encuentra en una sección anterior del código. Dado que el uso es solo como un medio para lograr una mejor legibilidad, no veo ningún problema con eso.
Como función privada, el compilador puede acceder a la función en cualquier lugar de la clase, lo que creo que es un defecto de encapsulación, ya que ese no es el propósito de una función anidada y local.