¿Cuál es el mejor enfoque para nombrar clases?

92

Es muy difícil encontrar nombres buenos y precisos para las clases. Si se hace correctamente, hace que el código sea más autodocumentado y proporciona un vocabulario para razonar sobre el código a un nivel más alto de abstracción.

Las clases que implementan un patrón de diseño en particular pueden recibir un nombre basado en el nombre del patrón bien conocido (por ejemplo, FooFactory, FooFacade), y las clases que modelan directamente conceptos de dominio pueden tomar sus nombres del dominio del problema, pero ¿qué pasa con otras clases? ¿Hay algo parecido a un tesauro de programador al que pueda recurrir cuando me falta inspiración y quiero evitar el uso de nombres de clases genéricos (como FooHandler, FooProcessor, FooUtils y FooManager)?

Enrique
fuente
6
esta es una excelente pregunta! Cerrarlo no está justificado en mi humilde opinión, mejor sería migrar el sitio de los programadores.
Timofey
1
Estoy de acuerdo, debería ser reabierto o movido
ftl
He visto muchas de estas excelentes preguntas "cerradas por casperOne". ¿Quizás podría servir como delecionista en Wikipedia?
Perlator

Respuestas:

59

Citaré algunos pasajes de Implementation Patterns de Kent Beck:

Nombre de superclase simple

"[...] Los nombres deben ser cortos y contundentes. Sin embargo, para que los nombres sean precisos a veces parece requerir varias palabras. Una forma de salir de este dilema es elegir una metáfora fuerte para el cálculo. Con una metáfora en mente, incluso las palabras sueltas traen consigo una rica red de asociaciones, conexiones e implicaciones. Por ejemplo, en el marco de dibujo de HotDraw, mi primer nombre para un objeto en un dibujo era DrawingObject . Ward Cunningham vino con la metáfora de la tipografía: un dibujo es como una página impresa y distribuida. Los elementos gráficos en una página son figuras, por lo que la clase se convirtió en Figura . En el contexto de la metáfora, Figura es simultáneamente más corta, más rica y más precisa que DrawingObject ".

Nombre de subclase calificado

"Los nombres de las subclases tienen dos funciones. Necesitan comunicar a qué clase son y en qué se diferencian. [...] A diferencia de los nombres en las raíces de las jerarquías, los nombres de las subclases no se usan con tanta frecuencia en las conversaciones, para que sean expresivos a costa de ser concisos. [...]

Dé a las subclases que sirven como raíces de jerarquías sus propios nombres simples. Por ejemplo, HotDraw tiene un identificador de clase que presenta operaciones de edición de figuras cuando se selecciona una figura. Se llama, simplemente, Mango a pesar de alargar Figura . Hay toda una familia de identificadores y lo más apropiado es que tengan nombres como StretchyHandle y TransparencyHandle . Dado que Handle es la raíz de su propia jerarquía, merece un nombre de superclase simple más que un nombre de subclase calificado.

Otra arruga en la denominación de subclases son las jerarquías de múltiples niveles. [...] En lugar de anteponer ciegamente los modificadores a la superclase inmediata, piense en el nombre desde la perspectiva del lector. ¿Qué clase necesita para saber cómo es esta clase? Utilice esa superclase como base para el nombre de la subclase ".

Interfaz

Dos estilos de nombrar interfaces dependen de cómo piense en las interfaces. Las interfaces como clases sin implementaciones deben nombrarse como si fueran clases ( Nombre de superclase simple , Nombre de subclase calificado ). Un problema con este estilo de denominación es que los buenos nombres se agotan antes de llegar a las clases de nombres. Una interfaz llamada Archivo necesita una clase de implementación llamada algo como ActualFile , ConcreteFile o (¡puaj!) FileImpl(tanto un sufijo como una abreviatura). En general, comunicar si se trata de un objeto concreto o abstracto es importante, si el objeto abstracto se implementa como una interfaz o una superclase es menos importante. Aplazar la distinción entre interfaces y superclases está bien respaldado por este estilo de denominación, lo que te deja libre para cambiar de opinión más tarde si eso se vuelve necesario.

A veces, nombrar clases concretas simplemente es más importante para la comunicación que ocultar el uso de interfaces. En este caso, anteponga los nombres de interfaz con "I". Si la interfaz se llama IFile , la clase se puede llamar simplemente Archivo .

¡Para una discusión más detallada, compre el libro! ¡Vale la pena! :)

Marcio Aguiar
fuente
1
"A veces, nombrar clases concretas simplemente es más importante para la comunicación que ocultar el uso de interfaces. En este caso, anteponga los nombres de las interfaces con una" I ". Si la interfaz se llama IFile, la clase se puede llamar simplemente Archivo". Es muy divertido, porque en el libro Clean Code de Robert C. Martin, descubrí que preferiríamos nombrar implementaciones como FileImpl, en lugar de nombrar la interfaz como IFile, porque no queremos que el cliente sepa que les estamos sirviendo un interfaz. Y en el libro ^ hay citas del libro al que te refieres :)
Cristian Ciobotea
38

