Cleaning code with too much conditionals - java

I've found this ugly piece of code from some time ago:
#FXML
private void buttSellAction(ActionEvent event){
InfoTip infoTip = new InfoTip();
if(comboPizza.getValue() != null){
if(comboPizzaSize.getValue() != null){
PizzaData selectedPizza = getPizzaData(comboPizza.getValue());
PizzaSizeData selectedPizzaSize = getPizzaSizeData(comboPizzaSize.getValue());
Date date = new Date();
Timestamp timestamp = new Timestamp(date.getTime());
if( selectedPizza != null ){
if(groupDelivery.getSelectedToggle().equals(radioNo)){ // sale without delivery
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Total cost: " + String.format("%.2f", selectedPizza.getPrice() + selectedPizzaSize.getPrice()));
alert.setContentText("Proceed with sale?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
insertSale(timestamp, currentUser.getLogin(), selectedPizza.getID(),
selectedPizzaSize.getSize(), false, selectedPizza.getPrice() + selectedPizzaSize.getPrice());
infoTip.getInfoTip().setId("greenInfoTip");
infoTip.showTip((Button)event.getSource(), " Saved ");
}
}else{ //Sale with delivery
String adress = textFAdress.getText();
String clientName = textFClientName.getText();
String telephone = textFTelephone.getText();
String deliveryCost = textFCost.getText();
boolean isAdressOK = ((adress.length() < 51) && (adress.isEmpty() == false))? true: false;
boolean isClientNameOK = (clientName.length() < 36)? true: false;
boolean isTelephoneOK = ((telephone.length() < 21) && (telephone.isEmpty() == false))? true: false;
boolean isCostOK;
try{ Double.valueOf(deliveryCost); isCostOK = true; }
catch(NumberFormatException exception){ isCostOK = false; }
if(isAdressOK == true){
if(isClientNameOK == true){
if(isTelephoneOK == true){
if(isCostOK == true){
double totalCost = selectedPizza.getPrice() + selectedPizzaSize.getPrice() + Double.valueOf(deliveryCost);
//everything is okey
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Total cost: " + totalCost);
alert.setContentText("Proceed with sale?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
int id = insertSale(timestamp, currentUser.getLogin(), selectedPizza.getID(),
selectedPizzaSize.getSize(), true, selectedPizza.getPrice() + selectedPizzaSize.getPrice());
insertDelivery(id, adress, clientName, telephone, Double.valueOf(deliveryCost));
infoTip.getInfoTip().setId("greenInfoTip");
infoTip.showTip((Button)event.getSource(), " Saved ");
} else {
// ... user chose CANCEL or closed the dialog
}
}else{ //cost not ok
infoTip.showTip(textFCost, "keep right format e.g. 4.35");
}
}else{ //telephone not ok
infoTip.showTip(textFTelephone, "max 20 characters, not empty");
}
}else{ //client name not ok
infoTip.showTip(textFClientName, "max 35 characters");
}
}else{ //adress not ok
infoTip.showTip(textFAdress, "max 50 characters, not empty");
}
}
}else{ //couldnt found selected pizza in pizzaList(which should not be possible)
ExceptionDialog exceptionDialog = new ExceptionDialog("Error when searching for selected pizza", new Exception());
exceptionDialog.showAndWait();
}
}else{ //pizza size not choosen
infoTip.showTip(comboPizzaSize, "select pizza size");
}
}else{ //pizza not choosen
infoTip.showTip(comboPizza, "select pizza");
}
}
I know now it has few major flaws:
method is doing too much and its too long,
it has too many conditional statements so it is easy to get lost,
unnecessary comments making code less readable.
repeated code,
possibly mixed levels of complexity.
testing it would be horrible.
something else??
How can I refactor it to make it clean and simple?

