I have written this simple program that is a basically a maths test. I would like to know is there any areas I can improve on and if I have any bad habits that would be useful to break now. I realise I could have written this in the main class, but I was trying to practice implementing other classes, so I tried to use a few classes.
Also, are there good practices that I am using that I should try to keep?
P.S. I don’t usually use the comments I just added them to tell you what my intention is for a particular piece of code.
import java.util.Scanner; import java.util.Random; class Machine { int num1, num2, ans, att; int score = 0; Random rand = new Random(); Scanner in = new Scanner(System.in); public void sumGenerator(){ num1 = rand.nextInt(10); num2 = rand.nextInt(10); ans = num1 + num2; System.out.println(num1 + " + " + num2 ); }//sumGenerator Method public void answerGetter_score(){ att = in.nextInt(); if(att == ans){ score = score + 1; System.out.println("Correct"); System.out.println("Score is currently: " + score + "/5"); }else{ score = score - 1; System.out.println("Incorrect"); System.out.println("Score is currently: " + score + "/5"); }//else }//answer Getter method }//machine class public class calcu { public static void main(String[] args) { Machine machine1 = new Machine(); System.out.println("***Welcome to addition Math test***"); for(int i=5; i>0; i--){ machine1.sumGenerator(); machine1.answerGetter_score(); } System.out.println("Thanks for taking the test."); }//main method
Answer
Naming and Problem Decomposition
- Class names should be nouns; method names should be verbs. If you have a method named as a noun like
sumGenerator()
, that’s a red flag. - Each method should do one thing only; its name should reflect its purpose. If you have a method named
answerGetter_score()
, that’s a red flag. Is it getting an answer and keeping score? It also breaks the standardinterCapsNaming()
convention. - Each class should do one thing only; its name should reflect its purpose. I have no idea what a
Machine
or acalcu
is. The latter also breaks the standard capitalization convention. - Separate your input/output routines from the calculation routines. Forcing yourself to separate the two helps you come up with clean designs.
- Keep your
main()
function minimal. The temptation to stuff a lot of functionality intomain()
leads to sloppy design. - Avoid hard-coding assumptions in more than one place. What if you want to change the length of the quiz? Currently, 5 is hard-coded in several places. It’s easy to introduce a bug if someone fails to make the same change everywhere.
For this problem, I think that there should be two classes: SumGenerator
and ArithmeticQuiz
. SumGenerator
is responsible for making random addition questions. ArithmeticQuiz
“drives” it.
What if you want to change the quiz to do multiplication? Just swap out the SumGenerator
for a ProductGenerator
. To ease that transition, it would be helpful to define a QuestionGenerator
interface.
Code Formatting (only because you asked about good habits)
Consistent indentation is very important for readability. Do that, and discard the noisy //end
comments.
Also, add some horizontal spacing around punctuation, such as comparison operators.
The one-point penalty for an incorrect answer deserves a comment, since not everyone expects that behaviour.
Proposed Solution
QuestionGenerator.java:
interface QuestionGenerator {
void next();
String getQuestion();
int getAnswer();
}
SumGenerator.java:
import java.util.Random;
class SumGenerator implements QuestionGenerator {
private int maxAddend, num1, num2, ans;
private Random rand = new Random();
public SumGenerator(int maxAddend) {
this.maxAddend = maxAddend;
this.next();
}
@Override
public void next() {
num1 = rand.nextInt(this.maxAddend + 1);
num2 = rand.nextInt(this.maxAddend + 1);
ans = num1 + num2;
}
@Override
public String getQuestion() {
return num1 + " + " + num2;
}
@Override
public int getAnswer() {
return ans;
}
}
ArithmeticQuiz.java:
import java.util.Scanner;
public class ArithmeticQuiz {
private int length;
private QuestionGenerator questions;
public ArithmeticQuiz(int length, QuestionGenerator q) {
this.length = length;
this.questions = new SumGenerator();
}
public void run() {
// Closing the Scanner after use is a good habit.
// Automatically closing the Scanner using the
// try-with-resources feature of Java 7 is even better.
try (Scanner in = new Scanner(System.in)) {
int score = 0;
for (int i = this.length; i > 0; i--) {
System.out.println(this.questions.getQuestion());
int answer = in.nextInt();
if (this.questions.getAnswer() == answer) {
score++;
System.out.println("Correct");
}else{
score--; // Penalty for incorrect answer
System.out.println("Incorrect");
}
System.out.printf("Score is currently: %d/%d\n", score, this.length);
this.questions.next();
}
}
}
public static void main(String[] args) {
System.out.println("***Welcome to addition Math test***");
ArithmeticQuiz quiz = new ArithmeticQuiz(5, new SumGenerator(9));
quiz.run();
System.out.println("Thanks for taking the test.");
}
}
Attribution
Source : Link , Question Author : dazzaondmic , Answer Author : 200_success