toolversion plugin oxygen how java eclipse pmd

java - plugin - pmd eclipse oxygen



if(x!=y) vs if(x== y) (9)

He ejecutado el complemento PMD en Eclipse con mi código y recibo una advertencia de alta prioridad para el código similar al que se muestra a continuación:

if(singleRequest !=null){ // do my work }else{ // do my other work }

PMD dice `Avoid if (x != y) ..; else .. `Avoid if (x != y) ..; else .. ;

Y la descripción del error se ve así:

In an "if" expression with an "else" clause, avoid negation in the test. For example, rephrase: if (x != y) diff(); else same(); as: if (x == y) same(); else diff(); Most "if (x != y)" cases without an "else" are often return

pero todavía no puedo entender el impacto en mi código. Si alguien pudiera guiarme con un ejemplo, lo apreciaría.


¿Quién lee tu código? Tú lo haces. El compilador lo hace. O tal vez el asistente del profesor. Un compañero de trabajo, que no puede hacer la diferencia entre == y! =? Espero que no.

Solo puedo pensar que los negativos son malos en expresiones complejas. (El contexto es: al menos para mí. Sé que me he frustrado en la depuración de mi cabeza while(!expr && !expr2 || expr3) { } )

ch=getch(); if (ch!=''a'') ch=getch(); if (ch!=''a'') es un patrón que se extiende fácilmente a
if (ch!=''a'' || ch!=''b'') que siempre es verdadero, mientras suena semánticamente correcto.

Desde el punto de vista del rendimiento, es mejor ordenar las probabilidades.

if (more_probable) { .... unconditional_jump_to_end_of_block; } else { ... }

Esta elección debería llevar a un mejor desempeño, ya que no hay una penalización de predicción errónea en la rama más probable.

if (p && p->next) evaluado desde el punto de vista de rendimiento da malos resultados.



Es porque "buen estilo" dice que si las pruebas posibles deberían ser "positivas", entonces:

if (singleRequest == null){ // do my other work } else { // do my work }

Es más fácil de leer porque la prueba es "positiva" (es decir, "es igual a" no "no es igual a") y, en última instancia, una mejor legibilidad lleva a menos errores.

Editado

Este es particularmente el caso con la prueba como:

if (!str.equals("foo")) {

Usted puede fácilmente perder el ! en la parte delantera, pero si la prueba es positiva, es mucho más limpio.

La única vez que debería tener una prueba negativa es cuando no hay else bloque, entonces una prueba negativa es inevitable a menos que tenga un bloque true vacío, que a su vez se considera un problema de estilo.


Es un caso de equilibrio entre la legibilidad del código y la organización del código. La advertencia básicamente sugiere que es confuso para las personas que leen el código navegar por la negación de un negativo.

Mi regla de oro personal es que lo que se espera que sea el caso "normal" es lo que debería probar en el if. Considerar:

if (x != y) { // do work here... } else { throw new IllegalArgumentException(); }

En esta situación, diría que el trabajo importante se está realizando en el caso x != y , por lo tanto, es lo que debe probar. Esto se debe a que me gusta organizar el código para que el trabajo importante sea lo primero, seguido por el manejo de casos excepcionales.


Es un problema de legibilidad. Considerar

if ( x != y ) { } else // "if x doesn''t not equal y" { }

contra

if ( x == y ) { } else // "if x doesn''t equal y" { }

El último ejemplo es más inmediatamente identificable. Eso sí, no veo nada de malo en usar negativos ... puede tener mucho más sentido, considere

if ( x != null )...


La única razón por la que evitaría usar el caso negativo es si resultara en negativos dobles, lo que podría ser confuso.

p.ej

if (!checkbox.disabled) { // checkbox is enabled } else { // checkbox is disabled }


No es realmente una respuesta, pero puedes minimizar la complejidad general y mejorar la legibilidad si regresas o fallas antes y luego continúas sin sangría:

if (something == null) { throw new IllegalArgumentException("something must not be null"); } // continue here


PMD es una herramienta. Trabajos de PMD basados ​​en heurísticas. Alguien se decidió por esta heurística; que los condicionales negativos con las instrucciones else no son "buen estilo".

Sin embargo, en este caso, como he argumentado en mis comentarios, el código publicado es cómo lo escribiría . (En particular con x != null , pero no exclusivamente para esta construcción).

Esto se debe a que no veo el condicional (excepto porque se puede simplificar; por ejemplo, eliminando los dobles negativos como lo muestra Jim Kin), sino que observo la lógica de las ramas o "flujo".

Es decir, pongo la rama positiva primero. En este caso sostengo que

if (x != null) { doValid // positive branch } else { doFallback }

es semánticamente equivalente a

if (isValid(x)) { // it looks like a "positive conditional" now doValid // still positive branch } else { doFallback }

y así es la rama positiva primero.

Por supuesto, no todas las situaciones tienen un flujo positivo tan "claro", y algunas expresiones pueden expresarse mucho más fácilmente de manera negativa. En estos casos, "invertiré" las ramas, de manera similar a lo que sugiere la PMD, generalmente con un comentario que indique la acción en la parte superior del bloque si se invirtió la rama / flujo positivo.

Otro factor que puede influir en la elección condicional utilizada es el "alcance inmediato que sale" de ramas como:

if (x == null) { // return, break, or throw new Exception("oops!"); } else { // But in this case, the else is silly // and should be removed for clarity (IMOHO) which, // if done, avoids the PMD warning entirely }

Así es como consistentemente (aparte de algunas excepciones ocasionales) escribo mi código: if (x != null) { .. } . Utilice las herramientas disponibles; y haz que trabajen para ti. Vea la respuesta de Steven sobre cómo se puede configurar PMD para un "gusto" más adecuado aquí.


Tienes que evitar tener "no iguales" en la condición if. Esto se debe a que cuando alguien más mira su código, existe una posibilidad real de que la persona pueda ignorar el = y puede llegar a una conclusión errónea sobre la lógica de su programa.

Para su caso, es posible que tenga que intercambiar la lógica if con la lógica else y cambiar! = A ==