¿Existen buenas técnicas o pruebas para nombrar tipos?

23

Una pregunta incómoda y abierta, pero es un problema con el que siempre me encuentro:

El software que es fácil de mantener y trabajar es un software bien diseñado. Intentar hacer un diseño intuitivo significa nombrar sus componentes de tal manera que el próximo desarrollador pueda inferir la función del componente. Es por eso que no nombramos nuestras clases "Tipo1", "Tipo2", etc.

Cuando modela un concepto del mundo real (por ejemplo, cliente), esto generalmente es tan simple como nombrar su tipo después del modelo del mundo real que se está modelando. Pero cuando construye cosas abstractas, que están más orientadas al sistema, es muy fácil quedarse sin nombres que sean fáciles de leer y de digerir.

Empeora (para mí) cuando intento nombrar familias de tipos, con un tipo base o interfaz que describe lo que los componentes tienen que hacer, pero no cómo funcionan. Naturalmente, esto lleva a que cada tipo derivado intente describir el sabor de la implementación (por ejemplo, IDataConnectiony SqlConnectionen .NET Framework), pero ¿cómo expresa algo complicado como "funciona por reflexión y busca un conjunto específico de atributos"?

Luego, cuando finalmente has elegido un nombre para el tipo que crees que describe lo que está tratando de hacer, tu colega pregunta "¿ Qué hace esto DomainSecurityMetadataProviderrealmente ? "

¿Existen buenas técnicas para elegir un nombre bien intencionado para un componente, o cómo construir una familia de componentes sin obtener nombres confusos?

¿Hay alguna prueba simple que pueda aplicar a un nombre para tener una mejor idea de si el nombre es "bueno" y debería ser más intuitivo para los demás?

Paul Turner
fuente
20
hay seis técnicas que han demostrado que funcionan para mí: 1) dedicar mucho tiempo a inventar nombres 2) usar revisiones de código 3) no dudar en cambiar el nombre 4) dedicar mucho tiempo a inventar nombres 5) usar revisiones de código 6) no dudes en cambiar el nombre
mosquito
55
@gnat: Publique su respuesta como respuesta para que podamos votarla.
S.Lott
3
A menudo uso un diccionario de sinónimos cuando hago nuevos desarrollos para ayudarme a encontrar buenos nombres.
Aprendiz del Dr. Wily
3
Intento evitar llamar a cualquier cosa "Administrador". Alan Green y Jeff Atwood argumentan que el término se usa en exceso y es demasiado vago para transmitir significado. Tengo que estar de acuerdo.
Aprendiz del Dr. Wily

Respuestas:

41

Para nombrar, hay seis técnicas que fueron probadas para mí:

  1. dedicar mucho tiempo a inventar nombres
  2. usar revisiones de código
  3. no dudes en renombrar
  4. dedicar mucho tiempo a inventar nombres
  5. usar revisiones de código
  6. no dudes en renombrar

PD. En caso de que su API sea pública, lo anterior se aplica antes de eso, porque, ya sabes,

"Las API públicas, como los diamantes, son para siempre. Tienes una oportunidad de hacerlo bien, así que da lo mejor de ti ..." (Joshua Bloch, Cómo diseñar una buena API y por qué es importante )

mosquito
fuente
1
En caso de que sea una API pública, hay tres técnicas adicionales que puede usar ...
UncleZeiv
1
@UncleZeiv: como ...?
FrustratedWithFormsDesigner
3
@FrustratedWithFormsDesigner: 1. dedica mucho tiempo a inventar nombres 2. usa revisiones de código y 3. no dudes en cambiar el nombre
S.Lott
3
Esta respuesta me ha convencido de que, en general: no, no hay una manera fácil de obtener los nombres correctos. Solo intentar trabajos realmente duros.
Paul Turner
44
7. No dude en rediseñar los tipos o funciones si resulta que es imposible diseñar un nombre propio para ellos. El código bien diseñado siempre se puede nombrar correctamente.
Joren
8

Mi prueba base es si puedes describir la función de la variable usando solo palabras de la variable:

por ejemplo, si DomainSecurityMetadataProvider "proporciona metadatos de seguridad de dominio" o "proporciona metadatos relacionados con la seguridad de dominio", está bien.

Sin embargo, hay matices que varían de persona a persona:

Por ejemplo, para mí, original_team_code es el código para el equipo original, mientras que para otra persona podría ser el código original para el equipo. Mi favorito personal fue "UnsafeLegacyMutex", que no pude evitar leer como "Este es un Letex Mutex que no es seguro", en lugar de "Este es un Mutex para ThreadUnsafe Legacy Code".

Entonces, mi prueba extendida es escribir la variable en un tablero / wiki / chat, y hacer que la gente adivine lo que significa.

deworde
fuente
7

¿Existen buenas técnicas para elegir un nombre bien intencionado para un componente, o cómo construir una familia de componentes sin obtener nombres confusos?

