Java: good programming approach? - java

I am being asked to learn Java very quickly and I am struggling with not only the verbose syntax but also the expected style and approach requirements.
Given a simple FizzBuzz challenge I produced the following code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n <= 30; n++) {
hit = false;
if (n % 3 == 0) {
System.out.print("Fizz");
hit = true;
}
if (n % 5 == 0) {
System.out.print("Buzz");
hit = true;
}
if (hit != true) {
System.out.print(n);
}
System.out.println();
}
}
}
Asked to refactor this code by the lead programmer and to consider possible future requirements and code managability issues I gave it some thought and produced the following refactored code:
public class FizzBuzz {
public static void main(String[] args) {
boolean hit;
for (int n = 1; n < 30; n++) {
hit = false;
hit = (n % 3 == 0) ? writeAction("Fizz") : hit;
hit = (n % 5 == 0) ? writeAction("Buzz") : hit;
if ( ! hit)
System.out.print(n);
System.out.println();
}
}
private static boolean writeAction(String actionWord){
System.out.print(actionWord);
return true;
}
}
However, the guy who set this task has moved on quite quickly and I never got any feedback on this approach. Am I going in the right direction with this or have I regressed?. To me this should scale better and would be easier to modify. I have also considered that maybe he was expecting some sort of TDD approach? I am aware that I have no tests currently.

This site isn't for reviews, but in case your question gets moved, here is some feedback (from the "clean code" perspective):
your "main" code sits in a main() method. Makes re-using it very hard.
talking about re-use - various things in there prevent re-using it
you have some duplicated code in there
you are violating the single layer of abstraction principle
How I would write something along the lines of:
public class FizzBuzz {
private final OutputStream out;
public FizzBuzz(OutputStream out) {
this.out = out;
}
public void runFizzBuzzUpTo(int n) {
for (int i = 1; i < n; i++) {
if ( writeIfTrue(n % 3 == 0, "Fizz") ) {
continue;
}
if ( writeIfTrue(n % 5 == 0, "Buzz") ) {
continue;
}
out.println(n);
}
}
private boolean writeIfTrue(boolean toCheck, String word) {
if (toCheck) {
out.println(word);
}
return toCheck;
}
public static void main(String[] args) {
new FizzBuzz(System.out).runFizzBuzzUpto(30);
}
}
Things I changed:
made the output the "core" thing of a class
provided the possibility to run for arbitrary positive numbers
Stuff still missing:
"single layere of abstraction" is still not good
instead of fixing "30" in main() - one could check for exactly one argument passed to main() - which would then be used as parameter for runFizzBuzzUpTo()

Of course, the second code is more modular and easier to modify that way. I mostly don't prefer to write the if conditions in the short way...
The method writeAction could be void because you don't have to return anything.
But you have good ideas :)

Related

Java Program does not give the output for values of n>6, Why?

import java.util.*;
class A{
static int count=0;
static String s;
public static void main(String z[]){
int n;
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
System.out.println(noOfBouncy(n));
}
public static int noOfBouncy(int k){
int limit=(int)Math.pow(10,k);
s=new String("1");
int num=Integer.parseInt(s);
while(num<limit){
if(isIncreasing(s) || isDecreasing(s) ){
}
else{
count++;
}
num++;
s=new String(Integer.toString(Integer.parseInt(s)+1));
}
count=limit-count;
return count;
}
}
public static boolean isIncreasing(String s){
int len=s.length();
for(int i=0;i<len-1;i++){
if(s.charAt(i)>s.charAt(i+1)){
return false;
}
}
return true;
}
public static boolean isDecreasing(String s){
int len=s.length();
for(int i=0;i<len-1;i++){
if(s.charAt(i)<s.charAt(i+1)){
return false;
}
}
return true;
}
I have given the definitions to the two functions used isIncreasing() & isDecresing()
The program runs well for the value of n<7 but does not respond for values above it, Why ?
I accept the programming style is very immature,please ignore.
I've tried to execute it with n=7 and it finishes in 810ms, returning 30817.
However, I recommend to you to optimize the performance of your program by saving unnecessary object instantiation: It will be better if you maintain the counter in num, and convert it to string just once, at the beginning of the loop:
int num=1;
while (num < limit)
{
s=Integer.toString(num);
if (isIncreasing(s) || isDecreasing(s))
{
}
else
{
count++;
}
num++;
}
Like this it takes just 450ms to finish.
The program was not actually stuck but it is taking way too much time to complete its execution when value of 'n' is larger.
So now the question is, I need to optimize the code to take minimum time #Little have an optimization bit that's not enough.
Any hint would be appreciable.
To increase the performance you should avoid the conversation to String and do the check with numbers.
As it doesn't matter for the result if you start the comparison from left to right or from right to left one computational solution could be.
as pseudo code
1) compare the value of the right most digit with the digit on it's left
2) is it lower --> we found a decreasing pair
3) else check if it is bigger --> we found an increasing pair
4) else --> not a bouncy pair
5) if we found already one decreasing and one increasing pair it's bouncy number
6) divide the number by ten if it's bigger then ten repeat with step 1)
The method to check if it's a bouncy number could look like this
static boolean isBouncyNumber(int number) {
boolean increasingNumber = false;
boolean decreasingNumber = false;
int previousUnitPosition = number % 10;
int remainder = number / 10;
while (remainder > 0) {
// step 1
int currentUnitPosition = remainder % 10;
if (currentUnitPosition > previousUnitPosition) {
// step 2
decreasingNumber = true;
} else if (currentUnitPosition < previousUnitPosition) {
// step 3
increasingNumber = true;
}
// step 5
if (decreasingNumber && increasingNumber) {
return true;
}
// step 6
previousUnitPosition = currentUnitPosition;
remainder = remainder / 10;
}
return decreasingNumber && increasingNumber;
}

