I am working on a project for my Intro to Java course. I submitted my code and the reviewer said I needed to rewrite the following:
public void move()
{
if (iCanWin() > -1)
{
moveOnColumn(iCanWin());
}
else if (theyCanWin(0, 0, false) > -1)
{
moveOnColumn(theyCanWin(0, 0, false));
else
{
moveOnColumn(brilliantMove());
}
}
int nextMove = iCanWin();
if(nextMove > -1) {
moveOnColumn(nextMove);
} else ...
Not sure what should come after the else... The reviewer said that this would avoid the repetitive calling of the same method.
generally in statement if-ifelse-else
if (check a condition is true?)
{
moveOnColumn(iCanWin()); //do something
}
else if (other condition is true?)
{
moveOnColumn(theyCanWin(0, 0, false)); //do something
else//otherwise
{
moveOnColumn(brilliantMove()); //if previous condition doesn't be true
almost one of them this line go to be execute
}
Just remove the repetitive calls where possible as #ajb mentioned
public void move(){
int nextMove = iCanWin();
if (nextMove <= -1){
nextMove = theyCanWin(0, 0, false);
if(nextMove <= -1){
nextMove = brilliantMove();
}
}
moveOnColumn(nextMove);
}
Related
I currently working on a project that I need to remove a class that is being used by different other classes. There are cases that I can remove the one line of code that consists of that class where it will never affect the functionality of the program, but also there are cases that the class that you want to be removed is inside an if-statement. The main problem is that once I removed the line of code consisting of that class where is it inside the if-statement, it will be an empty if-statement that will violates the sonar.
Is there another way to refactor an empty if-statement other that negating the condition of one of the statements? Because when I'm just negating the condition, the readability of the code reduced.
For Example:
if((example_A >= 0) && (condition_A))
{
removeThisClass();
}
else if((example_B >= )) && (condition_B))
{
doSomething();
}
else
{
doAnything();
}
Refactored:
if(!((example_A >= 0) && (condition_A)) && ((example_B >= )) && (condition_B)))
{
doSomething();
}
else
{
doAnything();
}
You can put this code in separate method (https://refactoring.com/catalog/extractFunction.html) and write it like this:
public void DoSomeStuff() {
if((example_A >= 0) && (condition_A))
return;
if((example_B >= )) && (condition_B)) {
doSomething();
return;
}
doAnything();
}
If I understand you right, the line removeThisClass(); should be removed, and you don't want to be left with an empty block like this:
if((example_A >= 0) && (condition_A))
{
}
else if((example_B >= )) && (condition_B))
{
doSomething();
}
else
{
doAnything();
}
In order to not do the "A" tests twice, you need to negate the condition, e.g. like this:
if ((example_A < 0) || ! (condition_A))
{
if ((example_B >= )) && (condition_B))
{
doSomething();
}
else
{
doAnything();
}
}
Your refactored code is wrong, because if the "A" condition is true, the original code would execute removeThisClass();, which means it should now do nothing, but your code will call doAnything(); when "A" is true.
You can put in a comment. Sonar should accept that and it could also help the reader.
void doSomething() {
for (int i = 0; i < 42; i++) // Non-Compliant
{
}
for (int i = 0; i < 42; i++); // Compliant
if (myVar == 4) // Compliant - contains a comment
{
// Do nothing because of X and Y
}
else // Compliant
{
doSomething();
}
try // Non-Compliant
{
}
catch (Exception e) // Compliant
{
// Ignore
}
}
I have this kind of code
if(a == 3) {
if(b == 4) {
// do somthing
} else {
// do an other thing
}
} else {
// do the same other thing
}
I wondered, when I am in the first else, how could I go to the second elsebecause it will execute the same code
Thank you
You only want the // do something part to be executed when a==3 AND b==4, so you can combine them with an && operator.
This way you can merge the two conditions into one, and have a single else clause that performs the // do an other thing part :
if(a == 3 && b == 4) {
// do something
} else {
// do an other thing
}
I'm getting a PMD warning UseCollectionIsEmpty and the exact message it gives is:
Substitute calls to size() == 0 (or size() != 0, size() > 0, size() <
1) with calls to isEmpty()
on the last else if statement.
My issue is that my statement is checking if my ArrayList is NOT empty. But the PMD warning is telling me to change it to isEmpty(), which is not what I need to do. What's the work around to fix this?
if (theNeighbors.get(getDirection()) == Terrain.CROSSWALK) {
myDirection = getDirection();
} else if (theNeighbors.get(getDirection().left()) == Terrain.CROSSWALK) {
myDirection = getDirection().left();
} else if (theNeighbors.get(getDirection().right()) == Terrain.CROSSWALK) {
myDirection = getDirection().right();
} else if (myPossDir.size() > 0) {
myDirection = myPossDir.get(random.nextInt(myPossDir.size()));
} else {
myDirection = getDirection().reverse();
}
Instead of
} else if (myPossDir.size() > 0) {
myDirection = myPossDir.get(random.nextInt(myPossDir.size()));
} else {
myDirection = getDirection().reverse();
}
You should use:
} else if (myPossDir.isEmpty()) {
myDirection = getDirection().reverse();
} else {
myDirection = myPossDir.get(random.nextInt(myPossDir.size()));
}
This will make the above PMD warning go away, and it more clearly states your intent, you want to check that the collection is not empty. Using size() is for other cases - when you don't compare it to zero.
EDIT: Changed order of ifs, so now you use isEmpty() instead of !isEmpty() (another PMD warning, and negated ifs are not as easily readable as not negated ones)
Instead of;
if ( myCollection.size() > 0)
you can use
if(myCollection !=null && !mycollection.isEmpty())
to fix this PMD error.
In my method under the if statement:
if (currentLocationX == 0 && currentLocationY == 4)
I have a break statement that should make the program exit out of the while loop and return true for 'answer' and for the method. Yet after some testing it seems that after returning true for 'answer', it goes back into the while loop giving the wrong results int the end. Why is my break statement not doing what it's supposed to? Thank you!
P.S. (this method calls on some other method that were not relevant to mention here)
public boolean solveMaze()
{
boolean answer = false;
int currentLocationX;
int currentLocationY;
//push starting location
pushX(2);
pushY(1);
while((isEmptyX() == false) && (isEmptyY() == false))
{
printMaze();
System.out.println();
currentLocationX = popX();
currentLocationY = popY();
//mark current location as visited
visited(currentLocationX, currentLocationY, maze);
System.out.println("Current Location: " + currentLocationX + ", " + currentLocationY);
if (currentLocationX == 0 && currentLocationY == 4)
{
answer = true;
break;
}
else
{
//push all unvisited OPEN neighbor locations into stack
if (checkEast(currentLocationX, currentLocationY) == 0)
{
pushX(eastX(currentLocationX));
pushY(eastY(currentLocationY));
}
else;
if (checkSouth(currentLocationX, currentLocationY)== 0)
{
pushX(southX(currentLocationX));
pushY(southY(currentLocationY));
}
else;
if (checkWest(currentLocationX, currentLocationY)== 0)
{
pushX(westX(currentLocationX));
pushY(westY(currentLocationY));
}
else;
if (checkNorth(currentLocationX, currentLocationY)== 0)
{
pushX (northX(currentLocationX));
pushY(northY(currentLocationY));
}
else;
}
}
return answer;
}
I wrote out the basic logic of your method as
public static boolean solveMaze() {
boolean answer = false;
int currentLocationX = 0;
int currentLocationY = 4;
while (true) {
if (currentLocationX == 0 && currentLocationY == 4) {
System.out.println("Hit the break");
break;
} else {
System.out.println("Missed the break");
}
}
return answer;
}
and if you execute it you get Hit the break. So your solveMaze() method is fine in terms of breaking out of the loop once it satisfies your if-statement. I would say that if you see your code subsequently going back into the while loop, it must be that solveMaze() was called a second time.
Suppose I have a (very simple) recursive method like this:
public static void myMeth(int n)
{
// do something
// now execute the recursive call
if (n < 0) return;
else if ( n == SOME_CONST ) throw new UnsupportedOperationException();
else myMeth(n - 1);
}
(The second condition n == SOME_CONST is just there to make the point that sometimes an exception can occur, sometimes it does not).
Suppose I call myMeth(10), and that the exception does happen after a few recursive calls (say SOME_CONST == 5).
Is there any trick I could do (with try-catch block, that is) to get me back to the first frame of myMeth ?
This could work, there is probably a cleaner solution out there, but it's a start:
public static void myMeth(int n, boolean firstCall)
{
// do something
// now execute the recursive call
try
{
if (n < 0) return;
else if ( n == SOME_CONST ) throw new UnsupportedOperationException();
else myMeth(n - 1, false);
}
catch(UnsupportedOperationException e)
{
if (firstCall)
{
//logic
}
else
{
throw e;
}
}
}
try{
myMeth(n);
catch (UnsupportedOperationException e) {
myMeth(n); //or another number
}
Using another static variable to keep track of the first number (10)
static int SOME_CONST = 5;
static int keepN;
public static void myMeth(int n) {
// do something
// now execute the recursive call
try {
if (n < 0) {
return;
} else if (n == SOME_CONST) {
throw new UnsupportedOperationException();
} else {
myMeth(n - 1);
}
} catch (UnsupportedOperationException e) {
if (n == keepN) {
System.out.println(e);
System.out.println("YES first frame");
} else {
System.out.println("NO");
throw e;
}
}
}
public static void main(String[] args) {
keepN = 10;
myMeth(10);
}
// depth should be 0 on first call
public static boolean myMeth(int n, int depth)
{
// do something
// now execute the recursive call
if (n < 0) return true;
else if ( n == SOME_CONST ) return false;
boolean success = myMeth(n - 1, depth + 1);
if (depth == 0 && !success) {
// uh-oh
}
return success;
}
Or if you don't care about each individual frame in the recursion, replace depth with a boolean and change to boolean success = myMeth(n - 1, false);
I'm not sure what you're asking when you say you want to get back to the first frame though. Do you want to go back to the beginning of the first method call, so you can repeat the steps in the // do something block? Or are you fine executing right after the recursive call to myMeth?
If you're generating the Exception yourself, I replaced the need for that by using booleans. If not, you can replace it. You could also just throw an exception in the first frame, while still using booleans.
Yes, but this kind of trick will miss the whole concept of the recursive and will be hard to read and understand.
You shouldn't use recursive if you can't expect the definite number of options it can produce.
Otherwise use another solution.