Opte siempre por MyClassA, MyClassB: permite una buena ordenación alfa ...

¡Estoy bromenando!

Esta es una buena pregunta y algo que experimenté no hace mucho tiempo. Estaba reorganizando mi base de código en el trabajo y tenía problemas de dónde poner qué y cómo llamarlo ...

los verdadero problema?

Tenía clases haciendo demasiado. Si intenta adherirse al principio de responsabilidad única , todo se combinará mucho mejor. En lugar de una clase PrintHandler monolítica , puede dividirla en PageHandler , PageFormatter (y así sucesivamente) y luego tener una clase de impresora maestra que lo trae todo junto.

En mi reorganización, me tomó tiempo, pero terminé agrupando una gran cantidad de código duplicado, obtuve mi base de código mucho más lógica y aprendí muchísimo cuando se trata de pensar antes de lanzar un método adicional en una clase: D

Sin embargo, no recomendaría poner cosas como nombres de patrones en el nombre de la clase. La interfaz de clases debería hacer eso obvio (como ocultar el constructor de un singleton). No hay nada de malo con el nombre genérico, si la clase tiene un propósito genérico.

¡Buena suerte!

Rob Cooper
fuente
Acepte no poner nombres de patrones en el nombre de la clase. ¿Qué pasa si el patrón cambia más adelante cuando cambia la implementación?
thegreendroid
2
Prefiero poner un nombre de patrón en un nombre. ¿Por qué? Porque si tengo que mirar los detalles de implementación (como un constructor privado) para descubrir que es un singleton, eso me está frenando como lector y, dependiendo de mi nivel de habilidad, es posible que no me dé cuenta de que en realidad es una parte de la clase. del patrón general. El constructor individual y privado es un ejemplo cuestionable, pero para patrones más complicados (visitante, adaptador, etc.) se está volviendo bastante complicado. Si el patrón cambia, los chaces son que esas clases ya no existirán ...
dragan.stepanovic
28

La excelente charla de Josh Bloch sobre un buen diseño de API tiene algunos buenos consejos:

  • Las clases deben hacer una cosa y hacerlo bien.
  • Si una clase es difícil de nombrar o explicar, probablemente no esté siguiendo los consejos del punto anterior.
  • Un nombre de clase debe comunicar instantáneamente qué es la clase.
  • Los buenos nombres generan buenos diseños.

Si su problema es cómo nombrar las clases internas expuestas, tal vez debería consolidarlas en una clase más grande.

Si su problema es nombrar una clase que está haciendo muchas cosas diferentes, debería considerar dividirla en varias clases.

Si ese es un buen consejo para una API pública, entonces no puede hacer daño a ninguna otra clase.

Josh Segall
fuente
1
enlace de video en youtube youtube.com/watch?v=aAb7hSCtvGw
Andrew Harry
12

Si le pegan con un nombre, a veces sólo lo que le da ningún nombre medio sensible con el compromiso de revisar más tarde es una buena estrategia.

No consigas nombrar parálisis. Sí, los nombres son muy importantes, pero no lo suficiente como para perder una gran cantidad de tiempo. Si no puede pensar en un buen nombre en 10 minutos, siga adelante.

Simon Johnson
fuente
9

Si no me viene a la mente un buen nombre, probablemente me preguntaría si hay un problema más profundo: ¿la clase cumple un buen propósito? Si es así, nombrarlo debería ser bastante sencillo.

Luke Halliwell
fuente
3

Si su "FooProcessor" realmente procesa foos, entonces no sea reacio a darle ese nombre solo porque ya tiene un BarProcessor, BazProcessor, etc. En caso de duda, lo obvio es lo mejor. Es posible que los otros desarrolladores que tienen que leer su código no estén usando el mismo tesauro que usted.

Dicho esto, más especificidad no estaría de más para este ejemplo en particular. "Proceso" es una palabra bastante amplia. ¿Es realmente un "FooUpdateProcessor" (que podría convertirse en "FooUpdater"), por ejemplo? No tiene que ser demasiado "creativo" con el nombre, pero si escribió el código, probablemente tenga una idea bastante clara de lo que hace y lo que no hace.

Finalmente, recuerde que el nombre de la clase no es todo lo que usted y los lectores de su código tienen que seguir; por lo general, también hay espacios de nombres en juego. A menudo, estos pueden dar a los lectores el contexto suficiente para ver claramente para qué es realmente su clase, incluso si su nombre es bastante genérico.

McKenzieG1
fuente