Return statement best practices in java?

I want to know the difference between these two codes even though they produce the same output:
CODE 1:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return x;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
CODE 2:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return 0;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
They both output 15 but how come the second code also output's 15 instead of zero?My understanding is that the last call would be add(0) for code 2 and it would return zero.I also want to know is it okay to use multiple return statements or use a single return statement and replace the rest with local variables.I remember reading that single entry single exit model is a good practice.
This is a recursive method, so when x != 0, you will return the result of "x added to calling the method again with (x-1)". The final call will always return x == 0 or constant = 0, so you will return 15 from both versions.
Single return vs. multiple return is a matter of debate. The former should be preferred as a rule. Generally it will be obvious where multiple return statements are acceptable as it will be simpler to understand the method with them than with the alternative code constructs required to engineer a single exit point. Also note you could rewrite add as:
public static int add(int x) {
return x == 0 ? 0 : (x + add(x-1));
}
Version 1:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (x = 0)
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
Version 2:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (constant = 0) // the only difference
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
The use of multiple return statement versus using a single exit point cannot be answered with an easy one-line answer. I guess the best answer you can get is "it depends on your company's standards".
Single exit point is a very good standard, even though I don't personally endorse it. You end up having methods that always have a single return statement at the end, so you never get in a position where you are looking for those many possible return statement while editing someone else's code. I believe that developers that used to code in C tend to follow this standard (see this question).
I, for one, perfer using multiple return statements when it can help simplify the code. One case where I like to use it is to prevent cascading braces in my code. For instance, in the following example:
private int doSomething (int param) {
int returnCode;
if (param >= 0) {
int someValue = param * CONSTANT_VALUE;
if (isWithinExpectedRange (someValue)) {
if (updateSomething (someValue)) {
returnCode = 0;
} else {
returnCode = -3;
}
} else {
returnCode = -2;
}
} else {
returnCode = -1;
}
return returnCode;
}
I find this type of coding to be very confusing when reading it. I tend to change this type of code to:
private int doSomething (int param) {
if (param < 0) {
return -1;
}
int someValue = param * CONSTANT_VALUE;
if (!isWithinExpectedRange (someValue)) {
return -2;
}
if (!updateSomething (someValue)) {
return -3;
}
return 0;
}
The second example looks cleaner, and clearer, to me. Even more when the actual code has some extra coding in the else blocks.
Again, this is personal tastes. Some company might enforce a single exit point, some might not, and some developers prefer single exit point. The bottom line is, if there's a guideline available for you to follow in your environment, then do so. If not, then you can chose your own preference base partly on these arguments.

if condition to check if only one variable is set of the four variables at any point in JAVA

