is this too much refactoring? - java

I try to refactor a code so that it will use separate methods to do some calculations. Just to make it clear.
What I want to know is, is it a good practice or a bad one to write a separate method to find out a simple thing like a number is odd or even ?
The original code is ,
int n = 11;
if (n % 2 == 0) {
System.out.println("Not selected");
} else {
boolean isPrime = true;
if (n == 0 || n == 1) {
isPrime = false;
} else {
int i = 2;
double a = Math.sqrt(Math.abs(n));
while (i <= a) {
if (n % i == 0) {
isPrime = false;
}
++i;
}
}
if(isPrime){
System.out.println("Prime it is");
}
}
The refactored code is,
int n = 11;
if (isEven(n)) {
System.out.println("Not selected");
} else {
if (isPrime(n)) {
System.out.println("Prime it is");
}
}
public static boolean isEven(int n) {
return n % 2 == 0 ? true : false;
}
public static boolean isPrime(int n){
if(n==0 || n==1)return false;
int i=2;
double a = Math.sqrt(Math.abs(n));
while(i<=a){
if(n%i==0){
return false;
}
++i;
}
return true;
}

It's generally considered good practice to break code down into separate methods for things like readability, length, or cyclomatic complexity, especially if you are not changing how the code works.
Boolean expressions, like what you have extracted, are often good choices for a quick extract function refactor. It allows a reader of the code base to know why a boolean expression is important or what it does by being able to read a descriptive function name versus complex domain related boolean math which they may not care to know the intricate details of.
A good book about commonly considered best practices in Java for code organization is a book called Clean Code. It's a pretty easy and enjoyable read, I would suggest it.

This is referred to as functional decomposition, and (in my opinion) is always good practice.
Not only is it easier to read, you can find problems in that code easier, since you can now easily test each section individually.
For example, you can now make sure isEven actually returns an even number. If a problem arises later on, you know that method is not the issue. This is called unit testing.
I suggest switching
if(isEven(n)) {
} else {
if(isPrime(n)) {
}
}
to
if(isEven(n)) {
} else if(isPrime(n)) {
}
Since it gives the same functionality, yet saves you a line.
Although, if you were counting 0 as being even, you wouldn't even need isPrime; if it's not even, it has to be prime. You wouldn't need to perform all the processing in isPrime:
if(isEven(n)) {
System.out.println("Even");
} else {
System.out.println("Odd");
}
To make it a bit cleaner:
String result = isEven(n) ? "Even" : "Odd";
System.out.println(result);

Related

Is it possible in java to simplify the following if-statement?

I want to simplify this if-Statement and prevent writing "!='*'" three times. Is it possible?
if (i != '*' && j != '*' && k != '*')
use arrays:put all elements into the array, traverse the array and judge。
List<String> list = new LinkedList<>(Arrays.asList(i,j,k));
if(list.stream().noneMatch("*"::equals)){
}else{
}
use string: splice elements into a string
String temp = i+j+k;
if(temp.contains("*")){
}
I want to simplify this if-Statement and prevent writing "!='*'" three times.
Here is a solution that simplifies the readability and intent.
First, make a simple, obvious method with a clear name (bonus: this is easy to write unit tests around):
private static boolean isValid(char i) {
return i != '*';
}
Then in your calling code, do this:
if (isValid(i) && isValid(j) && isValid(k)) {
// do things if all are valid
}
You can further improve the readability by making a single method which checks isValid() for an array of characters:
private static boolean allAreValid(char[] chars) {
for (char ch : chars) {
if (!isValid(ch)) {
return false;
}
}
return true;
}
Then your calling code becomes really clear, not just the steps but also the intent – proceed with the body of the if statement only if the characters are all valid.
char[] chars = {i, j, k};
if (allAreValid(chars)) {
// do things if all are valid
}
Yes it is possible to omit writing !='*' three times but the method will be still longer one. I would suggest to use the method which you have written in your question but if you really want to try something other out (maybe out of curiosity), you can do this:
char ch[] = {i,j,k}; /*I hope the variables i,j,k in question are char type*/
boolean flag = false;
for(int t = 0; t < ch.length; t++){
if(ch[t] != '*')
flag = true;
else{
flag = false;
break;
}
}
if(flag){
//Tasks to do...
}
Writing this much is a tedious job. Thus, if (i != '*' && j != '*' && k != '*') is the most optimised one. So I would recommend using it.

Change multiple if statements to avoid same code