Realmente no.

Un consejo, sin embargo, es evitar la "voz pasiva".

"DomainSecurityMetadataProvider" es pasivo. No hay verbo, todos son sustantivos y sustantivos utilizados como adjetivos.

"ProvideMetadataForDomainSecurity" está más activo. Hay un verbo

La programación orientada a objetos es (realmente) sustantivo-verbo. Sustantivo == objeto. Verbo == método. Entonces un nombre de clase es generalmente muy "sustantivo". Romper este hábito y comenzar a insertar verbos es difícil.

¿Hay alguna prueba simple que pueda aplicar a un nombre para tener una mejor idea de si el nombre es "bueno" y debería ser más intuitivo para los demás?

Sí. Definiste una excelente prueba en tu pregunta. Pregunta a otras personas.

En los viejos tiempos lo llamamos un "tutorial de diseño". Fue un gran negocio sudoroso en una metodología de cascada. Hoy en día, con los métodos ágiles, debería ser una colaboración ordinaria entre el autor y los usuarios de una clase. No (y no debería) tomar mucho tiempo. Discutir el diseño (y los nombres) antes de escribir las pruebas (y el código) reducirá el factor de asombro y puede evitar los WTF.

S.Lott
fuente
12
No estoy seguro de estar de acuerdo con la idea de voz pasiva. Para mí, las clases tienen más sentido como sustantivos.
deworde
77
En términos generales, estoy tratando de mantener mis nombres de tipo en voz pasiva, ya que se adapta al estilo sustantivo-verbo de OOP. Consideraría ProvideMetadataForDomainSecurityser un nombre de tipo pobre. Los nombres de los métodos suelen ser mucho más fáciles de nombrar precisamente porque soy libre de usar verbos. La restricción del idioma es el quid de la cuestión.
Paul Turner
Por mucho que me guste "preguntar a la gente" como una prueba real, debo preguntarles a mis colegas por nombrar al menos dos veces al día. Espero algo que no requiera el tiempo de otras personas.
Paul Turner
2
Las clases tienen sentido como sustantivos. El problema son estas clases complejas con largas frases de adjetivo sustantivo. Las preposiciones también pueden ayudar.
S.Lott
2
La colaboración es el secreto del buen software. La colaboración lleva tiempo. No hay camino real a la buena escritura.
S.Lott
6

Usando un tesauro

Muy a menudo me referiré a un diccionario de sinónimos cuando haga un nuevo desarrollo para encontrar palabras apropiadas para describir mis clases y métodos.

Clases que contienen principalmente lógica de operación

Tiendo a nombrar clases que proporcionan principalmente métodos de operación en una estructura de sustantivo-verbo como "EntityProvider", "EntityLocator", etc.

Estas clases generalmente no contienen mucho estado.

Clases que contienen estado

Las pantallas de la interfaz de usuario y las entidades de datos generalmente tienen estado, por lo que simplemente nombro estas clases con un patrón de nombre o adjetivo-nombre.

Ejemplos: persona, empleado, empleado actual, antiguo empleado

Clases de utilidad

Las clases que solo contienen métodos estáticos generalmente se consideran clases de "utilidad", por lo que siempre las llamo con el sufijo "Utilidad".

Ejemplos: NetworkUtilities, FileUtilities

Pruebas

No tengo buenas pruebas para decidir si algo está mal nombrado, pero sugeriría intentar usar un solo nombre y / o un solo verbo en el nombre, luego pensar si ese nombre / verbo describe con precisión lo que usted ' renombrando.

Si cree que hay más en la clase / método que no está capturado por el nombre, entonces esa clase / método podría necesitar una refactorización.

Alan Green y Jeff Attwood han escrito sobre los males de nombrar clases con el sufijo "Manager". Argumentan que el término "Gerente" se usa en exceso y es demasiado vago para transmitir algo significativo. Tengo que estar de acuerdo.

El artículo de Jeff también proporciona una lista de pautas sugeridas del Código completo de Steve McConnell.

variables

Recientemente he estado experimentando con nombres de variables / parámetros descriptivos más largos que incorporan preposiciones, como "Of", "By", "For", etc. A continuación se muestran algunos ejemplos:

string firstNameOfEmployee;

string lastNameOfEmployee;

// here I nimbly avoid worrying about whether to call it "Id" or "ID" :)
int idOfEmployee;

decimal amountForDeposit;

Account accountForDeposit;

Me parece que esto funciona bien con la función intellisense de Visual Studio que hace que sea fácil escribir estos nombres largos. También encuentro que hay menos duplicación de prefijos de nombres de variables (por ejemplo, personID, personFirstName, personLastName vs.idOfPerson, firstNameOfPerson, lastNameOfPerson), proporcionando un mejor "hash" que hace que intellisense sea aún más útil.

