2009-06-11 7 views
19

Por lo tanto, a menudo tengo problemas para describir una función en un nombre breve. Por lo general, no es un problema en las funciones que se hacen para su reutilización, pero a menudo un gran proceso debe dividirse en subfunciones. A menudo, estos obtienen nombres extraños, como connectionsToAccessLines o handleWallVisionSplit o algo así. Y aunque estas funciones solo hacen una cosa, es muy difícil encontrar un buen nombre para ellas porque realmente son solo una parte de un algoritmo más grande.Problemas para encontrar buenos nombres para las funciones

¿Qué haces en esta situación? Es muy frustrante

+5

Esto debería ser una wiki. – gnovice

Respuesta

17

A veces, si no se puede llegar a un buen nombre de la función es una indicación de que la función no tiene un buen , foco nítido y necesita ser refactorizado. Si se trata de un método de clase, quizás la clase también necesite una refacturación.

Pero vale la pena el problema para encontrar los mejores nombres posibles, ya que hace que su código sea mucho más comprensible y utilizable.

Actualización: Muchos autores de ingeniería de software han hablado sobre la importancia de nombrar. Henry F. Ledgard's Programming Proverbs (1975) y Brian Kernighan y P.J. Plaugher's Elements of Programming Style (1978) fueron los primeros y todavía vale la pena leerlos. El maravilloso Code Complete de Steve McConnell (2da edición, 2005) es un ejemplo más reciente, dedicando un capítulo entero al tema.

Elementos del estilo de programación se basaban en parte en Elements of Style Strunk and White, que en realidad tiene una relevancia sorprendente. Su énfasis en hacer que la prosa sea clara y extremadamente concisa se aplica a nuestros escritos técnicos y comentarios (y nombres), pero siempre lo he visto de forma análoga a lo que hacemos cuando refactorizamos y mejoramos nuestro código.

+1

Sí. Fuertemente de acuerdo. – PeterAllenWebb

+0

Excepto que a veces no se puede dividir una función en partes debido a la eficiencia. Por ejemplo, iterar a través de un conjunto y buscar simultáneamente esos valores en otro, y cuando los encuentre, eliminarlos, pero primero colóquelos en un tercer contenedor que se devuelve, también conocido como MoveSetUnionToNewSet. Aumentaría enormemente la complejidad algorítmica para dividir esta función. – rlbond

+0

Muy cierto, y Strunk y White no habrían sugerido eliminar las palabras necesarias para el significado. "MoveSetUnionToNewSet" ciertamente no es demasiado largo en mi libro, aunque quizás más claro sería "Set ExtractSetUnion (Set a, Set b)". –

13

Prefiero los nombres de métodos ridículamente largos en el contexto de un algoritmo más grande porque reduce la necesidad de observar la implementación de la función.

Un nombre como ReadPropertiesFromFileThenWriteToSession es mejor que ReadProps.

+8

Sí, los nombres largos son definitivamente preferibles a nombres cortos y ambiguos como Doaction (int id); Pero tampoco exageres. Si no puede describir en una palabra o en una frase corta lo que está haciendo el método, divídalo en más métodos :) –

+1

Diría que un problema con eso es cuando quiere que un método eventualmente llame a más métodos. Method1 llama a DoXAndYIfZ (que encapsula una variable/verificación de estado), que llama a X e Y por separado. En casos como este, cuando no desea la lógica de bifurcación en el método de nivel superior, no puede simplemente "agregar más métodos" a ella. Entonces tu nombre se hace más largo. –

+2

... aunque, en general, estaría de acuerdo con usted solo con "cuando tenga problemas para encontrar un nombre corto, simplemente haga un nombre largo" como una advertencia. :) –

0

¡Sus funciones realmente deberían indicar qué es lo que hacen! Pero no de una manera excesivamente detallada. Esto es algo que dominará con el tiempo, se necesita un poco de práctica para obtener una función correcta.

Lea rápidamente this para ver algunas cosas que escribí sobre este tipo de cosas hace un tiempo :) Asegúrese de seguir el other article que me inspiró a escribirlo y ver los comentarios.

0

Una sugerencia de refactorear libros es mirar el algoritmo largo y en cada lugar que sienta que hay un bloque en el código que puede describir con un comentario de una línea refactorizar este bloque en una función privada y usar lo que está en la línea única como nombre para la función. Eso podría ser muy largo, pero si te ayuda a leer el algoritmo de una manera rápida, está perfectamente bien. El código completo menciona un buen rango de entre 9 y 15 caracteres.

Y no se preocupe si se trata de una función de ayuda privado refactorización el nombre más adelante no es un problema

2

Cada vez que me golpeó una pared de ladrillos tratando de nombrar a una función o procedimiento, vuelvo y pensar mucho acerca de lo Creo que es para. A menudo, si un nombre no se sugiere fácilmente a sí mismo, es una pista de que no he pensado en lo que realmente se supone que debe hacer la función o el procedimiento.

Tiene un proceso que necesita hacer A, B, C, ..., X, Y y Z; no puede nombrar el procedimiento doABCDEFGHIJKLMNOPQRSTUVWXYZ. Tienes que encontrar alguna agrupación lógica de nivel medio (quizás varias capas de agrupaciones) que divide el proceso.

A veces, encontrar el nombre correcto requiere mover el código para que esté en fragmentos más lógicos.

Otra ayuda es encapsular las funciones/procedimientos (dependiendo de las características del idioma que esté utilizando) para que el nombre sea más corto (ya que su nombre puede interpretarse dentro del contexto de su contenedor). Por ejemplo, el procedimiento "abrir archivo" normalmente debería abrir un archivo para leer; pero en el contexto de una clase "UserPrefsFile", podría tener un significado más específico.

