Nuestra organización tiene una regla de codificación requerida (sin ninguna explicación) que:
if ... else if construcciones deben terminarse con una cláusula else
Ejemplo 1:
if ( x < 0 )
{
x = 0;
} /* else not needed */
Ejemplo 2
if ( x < 0 )
{
x = 0;
}
else if ( y < 0 )
{
x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
/* no change in value of x */
}
¿Qué caso límite está diseñado para manejar esto?
Lo que también me preocupa de la razón es que el Ejemplo 1 no necesita un else
pero el Ejemplo 2 sí. Si la razón es la reutilización y la extensibilidad, creo que else
debería usarse en ambos casos.
assert(false, "should never go here")
podría tener sentidoif (x < 0) { x = 0; } else { if (y < 0) { x = 3; }}
. O simplemente podría seguir tales reglas, muchas de las cuales son tontas, simplemente porque se le exige.< 0
verificaciones), por lo que esa afirmación continúa. para bloquear el programa en lo que probablemente sea el caso más común donde los valores están en los límites esperados.Respuestas:
Como se menciona en otra respuesta, esto es de las pautas de codificación MISRA-C. El propósito es la programación defensiva, un concepto que a menudo se usa en la programación de misión crítica.
Es decir, todos
if - else if
deben terminar con unelse
, y todosswitch
deben terminar con undefault
.Hay dos razones para esto:
Código autodocumentado. Si se escribe un
else
sino dejarlo vacío que significa: "Definitivamente he considerado el escenario cuando niif
tampocoelse if
son ciertas".No escribir una
else
no quiere decir: "Yo tampoco considera el escenario donde niif
tampocoelse if
son verdaderas, o he olvidado por completo a considerarlo y hay potencialmente un error de grasa aquí en mi código".Detener el código fuera de control. En el software de misión crítica, debe escribir programas robustos que tengan en cuenta incluso lo poco probable. Entonces puedes ver código como
Este código será completamente ajeno a los programadores de PC y los científicos informáticos, pero tiene mucho sentido en el software de misión crítica, ya que detecta el caso en que el "mybool" se ha corrompido, por cualquier razón.
Históricamente, temerías la corrupción de la memoria RAM debido a EMI / ruido. Esto no es un gran problema hoy. Es mucho más probable que la corrupción de la memoria ocurra debido a errores en otras partes del código: punteros a ubicaciones incorrectas, errores fuera de los límites de la matriz, desbordamiento de pila, código desbocado, etc.
Entonces, la mayoría de las veces, un código como este regresa para abofetearse cuando ha escrito errores durante la etapa de implementación. Lo que significa que también podría usarse como una técnica de depuración: el programa que está escribiendo le dice cuándo ha escrito errores.
EDITAR
En cuanto a por qué
else
no es necesario después de cada uno de ellosif
:Una
if-else
oif-else if-else
cubre completamente todos los valores posibles que puede tener una variable. Pero unaif
declaración simple no está necesariamente allí para cubrir todos los valores posibles, tiene un uso mucho más amplio. En la mayoría de los casos, solo desea verificar una determinada condición y, si no se cumple, no haga nada. Entonces simplemente no tiene sentido escribir programación defensiva para cubrir elelse
caso.Además, desordenaría el código por completo si escribiera un vacío
else
después de cada unoif
.MISRA-C: 2012 15.7 no da razones por las cuales
else
no es necesario, solo dice:fuente
if/else if/else
compilado a lo que espera? ¿Y luego uno más para verificar el verificador anterior también?mybool
tenga un tipo no booleano, como fue el caso antes de que C obtuviera el suyobool
; entonces el compilador no haría la suposición sin un análisis estático adicional). Y sobre el tema de 'Si escribe otra cosa pero la deja vacía, significa: "Definitivamente he considerado el escenario cuando ni si ni si es cierto". Mi primera reacción es asumir que el programador olvidó poner código. el bloque else, de lo contrario, ¿por qué tener un bloque else vacío sentado allí? Un// unused
comentario sería apropiado, no solo un bloque vacío.else
bloque debe contener algún tipo de comentario si no hay código. La práctica común de vacíoelse
es un solo punto y coma además de un comentario:else { ; // doesn't matter }
. Como no hay ninguna razón por la cual alguien simplemente escribiría un punto y coma con sangría en una línea propia. Práctica similar se utiliza a veces en bucles vacías:while(something) { ; // do nothing }
. (código con saltos de línea, obviamente. Los comentarios SO no los permiten)Su empresa siguió la guía de codificación MISRA. Hay algunas versiones de estas pautas que contienen esta regla, pero de MISRA-C: 2004 † :
En MISRA-C: 2012 , que reemplaza la versión 2004 y es la recomendación actual para nuevos proyectos, existe la misma regla pero está numerada 15.7 .
Ejemplo 1: en un solo programador if, el programador puede necesitar verificar n número de condiciones y realizar una sola operación.
En un uso regular, no es necesario realizar una operación todo el tiempo cuando
if
se usa.Ejemplo 2: Aquí el programador verifica n número de condiciones y realiza múltiples operaciones. En el uso regular
if..else if
es comoswitch
si tuviera que realizar una operación como predeterminada. Por lo tanto, el usoelse
es necesario según el estándar misra† Las versiones actuales y pasadas de estas publicaciones están disponibles para su compra a través de la tienda web MISRA ( vía ).
fuente
else
cláusula sea inalcanzable? (Deje la condición final en su lugar, ¿arroja un error, tal vez?)Este extra disminuirá la cobertura del código de su programa.
En mi experiencia con portar el kernel de Linux o el código de Android a una plataforma diferente, muchas veces hacemos algo mal y en logcat vemos algunos errores como
fuente
__FILE__
y__LINE__
macros son una herramienta útil para la toma de la ubicación de origen fácil de encontrar si el mensaje es cada vez impreso.Solo una breve explicación, ya que hice esto hace unos 5 años.
No hay (con la mayoría de los idiomas) ningún requisito sintáctico para incluir una
else
declaración "nula" (e innecesaria{..}
), y en "pequeños programas simples" no hay necesidad. Pero los programadores reales no escriben "pequeños programas simples" y, lo que es más importante, no escriben programas que se usarán una vez y luego se descartarán.Cuando uno escribe un if / else:
todo parece simple y apenas se ve el punto de agregar
{..}
.Pero algún día, dentro de unos meses, algún otro programador (¡nunca cometerá tal error!) Necesitará "mejorar" el programa y agregará una declaración.
De repente se
doSomethingElse
olvida que se supone que debe estar en laelse
pierna.Entonces eres un buen programador y siempre lo usas
{..}
. Pero tu escribes:Todo está bien hasta que ese nuevo niño haga una modificación a medianoche:
Sí, está formateado incorrectamente, pero también lo es la mitad del código en el proyecto, y el "formateador automático" se ve afectado por todas las
#ifdef
declaraciones. Y, por supuesto, el código real es mucho más complicado que este ejemplo de juguete.Desafortunadamente (o no), he estado fuera de este tipo de cosas durante algunos años, así que no tengo un nuevo ejemplo "real" en mente: lo anterior es (obviamente) artificial y un poco tonto.
fuente
Esto se hace para que el código sea más legible, para referencias posteriores y para dejar en claro, a un revisor posterior, que los casos restantes manejados por el último
else
, son casos de no hacer nada , para que no se pasen por alto a primera vista.Esta es una buena práctica de programación, que hace que el código sea reutilizable y ampliable .
fuente
Me gustaría agregar, y en parte contradecir, las respuestas anteriores. Si bien es común usar if-else if de una manera similar a un interruptor que debería cubrir el rango completo de valores pensables para una expresión, de ninguna manera se garantiza que cualquier rango de condiciones posibles esté completamente cubierto. Lo mismo puede decirse sobre la construcción del interruptor en sí, de ahí el requisito de usar una cláusula predeterminada, que capture todos los valores restantes y, si no se requiere de otra manera, puede usarse como una protección de aserción.
La pregunta en sí presenta un buen contraejemplo: la segunda condición no se relaciona en absoluto con x (que es la razón por la que a menudo prefiero la variante basada en if más flexible que la variante basada en switch). Del ejemplo, es obvio que si se cumple la condición A, x debe establecerse en un cierto valor. Si no se cumple A, entonces se prueba la condición B. Si se cumple, entonces x debería recibir otro valor. Si no se cumplen ni A ni B, entonces x debería permanecer sin cambios.
Aquí podemos ver que se debe usar una rama vacía para comentar sobre la intención del programador para el lector.
Por otro lado, no puedo ver por qué debe haber una cláusula else, especialmente para la última declaración if. En C, no existe tal cosa como 'más si'. Solo hay si y más. En cambio, de acuerdo con MISRA, la construcción debería tener una sangría formal de esta manera (y debería haber puesto las llaves de apertura en sus propias líneas, pero eso no me gusta):
Cuando MISRA pide colocar llaves alrededor de cada rama, se contradice al mencionar "si ... si no construye".
Cualquiera puede imaginar la fealdad de los árboles profundamente anidados si no, ver aquí en una nota al margen . Ahora imagine que esta construcción se puede extender arbitrariamente a cualquier lugar. Luego, pedir una cláusula else al final, pero no en ningún otro lado, se vuelve absurdo.
Por lo tanto, estoy seguro de que las personas que desarrollaron las pautas de MISRA tenían en mente la intención de cambiar si no es así.
Al final, se trata de que definan con precisión qué se entiende con un "if ... else if construct"
fuente
La razón básica es probablemente la cobertura del código y la otra implícita: ¿cómo se comportará el código si la condición no es verdadera? Para una prueba genuina, necesita alguna forma de ver que ha probado con la condición falsa. Si cada caso de prueba que tiene pasa por la cláusula if, su código podría tener problemas en el mundo real debido a una condición que no probó.
Sin embargo, algunas condiciones pueden ser como el Ejemplo 1, como en una declaración de impuestos: "Si el resultado es menor que 0, ingrese 0." Aún necesita hacerse una prueba donde la condición es falsa.
fuente
Lógicamente, cualquier prueba implica dos ramas. ¿Qué haces si es verdad y qué haces si es falso?
Para aquellos casos en que cualquiera de las ramas no tiene funcionalidad, es razonable agregar un comentario sobre por qué no necesita tener funcionalidad.
Esto puede ser beneficioso para el próximo programador de mantenimiento. No deberían tener que buscar demasiado para decidir si el código es correcto. Puedes prehunt el elefante .
Personalmente, me ayuda, ya que me obliga a mirar el caso más y evaluarlo. Puede ser una condición imposible, en cuyo caso puedo lanzar una excepción ya que se viola el contrato. Puede ser benigno, en cuyo caso un comentario puede ser suficiente.
Su experiencia puede ser diferente.
fuente
La mayoría de las veces cuando solo tiene una sola
if
declaración, es probable que sea una de las razones, tales como:Ejemplo
Pero cuando lo haga
if .. else if
, probablemente sea una de las razones, tales como:Y en caso de que
if .. else if
cubra todas las posibilidades, en ese caso su últimoif (...)
no es necesario, simplemente puede eliminarlo, porque en ese punto los únicos valores posibles son los cubiertos por esa condición.Ejemplo
Y en la mayoría de estos motivos, es posible que algo no encaje en ninguna de las categorías en su
if .. else if
, por lo tanto, la necesidad de manejarlos en unaelse
cláusula final , el manejo se puede hacer a través de un procedimiento de nivel comercial, notificación de usuario, mecanismo de error interno, ..etc.Ejemplo
Esta
else
cláusula final es bastante similar a algunas otras cosas en idiomas comoJava
yC++
, como:default
caso en una declaración de cambiocatch(...)
que viene después de todos loscatch
bloques específicosfinally
en una cláusula try-catchfuente
Nuestro software no era de misión crítica, pero también decidimos usar esta regla debido a la programación defensiva. Agregamos una excepción de lanzamiento al código teóricamente inalcanzable (switch + if-else). Y nos salvó muchas veces ya que el software falló rápidamente, por ejemplo, cuando se agregó un nuevo tipo y se nos olvidó cambiar uno o dos en caso contrario o cambiar. Como beneficio adicional, fue muy fácil encontrar el problema.
fuente
Bueno, mi ejemplo implica un comportamiento indefinido, pero a veces algunas personas intentan ser elegantes y fallan mucho, eche un vistazo:
Probablemente nunca esperarías tener lo
bool
que no estrue
nifalse
, sin embargo, puede suceder. Personalmente, creo que este es un problema causado por una persona que decide hacer algo elegante, pero unaelse
declaración adicional puede evitar más problemas.fuente
Actualmente estoy trabajando con PHP. Crear un formulario de registro y un formulario de inicio de sesión. Solo estoy usando if y else. No más si o algo que sea innecesario.
Si el usuario hace clic en el botón Enviar -> pasa a la siguiente declaración if ... si el nombre de usuario es menor que 'X', entonces alerta. Si tiene éxito, verifique la longitud de la contraseña, etc.
No es necesario un código adicional, como otro, si eso podría descartar la confiabilidad del tiempo de carga del servidor para verificar todo el código adicional.
fuente