En cualquier definición de clase dada, he visto las definiciones de métodos ordenadas de varias maneras: alfabético, cronológico basado en el uso más común, alfabético agrupado por visibilidad, alfabético con captadores y establecedores agrupados, etc. Cuando empiezo a escribir una nueva clase, Tiendo a escribir todo, luego reordenar cuando termine de escribir toda la clase. En esa nota, tengo tres preguntas:
- ¿Importa el orden?
- ¿Hay un "mejor" pedido?
- Supongo que no, así que ¿cuáles son los pros y los contras de las diferentes estrategias de pedido?
code-quality
Johntron
fuente
fuente
Respuestas:
En algunos lenguajes de programación, el orden es importante porque no puede utilizar las cosas hasta después de que se hayan declarado. Pero salvo eso, para la mayoría de los idiomas no le importa al compilador. Entonces, te queda importando para los humanos.
Mi cita favorita de Martin Fowler es:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
Entonces, diría que el orden de su clase dependerá de lo que facilite la comprensión de los humanos.Personalmente prefiero el tratamiento gradual que Bob Martin da en su
Clean Code
libro. Variables miembro en la parte superior de la clase, luego constructores, luego todos los demás métodos. Y usted ordena que los métodos se relacionen estrechamente con la forma en que se usan dentro de la clase (en lugar de poner arbitrariamente todo público, luego privado y luego protegido). Él lo llama minimizar la "distancia vertical" o algo así (no tengo el libro sobre mí en este momento).Editar:
La idea básica de la "distancia vertical" es que desea evitar que la gente salte todo su código fuente solo para entenderlo. Si las cosas están relacionadas, deberían estar más juntas. Las cosas no relacionadas pueden estar más separadas.
El Capítulo 5 de Clean Code (gran libro, por cierto) entra en muchos detalles sobre cómo el Sr. Martin sugiere ordenar el código. Sugiere que leer el código debería funcionar como leer un artículo de periódico: los detalles de alto nivel son lo primero (en la parte superior) y obtienes más detalles a medida que lees. Él dice: "Si una función llama a otra, deben estar cerca verticalmente, y la persona que llama debe estar por encima de la persona que llama, si es posible". Además, los conceptos relacionados deben estar muy juntos.
Así que aquí hay un ejemplo artificial que es malo en muchos sentidos (diseño pobre de OO; nunca se usa
double
por dinero) pero ilustra la idea:Los métodos están ordenados para que estén cerca de los que los llaman, trabajando desde la parte superior. Si hubiéramos puesto todos los
private
métodos debajo depublic
los, entonces tendrías que hacer más saltos para seguir el flujo del programa.getFirstName
ygetLastName
están relacionados conceptualmente (ygetEmployeeId
probablemente también lo estén), por lo que están muy juntos. Podríamos moverlos todos hacia abajo, pero no nos gustaría vergetFirstName
en la parte superior egetLastName
inferior.Esperemos que esto te de la idea básica. Si está interesado en este tipo de cosas, le recomiendo leer
Clean Code
.fuente
calculateBonus()
venir antesisFullTimeEmployee()
ydidCompleteBonusObjectives()
?isFullTimeEmployee
ydidCompleteBonusObjectives
son utilizados porisEligibleForBonus
lo que debe ser verticalmente cerca de ella. Pero podría moversecalculateBonus
hacia arriba para colocarlo más cerca de donde se llama. Desafortunadamente, como tiene funciones que llaman funciones, eventualmente termina con problemas (como una función compartida llamada por varias otras) donde no hay un pedido perfecto. Luego se deja a su mejor juicio. Recomiendo mantener clases y funciones pequeñas para mitigar esos problemas.Generalmente ordeno mis métodos por relación y orden de uso.
Tome una clase de red, voy a agrupar todos los métodos TCP juntos, luego todos los métodos UDP juntos. El TCP interno tendría el método de configuración como el primero, tal vez envíe un mensaje dado en segundo lugar y cierre el socket tcp como tercero.
Obviamente no todas las clases encajarán en ese patrón, pero ese es mi flujo de trabajo general.
Lo hago así para depurar más que cualquier otra cosa, cuando tengo un problema y quiero saltar al método, no creo cómo se deletrea, pienso de qué es responsable y voy a esa sección.
De esta manera, en particular, tiene sentido que un tercero vea / use su código como está agrupado y seguirá el orden en que se usa, por lo que el código que escribirá con su clase seguirá la misma estructura que la clase.
En cuanto a lo que importa?
para facilitar la lectura, definitivamente.
aparte de eso, en realidad no, solo en los casos en que ciertos idiomas no se pueden llamar al método a menos que se defina arriba donde se llama, etc.
fuente
Idealmente, sus clases son tan pequeñas que no importa. Si solo tiene una docena de métodos, y su editor o IDE admite el plegado, no tiene ningún problema, porque la lista completa de métodos cabe en 12 líneas.
De lo contrario, la distinción de nivel superior debe ser pública versus privada. Primero, enumere los métodos públicos: esto es lo que la gente buscará más, porque definen la forma en que su clase interactúa con el resto de la base de código.
Luego, dentro de cada uno de estos, tiene más sentido agrupar métodos por funcionalidad: constructores y destructores en un bloque, getters / setters en otro, sobrecargas de operadores, métodos estáticos y el resto del grupo. Sin
operator=
embargo, en C ++, me gusta mantenerme cerca de los constructores, porque está estrechamente relacionado con el constructor de copia, y también porque quiero poder detectar rápidamente si todos (o ninguno) de ctor, copy ctor, operator = y dtor predeterminados existe.fuente
tl; dr
Solo si el idioma en el que está trabajando requiere un pedido específico. Aparte de eso, el pedido depende de usted. Elija un sistema que sea consistente y tenga sentido, y trate de mantenerlo lo más posible.
Solo si el idioma en el que trabaja necesita tener una función definida antes en el archivo que donde se llama, como en este ejemplo:
obtendrá un error porque llama
funcB()
antes de usarlo. Creo que este es un problema en PL / SQL y posiblemente también en C, pero puede tener declaraciones de reenvío como:Esta es la única situación en la que puedo pensar, si el orden es "incorrecto", ni siquiera podrá compilar.
De lo contrario, siempre puede volver a ordenarlos como desee. Probablemente incluso podría escribir una herramienta para hacer eso por usted (si no puede encontrar una por ahí).
Si el idioma / entorno no tiene requisitos de pedido, entonces el "mejor" orden es el que mejor funciona para usted . Para mí, me gusta tener todos los captadores / establecedores juntos, generalmente al comienzo de la clase (pero después de los constructores / inicializadores estáticos), y luego los métodos privados, luego protegidos, luego públicos. En cada grupo basado en el alcance generalmente no hay ordenación, aunque los métodos sobrecargados que trato de mantener juntos, en orden de número de parámetros. También trato de mantener juntos los métodos con funcionalidad relacionada, aunque a veces tengo que romper mi orden basada en el alcance para hacerlo; y, a veces, tratar de mantener el orden basado en el alcance divide el grupo por funcionalidad. Y mi IDE me puede dar una vista de esquema alfabético, así que eso también es bueno. ;)
Algunos lenguajes, como C #, tienen la capacidad de agrupar códigos en "regiones" que no tienen ningún efecto en la compilación, pero podrían facilitar la tarea de mantener juntas las funciones relacionadas, y luego ocultarlas / mostrarlas con el IDE. Como señaló MainMa , hay quienes consideran que esta es una mala práctica. He visto buenos y malos ejemplos de regiones que se utilizan de esta manera, así que si vas a hacerlo, ten cuidado.
fuente