简体   繁体   中英

Format multiple if-else statements into methods

I have a program that checks for user date input and displays the output of the next date. However, I am using multiple if-else statements for the program.

I would like to alter it so that it will use methods to do the calculation instead of the repeated codes.

Below is an example of my code, take March and April for an example, one with 30 days, one with 31 days:

public class calDate{

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        boolean dateValid = false;
        int day = 0;
        int month = 0;
        int year = 0;
        int nextDay = 0
        int nextYear = 0;
        String nextMonth = "";
        boolean run=true;
        char again='Y';

while(run)
        {

        System.out.print("Day: ");
        day = scan.nextInt();

        System.out.print("Month: ");
        month = scan.nextInt();

        System.out.print("Year: ");
        year = scan.nextInt();

while (month < 1 && month > 12) //check if month is within 1 to 12
        { 
            dateValid = false;
        }

if ((month == 3) && (day >= 1 && day <= 31)) 
        {
            dateValid = true;
            nextDay = day + 1;
            nextMonth = " March ";
            nextYear = year;

            if (day == 31) {
                nextDay = 1;
                nextMonth = " April ";
                nextYear = year;
            }
        } 

        else if ((month == 4) && (day >= 1 && day <= 30)) 
        {
            dateValid = true;
            nextDay = day + 1;
            nextMonth = " April ";
            nextYear = year;

            if (day == 30) 
            {
                nextDay = 1;
                nextMonth = " May ";
                nextYear = year;
            }  
        }
if (dateValid){
        System.out.println("Tomorrow's date: " + nextDay + nextMonth + nextYear);
        System.out.print("Continue?(Y/N)  ");
        again = scan.next().charAt(0);
        if (again=='Y')
        {
        run=true;
        System.out.println("");
        }
        if (again=='N')
        {
        run=false;
        }
        if ((again != 'N')&&(again!='Y'))
        {
        System.out.println("Invalid input. Ending program."); 
            run=false;
        }   
        }

        else{
        System.out.println("Invalid input. Continue?(Y/N)  ");
        again = scan.next().charAt(0);
        if (again=='Y')
        {
        run=true;
        System.out.println("");
        }
        if (again=='N')
        {
        run=false;
        }
        if ((again != 'N')&&(again!='Y'))
        {
        System.out.println("Invalid input. Ending program.");
        run=false;
        }
    }
   }

There are many repeated values, such as dateValid , nextDay , nextMonth , nextYear . How may I format my code so that I can put the statements into separate methods? Thank you.

My first suggestion would be to turn the months into an enum. That way you can encapsulate inside one class all the logic associated with months:

enum Month {
    JAN ("Jan", 31),
    FEB ("Feb", 28), 
    ....
    DEC ("Dec", 31);

    private final String monthName;
    private final int daysInMonth;

    private Month(String monthName, int daysInMonth) {
        this.monthName = monthName;
        this.daysInMonth = daysInMonth;
    }

    public String getName() {
        return monthName;
    }

    public static Month monthWithNumber(int monthNumber) {
        if (monthNumber < 1 || monthNumber > 12) 
            throw new IllegalArgumentException();
        return values()[monthNumber - 1];
    }

    public isLegalDay(int day) {
        return day > 0 && day <= daysInMonth;
    }

    public isLastDayInMonth(int day) {
        return day == daysInMonth;
    }

    public Month nextMonth() {
        return values[(ordinal() + 1) % 12];
    }
}

That immediately removes most of your if statements and replaces them with:

Month month = Month.monthWithNumber(monthNumber);
if (month.isLegalDay(dayNumber)) {
    ....
    if (month.isLastDayInMonth(dayNumber)) {
        nextMonth = month.nextMonth().getName();
        nextDay = 0;
    }
}

I recommend that you build a String with the given input values, parse the resulting String with a SimpleDateFormat and then catch the ParseException to update your dateValid boolean.

This will also allow you to add a single day more easily too.

I suggest you use arrays like int[] daysInTheMonth = { 31. 28, ... and String[] monthName = ",Jan,Feb,Mar".split(","); Using data in your code will make it much shorter than it is now even if you handle all months.

It would be useful to include an isLeapYear(year) method.

For testing purposes I suggest you make sure you get the same results as the JSR-310 library. While I assume you can't use this library directly, you can use it to test your code is correct.

I would probably create methods getNextDay() , getMonthForNextDay() and getYearForNextDay() . They would get the user inputs as parameters and simply return the correct day, month and year, respectively. You could also combine that with Peter Lawreys answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM