I am doing a practice project to create a calculator with OOP principles. Below is my CalculatorApp that communicates with Calculator(to calc integers) and StringParser(to tokenize input). For CalculatorApp to work, strict rules need to follow. For example, the input must use "add" not "plus" and "(" not any other kind. Therefore I have so many hardcoded variables in the class. Is it a bad design? Am I doing too much in process and is creating variables (i.e wordToSign_map) on the fly bad practice? Should I refactor all the variables to another class? This is for a job so I need to make sure I do my best. Any feedback will be greatly appreciated.
public class CalculatorApp {
String input;
Calculator calculator;
int result;
final String open_parentheses = "(";
final String close_parentheses = ")";
final String delimiter = " ";
public CalculatorApp(Calculator calculator){
this.calculator = calculator;
}
public CalculatorApp input (String input){
this.input = input;
return this;
}
public CalculatorApp process (){
if(!isExpression()){
result=Integer.parseInt(input);
return this;
}
Map<String, String> wordToSign_map = new HashMap<>();
wordToSign_map.put("add", "+");
wordToSign_map.put("multiply", "*");
Map<String, String> parentheses_spacing_map = new HashMap<>();
parentheses_spacing_map.put(open_parentheses, open_parentheses+delimiter);
parentheses_spacing_map.put(close_parentheses, delimiter+close_parentheses);
StringParser stringParser = new StringParser(input, wordToSign_map, parentheses_spacing_map, delimiter);
String[] parsedString = stringParser.TokenizeExpression();
Set<String> operatorSigns = new HashSet<>();
operatorSigns.addAll(wordToSign_map.values());
try {
Tree tree = new Tree();
tree.constructATree(parsedString, operatorSigns, open_parentheses, close_parentheses);
result = evaluateExpressionTree(tree.getRoot());
} catch (EmptyStackException e) {
System.out.println("Invalid input");
throw e;
}
return this;
}
public int output (){
return result;
}
private boolean isExpression(){
return input.contains(open_parentheses) && input.contains(close_parentheses);
}
}
This is my Tree class. It takes a string list and creates nodes and children around the brackets and +,* signs. That's why the string has to be exactly one-spaced and can't contain any unknown signs. Should I leave the comments there? Is it too messy and hard to read? Is passing too many args in the method call bad, should I instead pass them in the constructor and hold them as fields?
public class Tree {
Node root;
public Node getRoot() {
return root;
}
public void constructATree (String[] parsedString, Set<String> operatorSigns, String startExp, String endExp) throws EmptyStackException {
Stack<Node> localRoot = new Stack<>();
for (int i = 0; i < parsedString.length; i++) {
if(parsedString[i].equals(startExp)) { // ignore (
continue;
}
if(operatorSigns.contains(parsedString[i])){ // operator for expression
localRoot.push(new Node(parsedString[i], true));
} else if(parsedString[i].equals(endExp)) // end of an expression
{
Node tempNode = localRoot.pop(); // get the last node
if(localRoot.empty()){
this.root = tempNode; // if there is only one expression return it as the root of the tree
} else {
Node tail = localRoot.peek(); //
tail.addChild(tempNode); // add the children from last node to trailing node
}
} else {
Node tempNode = localRoot.pop();
tempNode.addChild(new Node(parsedString[i], false)); // add values to children of operator node
localRoot.push(tempNode);
}
}
}
}
Node? \$\endgroup\$