Estoy leyendo Code Complete de McConell , y él analiza el uso de variables booleanas para documentar su código. Por ejemplo, en lugar de:
if((elementIndex < 0) || (MAX_ELEMENTS < elementIndex) ||
(elementIndex == lastElementIndex)){
...
}
Él sugiere:
finished = ((elementIndex < 0) || (MAX_ELEMENTS < elementIndex));
repeatedEntry = (elementIndex == lastElementIndex);
if(finished || repeatedEntry){
...
}
Esto me parece lógico, una buena práctica y muy autodocumentado. Sin embargo, dudo en empezar a utilizar esta técnica con regularidad, ya que casi nunca me he encontrado con ella; y quizás sería confuso solo por ser raro. Sin embargo, mi experiencia aún no es muy amplia, por lo que estoy interesado en escuchar la opinión de los programadores sobre esta técnica, y me gustaría saber si alguien usa esta técnica con regularidad o la ha visto con frecuencia al leer código. ¿Es esta una convención / estilo / técnica que vale la pena adoptar? ¿Lo entenderán y apreciarán otros programadores, o lo considerarán extraño?
fuente
Respuestas:
Dividir una expresión que está demasiado anidada y complicada en subexpresiones más simples asignadas a variables locales, y luego juntas de nuevo, es una técnica bastante común y popular, independientemente de si las subexpresiones y / o la expresión general son booleanas o de casi cualquier otro tipo. Con nombres bien elegidos, una descomposición elegante de este tipo puede aumentar la legibilidad, y un buen compilador no debería tener problemas para generar un código equivalente a la complicada expresión original.
Algunos lenguajes que no tienen el concepto de "asignación" per se, como Haskell, incluso introducen construcciones especializadas para permitirle usar la técnica "dar un nombre a una subexpresión" (la
where
cláusula en Haskell) - parece indicar algo popularidad de la técnica en cuestión! -)fuente
Lo he usado, aunque normalmente envuelvo la lógica booleana en un método reutilizable (si se llama desde múltiples ubicaciones).
Ayuda a la legibilidad y cuando la lógica cambia, solo necesita cambiarse en un lugar.
Otros lo entenderán y no lo encontrarán extraño (excepto para aquellos que solo escriben funciones de mil líneas, es decir).
fuente
Intento hacerlo siempre que sea posible. Seguro, está utilizando una "línea adicional" de código, pero al mismo tiempo, está describiendo por qué está haciendo una comparación de dos valores.
En su ejemplo, miro el código y me pregunto "¿por qué la persona que ve que el valor es menor que 0?" En el segundo me estás diciendo claramente que algunos procesos han finalizado cuando esto ocurre. Sin adivinar en el segundo cuál era tu intención.
El más importante para mí es cuando veo un método como:
DoSomeMethod(true);
¿Por qué se establece automáticamente en verdadero? Es mucho más legible comofuente
[Object createOrderWithSource:YES backOrder:NO custom:YES type:kCreditCard];
La muestra proporcionada:
También se puede reescribir para usar métodos, que mejoran la legibilidad y preservan la lógica booleana (como señaló Konrad):
Tiene un precio, por supuesto, que son dos métodos adicionales. Si hace esto mucho, puede hacer que su código sea más legible, pero sus clases menos transparentes. Pero, de nuevo, también puede mover los métodos adicionales a clases auxiliares.
fuente
La única forma en que podría ver que esto va mal es si el fragmento booleano no tiene un nombre que tenga sentido y se elige un nombre de todos modos.
Señalo esto porque es común hacer reglas como "comentar todo tu código", "usar booleanos con nombre para todos los criterios if con más de 3 partes" solo para obtener comentarios que están semánticamente vacíos del siguiente tipo
fuente
Al hacer esto
eliminas la lógica de tu cerebro y la pones en el código. Ahora el programa sabe lo que quiso decir.
Siempre que nombras algo, le das una representación física . Existe.
Puedes manipularlo y reutilizarlo.
Incluso puede definir todo el bloque como un predicado:
y hacer más cosas (más adelante) en esa función.
fuente
Si la expresión es compleja, la muevo a otra función que devuelve un
bool
ejemplo,isAnEveningInThePubAGoodIdea(dayOfWeek, sizeOfWorkLoad, amountOfSpareCash)
o reconsidero el código para que no se requiera una expresión tan compleja.fuente
Recuerda que de esta forma calculas más de lo necesario. Debido a que se eliminan las condiciones del código, siempre se calculan ambas (sin cortocircuito).
Así que eso:
Después de la transformación se convierte en:
No es un problema en la mayoría de los casos, pero aún en algunos puede significar un peor rendimiento u otros problemas, por ejemplo, cuando en la segunda expresión asume que la primera ha fallado.
fuente
Creo que es mejor crear funciones / métodos en lugar de variables temporales. De esta manera, la legibilidad aumenta también porque los métodos se acortan. El libro Refactoring de Martin Fowler tiene buenos consejos para mejorar la calidad del código. Las refactorizaciones relacionadas con su ejemplo particular se denominan "Reemplazar temperatura con consulta" y "Método de extracción".
fuente
Personalmente, creo que esta es una gran práctica. Su impacto en la ejecución del código es mínimo, pero la claridad que puede proporcionar, si se usa correctamente, es invaluable cuando se trata de mantener el código más adelante.
fuente
si el método requiere una notificación de éxito: (ejemplos en c #) Me gusta usar el
para empezar. el código es falso hasta que lo cambio a:
luego al final:
fuente
Creo que depende del estilo que prefiera usted o su equipo. La refactorización "Introducir variable" podría ser útil, pero a veces no :)
Y debería estar en desacuerdo con Kevin en su publicación anterior. Su ejemplo, supongo, utilizable en caso de que se pueda cambiar la variable introducida, pero introducirla solo para un booleano estático es inútil, porque tenemos el nombre del parámetro en una declaración de método, entonces, ¿por qué duplicarlo en el código?
por ejemplo:
fuente
En mi experiencia, a menudo volví a algunos guiones antiguos y me preguntaba '¿qué diablos estaba pensando en ese entonces?'. Por ejemplo:
que no es tan intuitivo como:
fuente
Rara vez creo variables separadas. Lo que hago cuando las pruebas se complican es anidar los IF y agregar comentarios. Me gusta
El defecto admitido de esta técnica es que el próximo programador que se presente puede cambiar la lógica pero no se molestará en actualizar los comentarios. Supongo que es un problema general, pero muchas veces he visto un comentario que dice "validar la identificación del cliente" y la siguiente línea es examinar el número de pieza o algo así y me pregunto dónde está el cliente. entra id.
fuente