I want to display an error if more than one of the four variables is set...
In Java..this is what I came up with..
if( (isAset() && isBset()) || (isBset() && isCset()) || (isCset() && isDset()) || (isDset() && isAset()) )
attri.greedySelectionException(..);
I wanted to check if there is a better way of doing this..?
How about you use a counter and then compare it to 1?
Something like...
int i = 0;
if (isAset()) i++;
if (isBset()) i++;
if (isCset()) i++;
if (isDset()) i++;
if (i > 1)
...
Alternatively, if you are checking properties of a certain object, you could use some reflection to iterate through the relevant properties instead of having one if statement per property.
Edit: Take a look at Marius Žilėnas's varargs static method below for some tidier code, i.e. using (changed the oldschool for to a for-each and the ternary expression for an if):
static int trueCount(boolean... booleans) {
int sum = 0;
for (boolean b : booleans) {
if (b) {
sum++;
}
}
return sum;
}
instead of several if statements.
You can simplify this expression with :
if((isAset() || isCset()) && (isBset() || isDset()))
attri.greedySelectionException(..);
Wolfram alpha made the work for you :
Original expression
You can verify with the truth tables :
Original
Final
In Java 8 you can solve this problem with Streams in an elegant way (assuming your values are null if they are not set):
if (Stream.of(valueA, valueB, valueC, valueD).filter(Objects::nonNull).count() != 1) {
/* throw error */
}
If you have control on the implementation of isAset(), isBSet, isCSet, & isDset methods, you can achieve this with much more clarity if you return 1 or 0 instead of true or fales from this functions. These functions are to be created as below...
public int isAset()
{
return (A != null) ? 1 : 0;
}
To verify if more than one variable is set use use something like below...
if( isASet() + isBSet() + isCSet() + isDSet() > 1)
ThrowMoreAreSetException()
If you don't have control on this here is another way of doing it...
int count = isASet() ? 1 : 0;
count+= isBSet() ? 1 : 0;
count+= isCSet() ? 1 : 0;
count+= isDSet() ? 1 : 0;
if(count > 1)
ThrowMoreAreSetException()
By following either of these approches, code will be less clumsy and more readable than doing somany comparision combinations.
I suggest using varargs ... (see Java tutorial) and make a function that calculates how many trues was given. The following code to demonstrates it:
public class Values
{
public static boolean isASet()
{
return false;
}
public static boolean isBSet()
{
return true;
}
public static boolean isCSet()
{
return true;
}
public static boolean isDSet()
{
return true;
}
public static int booleans(boolean... booleans)
{
int sum = 0;
for (int i = 0; i < booleans.length; i++)
{
sum += booleans[i] ? 1 : 0;
}
return sum;
}
public static void main(String[] args)
{
System.out.println(
booleans(isASet(), isBSet(), isCSet(), isDSet()));
if (1 < booleans(isASet(), isBSet(), isCSet(), isDSet()))
{
System.out.println("Condition met.");
}
}
}
Try this:
if (!(isAset ^ isBset ^ isCset ^ isDset))
This will true only is any one is true or else false.

Finding an odd perfect number

I wrote these two methods to determine if a number is perfect. My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that.
The issue is with my main method. I tested the two test methods. I tried debugging and it gets stuck on the number 5, though I can't figure out why. Here is my code:
public class Lab6
{
public static void main (String[]args)
{
int testNum = 3;
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
}
public static int sum_of_divisors(int numDiv)
{
int count = 1;
int totalDivisors = 0;
while (count < numDiv)
if (numDiv%count == 0)
{
totalDivisors = totalDivisors + count;
count++;
}
else
count++;
return totalDivisors;
}
public static boolean is_perfect(int numPerfect)
{
int count = 1;
int totalPerfect = 0;
while (totalPerfect < numPerfect)
{
totalPerfect = totalPerfect + count;
count++;
}
if (numPerfect == totalPerfect)
return true;
else
return false;
}
}
Make
testNum%2 != 2
as
testNum%2 != 0
testNum=3
while (testNum != sum_of_divisors(testNum) && testNum%2 != 2)
testNum++;
You may want to do 'testNum+=2' since you are concerned about only odd numbers and replace the testNum %2!=2 with testNum>0 or other stopping condition. Eventually your integers will overflow.
"My prof wants me to combine them to find out if there is an odd perfect number. I know there isn't one(that is known), but I need to actually write the code to prove that."
Do you mean between 3 & 2^32-1? It is not known that there are no odd perfect numbers.

Shrinking the Code

I've got some java code that is used for my games NPCs to move arround.
Those are obviously in an 1d array.
public void route11() {
Scanner in = new Scanner(System.in);
Random number = new Random();
int random = number.nextInt(2);
if(random ==1)
hunters[1].x = hunters[1].x -1;
else
hunters[1].y = hunters[1].y -1;
}
public void Update() {
route11();
route2();
route3();
route4();
route5();
}
Methods route2, route3, ..., route5 look pretty much the same, the only thing that changes is the value of the array to correspond with a different hunter.
Could this code be "shrinked"? Im pretty sure my lecturer will be happy to minus my mark for such a messy and very much anti-OO code.
Also, all my collision/score code looks something like this, and it works for individual hunters:
if(hunters[i].x==0 && hunters[i].y == 0){
hunters[i].x = 11;
hunters[i].y = 11;
Player.score = Player.score + 1;
}
Your issue has nothing to do with OOP design. This is just about learning to use the tools available to write less redundant and more manageable code. If you utilize a for loop in your update and pass each individual hunter then this becomes much more condensed.
I will note that there are some unrelated OOP issues that you would do well to correct.
Hunter's members such as X and Y should not be exposed publicly, utilize getters/setters
The same goes for the Player's score member/field
public void update()
{
for(var i = 0; i < 5; i++)
{
route(hunters[i]);
collisionAndScoring(hunters[i]);
}
}
public void route(Hunter hunter)
{
Scanner in = new Scanner(System.in);
Random number = new Random();
int random = number.nextInt(2);
if(random == 1)
{
hunters.x--;
}
else
{
hunter.y--;
}
}
public void collisionAndScoring(Hunter hunter)
{
if (hunter.x == 0 && hunter.y == 0) //You should define constants for these to give them more meaning
{
hunter.x = 11; //another opportunity for a constant
hunter.y = 11; //another opportunity for a constant
Player.score++;
}
}

Categories

Resources