I have the following code on a huge project. I want to find a better implementation to avoid the same code
if(CConst.CONST1.equals(SOMETHING1)){
const1fieldsaver = true;
if(a != 0){
//same code
if(value <= 0){
const1field = ...//same code
}
}
if(CConst.CONST2.equals(SOMETHING2)){
const2fieldsaver = true;
if(a != 0){
//same code
if(value <= 0){
const2field = ...//same code
}
}
how can i avoid these to if statements? The have the same code but as you can see it save the values to different variables. Is there any more efficient way to implement this?
I would suggest creating a method that you call inside each if block that executes the code you want.
if(CConst.CONST1.equals(SOMETHING1)){
const1fieldsaver = true;
if(a != 0){
executeSameCode(); //calling method here
if(value <= 0){
const1field = ...executeSameCode2(); //calling method, note that it is different from above method.
}
}
if(CConst.CONST2.equals(SOMETHING2)){
const2fieldsaver = true;
if(a != 0){
executeSameCode();
if(value <= 0){
const2field = ...executeSameCode2();
}
}
//somewhere else inside the class
public void executeMethod() {
//your code
} //can be made to return stuff
public void executeMethod2() {
//your code
} //again, can be made to return stuff
This way, you don't need to set up lots of temporary variables, but instead, just call the method from wherever you want.
Hope that helped!
If possible,
assign conditions directly to booleans and merge If-Statements.
e.g.
const1fieldsaver = CConst.CONST1.equals(SOMETHING1);
if(const1fieldsaver && a != 0 && value <= 0) {
const1field = ...
}
For more complex conditions I would use functions as recommended by Ted Lyngmo.

Partition Equal Subset Sum Top Down TLE

I am Solving Partition Equal Subset Sum of leetcode.
Problem States:
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
Each of the array element will not exceed 100.
The array size will not exceed 200.
I Wrote the Code for the following as
class Solution {
public boolean canPartition(int[] nums) {
int sum=0;
for(int i=0;i<nums.length;i++)
{
sum=sum+nums[i];
}
if(sum%2!=0)
{
return false;
}
int target=sum/2;
return helper(nums,target,nums.length);
}
boolean helper(int nums[],int sum,int n)
{
if(sum==0)
{
return true;
}
if(sum<0)
{
return false;
}
if(n==0)
{
return false;
}
return helper(nums,sum-nums[n-1],n-1)||helper(nums,sum,n-1);
}
}
Notice that I did not included the condition
if(sum<nums[n-1])
{
return false;
}
in the base case as i have included
if(sum<0)
{
return false;
}
which is the same thing as it would just add 1 more recursive call and then return false.
This code works for 89 of the test cases but gives TLE error for
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,100]
Now if the modify the same code and include
if(sum<nums[n-1])
{
return false;
}
and remove
if(sum<0)
{
return false;
}
i.e
class Solution {
public boolean canPartition(int[] nums) {
int sum=0;
for(int i=0;i<nums.length;i++)
{
sum=sum+nums[i];
}
if(sum%2!=0)
{
return false;
}
int target=sum/2;
return helper(nums,target,nums.length);
}
boolean helper(int nums[],int sum,int n)
{
if(sum==0)
{
return true;
}
if(n==0)
{
return false;
}
if(nums[n-1]>sum)
{
return false;
}
return helper(nums,sum-nums[n-1],n-1)||helper(nums,sum,n-1);
}
}
The code works fine and passes all the Test Cases.
Since both the code are same how is that one extra recursive call giving me TLE?
Is there is something else ?
The test cases are really weak. First one should get TLE as you did not use dynamic programming but performed a plain backtrack. Second one should get WA. If you used memoization your complexity would be O( totalSum * arraySize) but the complexity of your code is O(2 ^ arraySize).
now observe you have two options in every state. Either you pick the element or not. Even if this condition is true if(nums[n-1]>sum) , the second option is valid - going forward not picking the item. But your second code ignores both the cases for that condition reducing the calls to the point your solution takes less than 1 millisecond which is faster than most correct solution. As there was no counter test cases for the second solution it passed.

How to count number of branches in Java class

Is there a tool or a way to count the number of branches in a given Java class? For example, I want to count the number of branches in the following simple Java class:
public class Testt {
public boolean getTest(int x) {
if (x > 5) {
return true;
} else {
return false;
}
}
public int getTest1(int x) {
int t = 0;
if (x == 10) {
t = 1;
} else if (x == 8) {
t = 3;
} else {
t = 11;
}
return t;
}
}
The term you are looking for is "cyclomatic complexity".
Cyclomatic complexity is a software metric (measurement), used to
indicate the complexity of a program. It is a quantitative measure of
the number of linearly independent paths through a program's source
code.
If you are using Eclipse as your IDE there is a plugin called Eclipse Metrics that can give this kind of information.

How can I remove one of these if statements and shorten the code?

I have the following code. The only problem is that we run it through a checkstyle program and it comes up with the error Cyclomatic Complexity is 11 (max allowed is 10). I would like to know how can remove one of the if statement to make it do the same thing and let the program pass the test.
/**
* Check if there is a winner on the board
* #return the winner if BLANK there is no winner
**/
public char checkWinner(){
this.winner = BLANK;
int totalTiles = GRIDSIZE*GRIDSIZE;
//Check if the game has a win
for (int i=0; i < GRIDSIZE; i++) {
if((grid[i][0] == grid[i][1]) && (grid[i][1] == grid[i][2])){
winner = grid[i][0];
return winner;
}
if((grid[0][i] == grid[1][i]) && (grid[1][i] == grid[2][i])){
winner = grid[0][i];
return winner;
}
}
if((grid[0][0] == grid[1][1]) && (grid[1][1] == grid[2][2])){
winner = grid[0][0];
return winner;
}
if((grid[0][2] == grid[1][1]) && (grid[1][1] == grid[2][0])){
winner = grid[0][2];
return winner;
}
//Check if the game is a tie
if (movesMade == totalTiles){
winner = TIE;
}
return winner;
}
I don't know how the checker works but how about this:
if(((grid[0][0] == grid[1][1]) && (grid[1][1] == grid[2][2])) ||
((grid[0][2] == grid[1][1]) && (grid[1][1] == grid[2][0]))) {
winner = grid[1][1];
return winner;
}
If this does work, the irony of course is that this seems a little less readable than your code.
You could extract methods for checking rows and column and rewrite your code something like this:
public char checkWinner()
{
for (int i=0; i < GRIDSIZE; i++) {
if (checkRow(i)) return winner;
if (checkColumn(i)) return winner;
}
if (checkDiagTopLeft()) return winner;
if (checkDiagBottomLeft()) return winner;
}
Easier to read and less complexity.
Side note: Obviously, the winner stuff could use a redesign, but that was not part of the question and is left as an exercise for the reader (and commenters) if they feel like it.
The solution is already up there (combining the if statements), but I would not let Cyclomatic Complexity dictate my coding if the code of a method fits on a single page. The measure you want to aim for in a big project is readability and ease of understanding. Remember that code will be written potentially only once, but read quite a few times.
The first step can be to remove some redundancy from the equal expression. The allEqual makes the intent a bit clearer.
Assinging the winner to a field is strange. I've removed that in the refactoring. If you really need the assignment you could do it in a separate method calling checkWinner. The problem with returning and assigning is that it's unexpected for a caller to have this side effect.
public char checkWinner() {
// Check if the game has a win
for (int i = 0; i < GRIDSIZE; i++) {
if (allEqual(grid[i][0], grid[i][1], grid[i][2])) return grid[i][0];
if (allEqual(grid[0][i], grid[1][i], grid[2][i])) return grid[0][i];
}
if (allEqual(grid[0][0], grid[1][1], grid[2][2])) return grid[0][0];
if (allEqual(grid[0][2], grid[1][1], grid[2][0])) return grid[0][2];
// Check if the game is a tie
int totalTiles = GRIDSIZE * GRIDSIZE;
return movesMade == totalTiles ? TIE : BLACK;
}
private boolean allEqual(char... c) {
for(int i=1;i<c.length;i++) if(c[i-1] != c[i]) return false;
return true;
}
Open Problems:
The char[][] array is not the most efficient data structure to represent the board. You could use a BitSet.
You defined GRIDSIZE constant but you're could would break down if you actually changed it from 3 to another value.
You can use the fact that checking row/columns and diagonals is symmetric. The parameters have to be transposed use this.
Using the GRIDSIZE constant you do not have to address all cells explicitly:
public char checkWinner() {
// Check if the game has a win
for (int i = 0; i < GRIDSIZE; i++) {
if (rowEqual(i)) return grid[i][0];
if (columnEqual(i)) return grid[0][i];
}
if (diagonalLeftToRightEqual()) return grid[0][0];
if (diagonalRightToLefttEqual()) return grid[0][GRIDSIZE];
// Check if the game is a tie
int totalTiles = GRIDSIZE * GRIDSIZE;
return movesMade == totalTiles ? TIE : BLACK;
}
private boolean rowEqual(int r) {
for(int i=1;i<GRIDSIZE;i++) if(grid[r][i-1] != grid[r][i]) return false;
return true;
}
private boolean diagonalLeftToRightEqual() {
for(int i=1;i<GRIDSIZE;i++) if(grid[i-1][i-1] != grid[i][i]) return false;
return true;
}
Cyclometric complexity is a measure of the number of paths through your code. Your function is composed almost exclusively of if statements.
You can combine two or more if statements with or:
if(a)
do_something();
if(b)
do_something();
Should be replaced by:
if(a || b)
do_something();

Categories

Resources