Aprendiz del Dr. Wily
fuente
1
Voy a aclarar el punto sobre los nombres largos de variables, de nuevo, Visual Studio (si lo está usando) hace que esto sea obvio. Es mucho menos dañino tener nombres de variables largos que sean explícitos que los nombres de variables cortos en los que hay que "pensar" o investigar qué significa realmente el nombre. También piense en el contexto. Prefiero ver "peopleToDelete" que "listOfPeople". Nuevamente, Visual Studio le dice el tipo de variable, no es necesario incluirla.
John Bubriski
Tampoco me gusta la elaborada notación húngara que ha agregado a los nombres de variables. No debería tener que preocuparme si una colección de ID de personas es una List, matriz IEnumerableo ConcurrentQueue. Es un conjunto de ID que necesito enumerar, y el detalle de implementación de cómo se almacenan es un equipaje mental innecesario. Aunque generalmente estoy de acuerdo en que si un nombre más largo es considerablemente más descriptivo, debería preferirse a un nombre más corto y menos claro.
Allon Guralnek
@Allon - Es curioso, estaba a punto de revisar mi respuesta en función del comentario de SkippyFire. De hecho estoy de acuerdo contigo; mi ejemplo huele a notación húngara. Mi única defensa es que es fácil leer el código y comprender los tipos de datos involucrados sin un IDE disponible, como si estuviera leyendo a través de un control de fuente diff. Sin embargo, eso no es excusa. :) Voy a revisar mi ejemplo para que esté en la línea de firstNameOfEmployee, lastNameOfEmployee, etc.
Aprendiz del Dr. Wily
2

Luego, cuando finalmente ha elegido un nombre para el tipo que cree que describe lo que está tratando de hacer, su colega pregunta "¿Qué hace realmente este DomainSecurityMetadataProvider?"

¿Qué tipo de nombre esperas para una clase compleja y específica de dominio? Esto es casi tan bueno como va a ser sin hacer que el nombre de su clase sea una oración (lo que hará que todos piensen que ha dado demasiada responsabilidad a una sola clase)

Consideraría eliminar al proveedor del nombre. Si menciona específicamente los metadatos, todos ya saben que está utilizando la reflexión. Podría hacerlo una palabra más concisa (o posiblemente cambiar a otra palabra, es más un consumidor que un proveedor por lo que ha escrito)

brian
fuente
Los metadatos en cuestión no se derivan de la reflexión (pero describen cómo tratar los tipos). El tipo implementa una ISecurityMetadataProviderinterfaz, que existe un punto inyectable en la infraestructura de seguridad, para proporcionar información al subsistema. Nombrar es difícil.
Paul Turner
Considero DomainSecurityMetadataProviderser un proveedor de DomainSecurityMetadataobjetos, donde DomainSecurityMetadataestán los metadatos en sí. Nombre claro y entendible. ¡Ni siquiera necesito saber qué DomainSecurityMetadataes! Es solo un objeto que proporciona este proveedor. Solo eliminar un Providersufijo no mejora la legibilidad, sino todo lo contrario: reduzca. Sin este sufijo, pensaría que son solo algunos metadatos (objeto contenedor para algunos metadatos), pero no un objeto para obtener metadatos de (un proveedor).
Ruslan Stelmachenko
0

Usa metáforas para describir partes del sistema. No solo te hará descubrir nuevas analogías, sino que te ayudará a nombrar más fácilmente.

(Soy consciente de que este no es un ejemplo sólido, pero de todos modos) Por ejemplo, puede llamar a una variable o un tipo como mailbox, que sirve como una cola para los mensajes recibidos para una clase.

nimcap
fuente
-1

Una cosa en la que sería muy firme es que NUNCA se debe permitir que sean incorrectos. El mejor ejemplo, durante algunas refactorizaciones, cambió mucho código y algunas variables comenzaron a referirse a algo diferente a lo que sugerían sus nombres.

Muy pronto, un programador estaba pasando años y utilizando algunas llamadas de bases de datos muy costosas tratando de obtener ciertos datos que ya se habían extraído y almacenado. Cambié el nombre de todo y de repente pudimos eliminar un montón de lógica demasiado complicada y con errores.

deworde
fuente
1
debe eliminar esta respuesta y editarla en su respuesta de origen
Ryathal
Creo que esta es una respuesta diferente a mi otra respuesta.
deworde
-1

Con suerte, los casos en los que hay que pensar tanto sobre los nombres son raros. Cuando surjan esos casos, solo escriba un párrafo que explique lo que hace la clase. Contrariamente a los comentarios en función o comentarios a nivel de función, el propósito principal de una clase rara vez cambia, por lo que el riesgo de que los comentarios se desactualicen es relativamente pequeño. Así que tiene el lujo de escribir un par de párrafos o incluso dibujar ASCII para explicar lo que hace la clase.

kizzx2
fuente