python - ¿Hacer que las operaciones en el lugar devuelvan el objeto es una mala idea?
coding-style mutable (3)
Estoy hablando principalmente de Python aquí, pero supongo que esto probablemente se aplica a la mayoría de los idiomas. Si tengo un objeto mutable, ¿es una mala idea realizar una operación en el lugar que también devuelva el objeto? Parece que la mayoría de los ejemplos simplemente modifican el objeto y devuelven None
. Por ejemplo, list.sort
.
Devolver el objeto modificado del método que lo modificó puede tener algunos beneficios, pero no se recomienda en Python. Devolverse después de una operación de modificación le permitirá realizar el encadenamiento de métodos en el objeto, que es una forma conveniente de ejecutar varios métodos en el mismo objeto, es un lenguaje muy común en la programación orientada a objetos. Y a su vez, el encadenamiento de métodos permite una implementación sencilla de interfaces fluidas . Además, permite que algunos lenguajes de programación funcional se expresen más fácilmente.
Para nombrar algunos ejemplos: en Python, la biblioteca Moka utiliza el encadenamiento de métodos. En Java, la clase StringBuilder
permite múltiples invocaciones append()
en el mismo objeto. En JavaScript, JQuery utiliza el método de encadenamiento extensivo. Smalltalk lleva esta idea al siguiente nivel: de forma predeterminada, todos los métodos se devuelven a self
menos que se especifique lo contrario (por lo tanto, se recomienda el encadenamiento de métodos): contrasta esto con Python, que devuelve None
de forma predeterminada.
El uso de este lenguaje no es común en Python, porque Python cumple con el Principio de Separación de Comando / Consulta , que establece que "cada método debe ser un comando que realice una acción o una consulta que devuelva datos al llamante, pero no ambos".
A fin de cuentas, ya sea una buena o una mala idea devolverse al final es una cuestión de programación cultural y de convenciones, mezclada con gusto personal. Como se mencionó anteriormente, algunos lenguajes de programación fomentan esto (como Smalltalk) mientras que otros lo desalientan (como Python). Cada punto de vista tiene ventajas y desventajas, abierto a discusiones acaloradas. Si eres un Pythonist de by-the-book, mejor abstente de devolverte a ti self
; ten en cuenta que a veces puede ser útil romper esta regla.
Sí, es una mala idea. La razón es que si las operaciones in situ y no in situ tienen una salida aparentemente idéntica, los programadores a menudo mezclarán operaciones in situ y operaciones no in situ ( List.sort()
vs. sorted()
) y que resulta en errores difíciles de detectar.
Las operaciones en el lugar que se devuelven pueden permitirle realizar el "encadenamiento de métodos", sin embargo, esta es una mala práctica porque puede enterrar funciones con efectos secundarios en medio de una cadena por accidente.
Para evitar errores como este, las cadenas de métodos solo deberían tener un método con efectos secundarios, y esa función debería estar al final de la cadena. Las funciones antes de eso en la cadena deben transformar la entrada sin efectos secundarios (por ejemplo, navegar por un árbol, cortar una cadena, etc.). Si las operaciones in situ se devuelven, entonces un programador está obligado a usarlo accidentalmente en lugar de una función alternativa que devuelve una copia y, por lo tanto, no tiene efectos secundarios (de nuevo, List.sort()
vs. sorted()
), lo que puede resultar en Un error que es difícil de depurar.
Esta es la razón por la que las funciones estándar de la biblioteca de Python siempre devuelven una copia o devuelven None
y modifican los objetos en el lugar, pero nunca modifican los objetos en el lugar y también se devuelven a sí mismos. Otras bibliotecas de Python como Django también siguen esta práctica (consulte esta pregunta muy similar sobre Django).
Supongo que depende del caso de uso. No entiendo por qué devolverle un objeto desde una operación en el lugar resultaría perjudicial, aparte de que tal vez no utilice el resultado, pero eso no es realmente un problema si no se muestra muy exigente con el funcionalismo puro. Me gusta el patrón de encadenamiento de llamadas, como los usos de jQuery, así que aprecio que las funciones devuelvan el objeto sobre el que han actuado, en caso de que quiera usarlo más.