I'd take a slightly different approach to the other answer. I'd separate the validation from the other logic in the method. This means that you don't have to read lots of if statements to see the core logic of the method and if you want to change the validation you only need to update one statement in one place. eg for the first section, add a private method:
private PizzaSizeData getAndVerifySelectedPizza() {
if (comboPizza.getValue() == null) {
infoTip.showTip(comboPizza, "select pizza");
return null;
}
if (comboPizzaSize.getValue() == null) {
infoTip.showTip(comboPizzaSize, "select pizza size");
return null;
}
PizzaData selectedPizza = getPizzaData(comboPizza.getValue());
if (selectedPizza == null) {
ExceptionDialog exceptionDialog = new ExceptionDialog("Error when searching for selected pizza", new Exception());
exceptionDialog.showAndWait();
return null;
}
return getPizzaSizeData(comboPizzaSize.getValue());
}
You could return optionals instead of null but this illustrates the mechanism.
And then call the new method:
private void buttSellAction(ActionEvent event){
InfoTip infoTip = new InfoTip();
PizzaSizeData selectedPizzaSize = getAndVerifySelectedPizza();
if (selectedPizzaSize == null) {
return;
}
// Carry on with the method....
Putting validation at the start of a method with an early return statement is a common pattern so the multiple returns aren't going to confuse anyone and they allow each validation rule to be written separately.

you can use ladder if else in your code. like this
if(isAdressOK == true && isClientNameOK == true && isTelephoneOK == true && isCostOK == true){
double totalCost = selectedPizza.getPrice() + selectedPizzaSize.getPrice() + Double.valueOf(deliveryCost);
//everything is okey
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Total cost: " + totalCost);
alert.setContentText("Proceed with sale?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
int id = insertSale(timestamp, currentUser.getLogin(), selectedPizza.getID(),
selectedPizzaSize.getSize(), true, selectedPizza.getPrice() + selectedPizzaSize.getPrice());
insertDelivery(id, adress, clientName, telephone, Double.valueOf(deliveryCost));
infoTip.getInfoTip().setId("greenInfoTip");
infoTip.showTip((Button)event.getSource(), " Saved ");
} else {
// ... user chose CANCEL or closed the dialog
}
}else if(!isAdressOK == true){
infoTip.showTip(textFAdress, "max 50 characters, not empty");
}else if(!isClientNameOK == true){
infoTip.showTip(textFClientName, "max 35 characters");
}else if(!isTelephoneOK == true){
infoTip.showTip(textFTelephone, "max 20 characters, not empty");
}else{
infoTip.showTip(textFCost, "keep right format e.g. 4.35");
}
same for other if else condition.

Related

How do I output a message using JFrame depending on whether data is incorrect or correct?

I have used a boolean method to decide whether the data is correct or not. For some reason, even when the data is correct or not the data still shows up as incorrect. The boolean is underlined and states that the variable error is never used. When the report button is clicked it should check if the data is correct or not.
If the data is not correct it should show
Data problems
data errors here.
If the data is correct it should show
Medical Report
data here.
here is my code:
if (e.getSource()==reportButton )
{
int riskCounter =0;
boolean error = false;
String convert = ageField.getText();
if (error = true){
log.setText("Data problems \n============\n");
}
else
{
log.setText("Medical Report \n============\n");
}
try {
int age = Integer.parseInt(convert);
if (age < 0 || age > 116)
{
log.append("Age can only be between 0 and 116!\n");
error = true;
}
else if (age > 70)
{
riskCounter++;
error = false;
}
else
{
error = false;
log.append("Age: " + age + "\n");
}
}
catch (NumberFormatException r)
{
log.append("Integers only for Age!\n");
error = true;
}
String smoke = smokesField.getText();
if (smoke.equalsIgnoreCase("y"))
{
error = false;
log.append("Smokes: "+smoke +"\n");
riskCounter++;
}
else if (smoke.equalsIgnoreCase("n"))
{
log.append("Smokes: "+smoke +"\n");
error = false;
}
else
{
error = true;
log.append("Smokes must be one of 'y', 'Y','n','N'\n");
}
String overweight = overweightField.getText();
if (overweight.equalsIgnoreCase("y"))
{
log.append(overweight +"\n");
error = false;
riskCounter++;
}
else if (overweight.equalsIgnoreCase("n"))
{
error = false;
log.append("Overweight: "+ overweight +"\n");
}
else
{
log.append("Overweight must be one of 'y', 'Y','n','N'\n");
}
if (riskCounter <=0)
{
log.append("Low Risk");
}
else if (riskCounter >0 && riskCounter <2)
{
log.append("Medium Risk");
}
else if (riskCounter >=2 && riskCounter <3)
{
log.append("High Risk");
}
else if (riskCounter >=3)
{
log.append("Very High Risk");
}
}
I needed to compare the boolean. To check if the error is true:
if (error){
log.setText("Data problems \n============\n");
}

Java registration simple checker

I have a simple password and text area checker for a registration page. Here all the text area MUST be filled, otherwise a popup JOptionPane. AND the password and the re-entered password (confirm password) should be equal otherwise warning.
I don't know how to do this.
Code:
private boolean check() {
boolean isEmpty=false;
if(nickNametxt.getText().equals("") || pwdTxt.getText().equals("") ||
logintxt.getText().equals("") || rePwdTxt.getText().equals("")){
JOptionPane.showMessageDialog(null, "Please fill all the fields before proceeding");
if (pwdTxt != rePwdTxt){
JOptionPane.showMessageDialog(null, "Wrong Password");
}
isEmpty = true ;
}
return isEmpty ;
}
Try with the following code snippet. The second if condition has been modified from != to .equals as != will verify object reference.
private boolean check(){
boolean isEmpty = false;
String nickName = nickNametxt.getText();
String login = logintxt.getText();
String pwd = pwdTxt.getText();
String rePwd = nickNametxt.getText();
isEmpty = true;
if(!((null != nickName && !nickName.isEmpty()) && (null != login && !login.isEmpty())
&& (null != pwd && !pwd.isEmpty()) && (null != rePwd && !rePwd.isEmpty()))){
JOptionPane.showMessageDialog(null, "Please fill all the fields before proceeding");
isEmpty = true;
}else if(!pwd.equals(rePwd)){
JOptionPane.showMessageDialog(null, "Wrong Password");
//Depending on your usecase - place it here or not
//isEmpty = true;
}
return isEmpty;
}

stopping code at a certain point in a method

I'm making a program for school which inserts contacts into an array lists using JOptionPane/Dialog boxes for input/output.
The problem I'm having is with the Cancel and "X" buttons : when pressed by the user they crash the program.
I figured out using "return" I could stop the method, and that worked for the first dialog box but if information is entered and the user proceeds to the next Dialog box it crashes even though i'm using return again.
So basically what I want to do is if the user presses cancel or "X" to escape the current method it will do so without crashing and return to the main method to carry out other processes.
This code works for the first entry and exits the program successfully:
while(nameError)
{
surname = JOptionPane.showInputDialog(null, "Enter a Surname");
if(surname == null)
{
return;
}
else
{
if(!(surname.matches(NamesTest)))
{
JOptionPane.showMessageDialog(null,errorMsg);
}
else nameError = false;
temp[0] = surname;
}
}
but the next line of code in the method for the second Dialog box doesnt:
while(nameError1)
{
if(forename == null)
{
return;
}
else
{
forename = JOptionPane.showInputDialog(null, "Enter a Forename");
if(!(forename.matches(NamesTest)))
{
JOptionPane.showMessageDialog(null,errorMsg);
}
else nameError1 = false;
temp[1] = forename;
}
}
Something like this should do it:
import javax.swing.JOptionPane;
public class DialogExample {
public static void main(String[] args) {
new DialogExample().getNames();
}
private void getNames() {
String firstName = null;
String lastName = null;
while (firstName == null || firstName.length() == 0) {
firstName = getFirstName();
}
while (lastName == null || lastName.length() == 0) {
lastName = getLastName();
}
JOptionPane.showMessageDialog(null, "Hello " + firstName + " " + lastName);
}
private String getFirstName() {
String rtn = JOptionPane.showInputDialog(null, "Enter First Name");
if(rtn == null || rtn.length() == 0) {
JOptionPane.showMessageDialog(null, "Name cannot be empty");
}
return rtn;
}
private String getLastName() {
String rtn = JOptionPane.showInputDialog(null, "Enter Last Name");
if(rtn == null || rtn.length() == 0) {
JOptionPane.showMessageDialog(null, "Name cannot be empty");
}
return rtn;
}
}

Checking if an IPv4 address is valid

I am trying to write a basic program in Java that checks if an IP address is valid. I am trying to use no external classes other than the Scanner class and also no regular expressions.
My code, available at this gisttakes in 4 integers as input, one for each octet. I also have this codewhich is a little more readable than the first but is longer.
My question is, is there any other way to implement this idea in significantly fewer lines, and if so, how would I accomplish this?
While this code segment is a bit verbose, it is simple, self-descriptive, and has proven to be tight.
private static boolean isIPAddressValid(String ip) {
boolean result = true;
int i = 0;
int [] val = new int[4];
if ((ip == null) || (ip.trim().length() == 0))
{
//null ip address entered
result = false;
}
else
{
if (!(ip.contains(".")))
{
//no '.' found
result = false;
}
else
{
String [] parts = ip.split("\\.");
if (!(parts.length == 4))
{
//not 4 quadrants
result = false;
}
else
{
for (String s : parts) {
try {
val[i] = Integer.parseInt(s);
if ((val[i] < 0) || (val[i] > 255))
{
//this quadrant's value exceeds limits
result = false;
}
i++;
} catch (Exception e) {
//failed to parse quadrant to an integer");
result = false;
}
}
}
}
}
return result;
}
only some minor enhancements (i think your code looks very good - my opinio so far) it is clearly to read and all work blocks are properly to understand....
boolean isFailed = false;
if (first < 0 || first > 255) {
System.out.println("Octet 1 is invalid");
isFailed = true;
}
if (second < 0 || second > 255) {
System.out.println("Octet 2 is invalid");
isFailed = true;
}
if (third < 0 || third > 255) {
System.out.println("Octet 3 is invalid");
isFailed = true;
}
if (fourth < 0 || fourth > 255) {
System.out.println("Octet 4 is invalid");
isFailed = true;
}
if (!isFailed){
System.out.println("IP Address: " + first + "." + second + "." + third + "." + fourth);
}
so i simply invert the order of printing - that saves you only that big check before...
your approach was to can check each octet...
you can simply do this 4 times or write a method for it:
private static boolean check(int octet, int index){
if (0xFF & octet < 256) return true;
System.out.println("Octet "+index+" is invalid";
return false;
}
and use this method in your main method
if (check(first,0) && check (second, 2) && check (third, 3) && check(fourth, 4) ){
System.out.println("your ip is valid");
}
note - this only reveals the first invalid octet - if you want to check all you need another boolean
boolean result = check(first,0) &&
check (second, 2) &&
check (third, 3) &&
check(fourth, 4); //reveals all errors
a totally different approach would be to use http://docs.oracle.com/javase/7/docs/api/java/net/InetAddress.html#getByName%28java.lang.String%29
try{
/*InetAdress adress =*/ InetAdress.
getByName(""+first+"."+second+"."+third+"."+forth)
System.out.println("your ip is valid");
}catch (UnknownHostException e){
//TODO represent that error message into a nice expression
System.out.println("your ip is invalid");
}
but this as well doesn't provide information about that octet which is invalid...
(by the way - what is wrong with your code? it's fine, really!)
I was just bored and wrote this regexp
public static boolean isValid(String ip) {
boolean isvalid;
isvalid = ip.matches(
"(([0-9]|[0-9]{0,2}|1[0-9]*{0,2}|2[0-5][0-5]|0{0,3}).){3}" +
"([0-9]|[0-9]{0,2}|1[0-9]*{0,2}|2[0-5][0-5]|0{0,3})"
);
return isvalid;
}
And it was tested on the following dataset:
String[] ips = {
"0.0.0.0",
"0.111.222.0",
"0.0.0.000",
"0.00.0.000",
"1.1.1.1",
"2.2.2.2",
"12.13.14.15",
"29.29.29.29",
"99.99.000.1",
"111.102.144.190",
"255.255.199.199",
"266.255.255.255", //inv
"255.265.255.255", //inv
"255.255.258.255", //inv
"255.255.255.259", //inv
"299.100.110.255" //inv
};
for (String s : ips) {
if (isValid(s) == false) {
System.err.println(s + " is invalid");
}
}

Get input from button and validate if its correct or wrong

I'm creating an ATM machine with pin function. The problem is I want to get the input from the button when its pressed by the user and validate if its correct or wrong. When the button is pressed, it will store the result in the string. It will then be used to validate if its correct or wrong. For example: User A pressed 012345. Each number will then be stored to another string for validation. The string is then compared to the pin.
public class atmMachine:
int numberPinButton = 10;
String pin = "012345";
String zero, one, two, three, four, five, six, seven, eight, nine;
public atmMachine:
panel = new JPanel();
pinButton = new JButton[numberPinButton];
for(int i = 0; i < numberPinButton; i++) {
pinButton[i] = new JButton("" + i);
pinButton[i].addActionListener(this);
panel.add(pinButton[i]);
}
enterButton = new JButton("Enter");
enterButton.addActionListener(this);
panel.add(enterBtn);
panel.setBorder(BorderFactory.createTitledBorder("Enter your pin:"));
add(panel, BorderLayout.WEST);
public void actionPerformed:
public void actionPerformed(ActionEvent event) {
if(event.getSource() == pinButton[0]) {
zero = "0";
} else if(e.getSource() == pinButton[1]) {
one = "1";
} else if(e.getSource() == pinButton[2]) {
two = "2";
} else if(e.getSource() == pinButton[3]) {
three = "3";
} else if(e.getSource() == pinButton[4]) {
four = "4";;
} else if(e.getSource() == pinButton[5]) {
five = "5";
} else if(e.getSource() == pinButton[6]) {
six = "6";
} else if(e.getSource() == pinButton[7]) {
seven = "7";
} else if(e.getSource() == pinButton[8]) {
eight = "8";
} else if(e.getSource() == pinButton[9]) {
nine = "9";
}
if(e.getSource() == enterBtn) {
if(???.equals(pin)) {
System.out.println("Correct");
} else {
System.out.println("Wrong");
}
}
}
Have an instance variable-
StringBuffer userKeyString = new StringBuffer();
On action performed, append any digit button pressed-
userKeyString.append(event.getActionCommand());
On action performed, if enter pressed-
if(event.getSource() == enterBtn){
if(pin.equals(userKeyString.toString()){
// Correct pin
} else {
// Incorrect pin
}
userKeyString.setLength(0); // Clear the buffer for next input and validation
} else {
userKeyString.append(event.getActionCommand());
}
You should set the action commands of your buttons-
for(int i = 0; i < numberPinButton; i++) {
pinButton[i] = new JButton("" + i);
pinButton[i].setActionCommand(String.valueOf(i));
pinButton[i].addActionListener(this);
panel.add(pinButton[i]);
}
You can declare String pin as a field like:
String pin;
then in action performed you append to it (pseudo code)
actionPerformed(...){
pin += keyPressed;
if(pin.length > 5){
validatePin(pin);
}
}
Does this answer your question?
But to be honest I would suggest against validation in the action performed method. I'd try to validate the pin after all the numbers were inserted. This way you can save a bit on performance and the code would be more readable. The performance isn't an issue here but it's a good practice as you would check the pin 6 times here instead of just once outside the actionPerformed method.
Like:
for(int i = 0; i < pinLength; i++){
waitForUserToPressButtonOrTimeout();
appendToCurrentPin();
}
validatePin();
Or let the user simply press another button after entering the pin code and link validation to that button. But I think using String pin field and appending to it is an answer to your question.

Categories

Resources