Convención de nomenclatura para funciones que tienen efectos secundarios? [cerrado]

9

Escuché a alguien decir que su idioma tiene una convención donde los nombres de las funciones que mutan el estado deben terminar con un signo de exclamación. Estoy tratando de escribir un código más funcional y me gusta la idea de marcar de alguna manera las funciones de acuerdo con su estado de efectos secundarios, es decir, ninguno, efectos secundarios internos, efectos secundarios externos (desconozco la terminología de fp correcta, pero se entiende la idea I esperanza).

Obviamente, es fácil para mí idear mi propio esquema de nombres, pero me preguntaba si tales esquemas / convenciones ya existen antes de irme a casa.

editar: Gracias por todas las respuestas, eso fue exactamente lo que estaba buscando y las encontré todas realmente útiles. Probablemente debería haber mencionado que estoy refactorizando algunos JavaScript antiguos, por lo que, si bien los lenguajes estáticamente escritos pueden imponer una diferencia entre el código con y sin efectos secundarios, tendré que confiar en una convención de nomenclatura autoimpuesta.

edit2: En cuanto a los mods que cierran esto como principalmente basado en opiniones, tengo que estar en desacuerdo. Me preguntaba qué convenciones eran de uso común, si es que existían, ¡esta es, por definición, una cuestión de hecho, no de opinión!

bloque tecnico
fuente
1
Es probable que esto varíe entre idiomas y que esté muy orientado a la opinión.
David Arno
1
Por ejemplo, la convención de Scala es declarar métodos sin paréntesis (muy similares a las propiedades), a menos que tengan efectos secundarios. Pero no puedes usar esto en ningún otro idioma que yo sepa. El signo de exclamación me parece horrible; Hay muchos otros usos para ese símbolo, y creo que se usa para marcar métodos que distraen.
Robert Harvey
2
@RobertHarvey Creo que Scheme es un lenguaje que usa esa convención, y la convención existe porque el operador para mutar el estado de una variable es !(no sería sintácticamente válido mutar el estado de una variable sin ese operador, si la memoria sirve ), por lo que en realidad es una convención bastante sensata en ese idioma .
Servy
3
@Servy Standard Scheme tiene set!para mutar una variable, pero no un !operador independiente . La convención existe porque Lisp tiene un historial de uso de símbolos en identificadores para transmitir significado debido a muy pocas restricciones sobre qué es un identificador válido. La falta de restricciones existe debido al enfoque de Lisp en macros y lenguajes específicos de dominio.
Jack
1
Ruby también usa la !convención (por ejemplo, for downcaseand downcase!), pero indica "peligro" más generalmente que "efectos secundarios".
Andrew

Respuestas:

8

Siga la separación de comando-consulta . Las funciones que devuelven valores no tienen efectos secundarios, las funciones que tienen efectos secundarios no devuelven valores.

También ayuda nombrar funciones que devuelven valores después de lo que devuelven, es decir, un sustantivo o adjetivo. Mientras que las funciones que tienen efectos secundarios deben nombrarse después del efecto que realizan, es decir, un verbo.

Entonces, por ejemplo, myArray.sort()tiene un efecto secundario, ordena la matriz. Por lo tanto, no devuelve nada y lleva el nombre de un verbo. Mientras tanto, myArray.sorted()devuelve una copia ordenada demyArray . Por lo tanto, no tiene ningún efecto secundario y lleva el nombre de lo que devuelve.

Para su información, la idea anterior (sustantivos / adjetivos para funciones puras y verbos para funciones productoras de efectos secundarios) es un estándar en Swift 3.

Nombrar funciones y métodos de acuerdo con sus efectos secundarios

  • Aquellos sin efectos secundarios deben leerse como frases nominales.
  • Aquellos con efectos secundarios deben leer como frases verbales imperativas.