9

El difunto, gran Phil Karlton bromeó de manera famosa: Solo hay dos problemas difíciles en la ciencia de la computación: nombrar cosas y la invalidación de la memoria caché. Mi experiencia me lleva a creer que hay mucha verdad en eso.

Nombrar las cosas bien es tanto un arte como una ciencia, y como tal, no existen reglas estrictas.Dicho esto, a veces leo Ottinger's rules for Variable and Class Naming, que tiene algunas buenas heurísticas para tener en cuenta. Uno de mis favoritos es usar frases nominales, como - person.getName(), o bitTorrentClient.findPeersFromTracker(). En ambos casos, la intención de la línea de código es similar a una frase en inglés.

+0

+1 - el enlace de Ottinger es bueno. –

+0

"obtener nombre" y "buscar pares del rastreador" son frases verbales :) –

+0

http://agileinaflash.blogspot.com/2009/02/meaningful-names.html es la forma abreviada de mis reglas de denominación. La forma larga es el capítulo 2 del Código limpio. –

6

Algunas veces puede reducir la longitud de un nombre de una función simplemente reformulando el nombre. En lugar de:

void RetrievePropertiesFromRemoteStore() 

que puede usar:

void RetrieveRemoteProperties() 

en lugar de:

bool CheckToSeeIfUserIsAuthorized() 

Uso:

bool IsUserAuthorized() 

Otra manera de reducirlo es volver a pensar lo que el la función lo hace. En vez de una función como esta:

void GetUserProfileAndSetUpSession() 

usted podría tener:

void GetUserProfile() 
void SetupSession() 
+5

en el caso de IsUserAuthorized, si es un método en una clase, entonces user.IsAuthorized() o service.IsAuthorized (user) es aún mejor. – plinth

1

Heh. Me llamó la atención al leer el título de la pregunta que el acto de programación podría describirse como "problemas para encontrar buenos nombres para las funciones".

-3

Puede utilizar la numeración y sufijos "_ *" para evitar demasiados nombres en su código:

void DoX() 
void DoX_Decode1()   <-- this name shows that this function is only used by DoX() 
void DoX_Decode2() 
void DoX_Decode3() 
void DoX_Find1() 
void DoX_Find2() 
void DoX_Find3() 

También puede agrupar funcionalidad similar con prefijos:

void tcpip_ShowConnectDialog() 
void tcpip_AcceptConnections() 
void logging_WriteToFile() 
void logging_UpdateLogWindow() 

esta manera se obtiene nombres de función únicos (ayuda a buscar y buscar y reemplazar) y aún los mantiene relativamente cortos. También evita la molestia de extraerlos para separar la clase y separar el archivo de código. Simplemente mantenga los prefijos cortos para que pueda ignorar fácilmente y ver más allá de ellos.

+1

DoX_Decode2 no significa absolutamente nada para mí. Y, tal vez esté utilizando un idioma sin OO, pero DoX.find() y DoX.Decode() es mucho mejor IMO. Lo digo porque hablabas de separar la clase ... así que supongo que es OO. Por último, uno no debería evitar la refactorización debido a la "molestia de extraerlos" ... con un buen IDE (tos * tos * eclipse tos *), el cambio de nombre y método de extracción es realmente algo agradable de hacer. :) – user35978

+0

Sí, estoy muy pasado de moda de esa manera. Odio tener una clase y un archivo separados para cada pequeña cosa. Para mí es prácticamente imposible hacer que tu código sea más corto (refactorizando) cuando todo lo que ves son abstracciones de alto nivel, que todos hacen "sence" y "pelea" por su existencia (perdón por las analogías tan exageradas). También creo más en listas, que en jerarquías o árboles. Por ejemplo, preferiría usar múltiples documentos de Excel con tablas bidimensionales, ese documento xml con estructura de árbol jerárquica (si tiene sentido para usted). Es por eso que odio las jerarquías de clase OO. – AareP

1

Cuando se agoten los nombres razonables, simplemente use letras del alfabeto. Una vez que te quedas sin ellos, elige palabras aleatorias del diccionario.De esta forma, nunca podrán despedirte, porque eres el único que entiende el código.

+0

¡Hah! Consulte http://stackoverflow.com/questions/961942/what-is-the-worst-programming-language-you-ever-worked-with para ver ejemplos de varios idiomas donde casi solo tenía letras del alfabeto. Un BASIC que vi una vez solo permitía nombres como A y B1 para enteros, y $ D y $ R2 para cadenas. Horrible. –

0

Al utilizar un enfoque orientado a objetos, ayuda a reducir este problema. connectionsToAccessLines -> connexion.connect (System.getAccessLines());

handleWallVisionSplit -> esta, no estoy muy seguro de lo que hace: D Pero, diría algo como: wall.handleVision (Wall.split); o lo que sea, creo que entiendes lo que quiero decir.

Además, a veces, cuando es realmente difícil nombrar una función demasiado específica, puede deberse a que el código no es suficiente de alto nivel. Por ejemplo: readSecondWordOfLine (a_line) -> line.split() [1].

O, ordenar (sortWithSecondWordOfLine()) podría ser, ordenar (línea => división (línea) [1]) .. Sé que no siempre es posible tan limpio como eso en todos los idiomas, pero entiendes mi punto. Con C++, por ejemplo, puede usar los compuestos bind y stl para construir una expresión de línea en vez de crear un nuevo método.

Por lo tanto, podría resumirlo diciendo que si tiene un método demasiado técnico, que generalmente es muy corto porque de lo contrario el nombre sería fácil de encontrar abstrayendo las funcionalidades, es bueno crear una nueva función/clase más generalizado con un nombre abstracto y utilícelo directamente en la primera función.

Cuestiones relacionadas