Soy bastante nuevo en ingeniería de software y, como ejercicio de aprendizaje, escribí un juego de ajedrez. Mi amigo lo miró y señaló que mi código parecía
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
mientras él insistía en que debería ser
for (int i = 0; i < CHESS_CONST; i++){
for (int j = 0; j < CHESS_CONST; j++){
con un mejor nombre de símbolo que no me puedo molestar en pensar en este momento.
Ahora, por supuesto, sé que generalmente evito usar números mágicos, pero siento que desde
- este número nunca cambiará;
- el nombre no podría ser tan descriptivo de todos modos ya que el número se usa en muchos lugares en todo el código; y
- cualquiera que esté pasando por el código fuente de un programa de ajedrez debe saber lo suficiente sobre el ajedrez como para saber para qué sirve el 8,
Realmente no hay necesidad de una constante simbólica.
Entonces, ¿qué piensan ustedes? ¿Es esto exagerado, o debería seguir la convención y usar un símbolo?
coding-style
coding-standards
chocolatedevil
fuente
fuente
i
yj
las variables de bucle. Por mi vida no puedo determinar cuál se supone que representa el rango y cuál se supone que representa el archivo. Los rangos van desde 1..8 y archivos van desde a..h, pero en su caso, tantoi
yj
rango de 0..7, por lo que no ayuda a ver cuál es cuál. ¿Hay alguna crisis internacional de cartas de escasez no sé sobre, o lo que es malo con el cambio de nombre arank
yfile
?foreach(var rank in Ranks)
. También consideraría fusionar ambos bucles en uno donde cada elemento es una tupla (rango, archivo).Respuestas:
En mi humilde opinión, tu amigo tiene razón al usar un nombre simbólico, aunque creo que el nombre definitivamente debería ser más descriptivo (como en
BOARD_WIDTH
lugar deCHESS_CONST
).Incluso cuando el número nunca cambie a lo largo de la vida útil del programa, puede haber otros lugares en su programa donde el número 8 ocurrirá con un significado diferente. Reemplazar "8" por
BOARD_WIDTH
el ancho del tablero, y usar otro nombre simbólico cuando se trata de algo diferente hace que estos significados diferentes sean explícitos, obvios y que su programa general sea más legible y fácil de mantener. También le permite realizar una búsqueda global en su programa (o una búsqueda de símbolo inverso, si su entorno lo proporciona) en caso de que necesite identificar rápidamente todos los lugares en el código que dependen del ancho del tablero.Vea también esta publicación anterior de SE.SE para una discusión sobre cómo (o cómo no) elegir nombres para los números.
Como nota al margen, ya que se discutió aquí en los comentarios : si, en el código de su programa real, importa si la variable se
i
refiere a filas yj
columnas del tablero, o viceversa, entonces es recomendable elegir nombres de variables que haga la distinción clara, comorow
ycol
. El beneficio de tales nombres es que hacen que el código incorrecto parezca incorrecto.fuente
Ok, aquí hay algunos comentarios que tengo:
Deshacerse de los números mágicos es una gran idea. Existe un concepto conocido como DRY, que a menudo se tergiversa, pero la idea es que no duplique el conocimiento de los conceptos en su proyecto. Entonces, si tiene una clase llamada ChessBoard, puede mantener una constante llamada BOARD_SIZE o ChessBoard.SIZE adjunta. De esta manera, hay una única fuente para esta información. Además, esto ayuda a la legibilidad más adelante:
Incluso si el número nunca cambia, su programa es posiblemente mejor. Cualquier persona que lo lea sabe más información sobre lo que está haciendo el código.
Un mal nombre es peor que ningún nombre, pero eso no significa que algo no deba nombrarse. Solo cambia el nombre. No tire al bebé con el agua del baño. : p El nombre puede ser descriptivo siempre que comprenda bien lo que está describiendo. Entonces, ese concepto puede usarse para múltiples cosas diferentes.
fuente
Lo que realmente desea es eliminar las referencias ad nauseum a las constantes, ya sea que estén nombradas o desnudas:
Si realmente va a proliferar la constante repitiendo tales bucles y otras cosas, es mejor quedarse
8
.8
es autodescriptivo; No es una macro que representa otra cosa.You Are't Don't Gonna (TM) lo convertirá en un programa de ajedrez de 9x9 y si alguna vez lo hace, la proliferación de 8 no será la mayor dificultad.
Podemos buscar una base de código de línea de 150,000 para el token 8, y clasificar qué ocurrencias significan qué en segundos.
Mucho más importante es modularizar el código para que el conocimiento del ajedrez se concentre en la menor cantidad de lugares posible. Es mejor tener uno, dos, quizás tres módulos específicos de ajedrez en los que se produce un 8 literal, que treinta y siete módulos unidos con responsabilidad específica de ajedrez, que se refieren al 8 a través de un nombre simbólico.
Cuando o 8 esta constante se convierte en una fuente de tensión en su programa, puede solucionarlo fácilmente en ese momento. Solucione problemas reales que están sucediendo ahora. Si no siente que se ve obstaculizado por ese 8 en particular, vaya con ese instinto.
Suponga que en el futuro desea admitir dimensiones de placa alternativas. En ese caso, esos bucles tendrán que cambiar si usan una constante con nombre o
8
, porque las dimensiones serán recuperadas por alguna expresión comoboard.width
yboard.height
. Si tiene enBOARD_SIZE
lugar de8
, estos lugares serán más fáciles de encontrar. Entonces eso es menos esfuerzo. Sin embargo, no hay que olvidar el esfuerzo de reemplazar8
conBOARD_SIZE
en el primer lugar. El esfuerzo general no es menor. Haciendo un paso sobre el código para el cambio8
aBOARD_SIZE
, y luego otro para apoyar dimensiones alternativas, no es más barato que sólo ir de8
a apoyo dimensión alternativa.También podemos ver esto desde un análisis de riesgo / beneficio puramente frío y objetivo. El programa tiene constantes desnudas ahora. Si estos son reemplazados por una constante, no hay beneficio; El programa es idéntico. Con cualquier cambio, existe un riesgo distinto de cero. En este caso, es pequeño. Aún así, no se debe correr ningún riesgo sin un beneficio. Para "vender" el cambio frente a este razonamiento, tenemos la hipótesis de un beneficio: un beneficio futuro que ayudará con un programa diferente: una versión futura del programa que no existe ahora. Si se está planificando tal programa, esta hipótesis y su razonamiento asociado son de buena fe y deben tomarse en serio.
Por ejemplo, si le faltan días para agregar más código que prolifere aún más estas constantes, es posible que desee eliminarlas. Si esas instancias de las constantes son aproximadamente todas las instancias que existirán, ¿por qué molestarse?
Si alguna vez trabaja en software comercial, los argumentos de ROI también se aplicarán. Si un programa no se vende, y cambiar algunos números codificados a constantes no mejorará las ventas, no se le compensará el esfuerzo. El cambio tiene cero retorno de la inversión de tiempo. Los argumentos del ROI se generalizan más allá del dinero. Usted escribió un programa, invirtiendo tiempo y esfuerzo, y obtuvo algo de él: ese es su retorno, su "R". Si al hacer ese cambio solo, obtienes más de esa "R", sea lo que sea, entonces por todos los medios. Si tiene algún plan para un mayor desarrollo y ese cambio mejora su "R", lo mismo. Si el cambio no tiene una "R" inmediata o previsible para usted, olvídalo.
fuente
8
NO es tan autodescriptivo, es un número que podría significar cualquier cosa. Y tal vez quieran hacer un juego de ajedrez de 9x9, ¿por qué no? Si tiene 150,000 líneas de código, no hay forma de que pueda memorizar lo que cada una8
significa en el código, e incluso si pudiera, ¿por qué lo haría? Eso es solo un montón de problemas adicionales. En cuanto a la modularización, reemplazar8
con algo asíNUM_RANKS
no daña la modularidad, de hecho, ayuda porque hace que el código sea más fácil de manipular.8
conBOARD_SIZE
en el primer lugar" - El tiempo que había pasado más de escrutar su código tratando de averiguar lo que cada uno8
hace en sus meses de programa a partir de ahora muy probablemente superaría el tiempo dedicado a reemplazar8
con Una constante significativa a nivel de módulo.