( https://swift.org/documentation/api-design-guidelines/#strive-for-fluent-usage )

Daniel T.
fuente
4

El problema fundamental es que los efectos secundarios no se capturan en el sistema de tipos. El uso de una convención de nomenclatura de funciones es un mal sustituto de la verificación estática. Hay algunas formas de evitar esto.

Haskell usa mónadas para capturar efectos secundarios dentro de un contexto. La bindoperación monádica compone funciones impuras tanto como el operador de composición de funciones normales compone funciones puras. Las leyes de mónada aseguran que este operador actúe de manera análoga a la composición regular.

Otra ruta es la de separar puro a partir impuro mediante la separación de las expresiones de los comandos del todo . Estas son dos categorías sintácticas completamente diferentes que no se pueden mezclar. Las expresiones tienen tipos que nos permiten componer términos. Una expresión, por definición, no puede depender de ningún asignable (no tiene acceso a la tienda ). Los comandos no tienen un tipo en el sentido tradicional y no pueden devolver un valor. Solo pueden interactuar con el programa mutando la tienda.

Tenga en cuenta que los lenguajes "funcionales" convencionalmente seguros de escribir pueden no seguir ninguno de estos paradigmas. Por ejemplo, OCaml y SML no diferencian adecuadamente las funciones puras de las impuras.

Ninguna de estas soluciones es perfecta, y esta sigue siendo un área activa de investigación.

cabeza de jardín
fuente
tenga en cuenta que haskell también tiene inseguroPerformIO
jk.
No estoy muy familiarizado con Haskell. La mayoría de los idiomas seguros proporcionan una manera de subvertir el sistema de tipos como último recurso. Además, su nombre de usuario me dificulta tomar en serio todo lo que diga: D
gardenhead
@jk unsafePerformIO se puede descartar de forma segura en este contexto. Es una escotilla de escape que no debe ser utilizada por el código regular, y viene con advertencias y advertencias significativas . No debe usarse con código de efectos secundarios, de todos modos.
Andres F.
@AndresF. mi punto fue que inseguro * es una convención de nomenclatura para, bueno, cosas inseguras en Haskell, lo que significa prácticamente cosas que por sí mismas producen efectos secundarios, aunque también solo lo usa la implementación en sí, no el código de usuario
jk.
3

Llamar a métodos o funciones parece una idea fantástica porque podría ayudar a eliminar los momentos en que el código introduce un nivel de inseguridad. Joel Spolsky profundiza bastante en esta idea en su artículo Cómo hacer que el código incorrecto parezca incorrecto ( http://www.joelonsoftware.com/articles/Wrong.html ) donde recomienda utilizar una versión menos conocida de la notación húngara para hacer ciertas ideas más transparentes dentro del sistema.

El lenguaje al que se refiere es casi seguro el Esquema (consulte http://download.plt-scheme.org/doc/html/guide/set_.html para ver un ejemplo sencillo). No estoy al tanto de nada global.

Los prefijos de Java métodos de propiedad con gety setpara cumplir parcialmente este propósito, pero no estoy al tanto de ninguna convención común del tipo que mencionas fuera del mundo de Lisp que no están (como señaló @gardenhead) incrustadas en el sistema de tipos.

Creo que, en general, es bastante seguro crear una pauta de estilo para su equipo, particularmente si se trata de algo con mucha concurrencia donde los efectos secundarios son aún más peligrosos de lo habitual.

Para lo que sea que valga, puedo pensar en un par de formas de implementar esto en lenguajes ALGOL-esque. Uno simple podría ser un prefijo, como lo sugirió cuasi Spolsky, digamos s_para operaciones con estado y l_para operaciones sin estado.

Una idea más moderna podría ser poner palabras como prefijos o sufijos. Quizás calculatees una función pura pero mutateCalculationes la impura.

Finalmente, hay un grado en el que mucho de esto debería manejarse separando las preocupaciones; solo la capa que actualiza la base de datos debería ser capaz de actualizar la base de datos, por ejemplo. En ese caso, es bastante obvio que debe preocuparse por los efectos secundarios en las capas con estado.

Miguel
fuente
Gracias por la respuesta. Estoy de acuerdo en que, en un mundo ideal, esto debería manejarse principalmente mediante la separación de las preocupaciones. ¡Mi caso de uso principal para una convención de nomenclatura es separar y refactorizar códigos antiguos que no necesariamente se escribieron teniendo en cuenta la elegancia y las mejores prácticas! (tal vez a veces por mí mismo de vuelta en el día antes de que llegara la religión!)
technicalbloke
Ah, y ese artículo de Joel Spolsky es fantástico, ¡gracias por el enlace!
Technicalbloke