How to write
complex
computer programs
- The key
to developing
complex programs
is:
- Divide and
conquer
- Abstraction
of methods
|
- Abstraction of
a method:
- The
divide-and-conquer
strategy,
a.k.a.
stepwise refinement:
- You decompose a
problem into
smaller subproblems and
write methods
to solve each
subproblem
|
-
Key to
develop
programs to
solve
problems:
- Knowing
what
information
is needed to
solve the
problem
|
|
Program to print a calendar
- We will write a program that:
- Reads in
a year
and
- Reads in a
month
- Then
prints out the
calendar for
that month of that year
|
Example:
Enter year (e.g., 2001): 2023
Enter month in number between 1 and 12: 2
Output:
February 2023
-----------------------------
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28
|
|
Start constructing an high-level
program from the description
- A
high-level
program
is a computer program
with
very little
details
- From the description,
we know the
program must
perform these
actions:
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
// (1) Prompt the user to enter the year
System.out.print("Enter year (e.g., 2001): ");
int year = input.nextInt();
// (2) Prompt the user to enter the month
System.out.print("Enter month in number between 1 and 12: ");
int month = input.nextInt();
// (3) Print calendar for the month of the year
printMonth(year, month); // This method must print the calender
// for the monthof the year
}
public static void printMonth(int year, int month)
{
// We need to work this out....
}
|
|
DEMO:
demo/06-methods/08-stepwise-refinement/Demo.java
Flesh out
the incomplete
methods:
what does it take to print a
calendar month ?
DEMO:
write
dummy
methods for
printMonthTitle( ) and
printMonthBody( )
Flesh out
the incomplete
methods:
what does it take to print a
month title ?
DEMO:
test
functionality using
a
dummy
getMonthName(month)
Flesh out
the incomplete
methods:
what does it take to translate
month number to
month name ?
- We then flesh out the
getMonthName( month )
method:
public static String getMonthName(int month)
{
String monthName = "";
switch (month)
{
case 1: monthName = "January"; break;
case 2: monthName = "February"; break;
case 3: monthName = "March"; break;
case 4: monthName = "April"; break;
case 5: monthName = "May"; break;
case 6: monthName = "June"; break;
case 7: monthName = "July"; break;
case 8: monthName = "August"; break;
case 9: monthName = "September"; break;
case 10: monthName = "October"; break;
case 11: monthName = "November"; break;
case 12: monthName = "December"; break;
}
return monthName;
}
|
|
DEMO:
test
functionality using
different
year and
month
Flesh out
the incomplete
methods:
what does it take to print
a month body ?
- Next, we
flesh out
the
printMonthBody( )
method:
printMonthBody(2023, 2):
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28
printMonthBody(2018, 5):
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
|
- We need to figure out:
-
How to
accomplish this
task ?
(
Hint:
what
information do
you need ?)
|
|
Flesh out
the incomplete
methods:
what does it take to print
a month body ?
- The
information that we
need in order to
write
printMonthBody(year, month)
are:
Days: 0 1 2 3 4 5 6
1 2 3 4 (1) startDay = 3
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 (2) numberOfDaysInMonth = 28
1 2 3 4 5 (1) startDay = 2
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 (2) numberOfDaysInMonth = 31
|
-
Suppose
we know
the startDay and
the numberOfDays:
- How
can we write the
printMonthBody(year, month)
method ?
|
|
Flesh out
the incomplete
methods:
what does it take to print
a month body ?
- How to
print a
month body:
If: (1) startDay = 3
(2) numberOfDaysInMonth = 28
Days: 0 1 2 3 4 5 6
1 2 3 4 (1) Print 3 "empty" days
5 6 7 8 9 10 11 (2) Print days 1 - 28
12 13 14 15 16 17 18
19 20 21 22 23 24 25 Note: start a new line
26 27 28 after printing 7 days
If: (1) startDay = 2
(2) numberOfDaysInMonth = 31
Days: 0 1 2 3 4 5 6
1 2 3 4 5 (1) Print 2 "empty" days
6 7 8 9 10 11 12 (2) Print days 1 - 31
13 14 15 16 17 18 19
20 21 22 23 24 25 26 Note: start a new line
27 28 29 30 31 after printing 7 days
|
|
Flesh out
the incomplete
methods:
what does it take to print
a month body ?
- The
printMonthBody(year, month)
method:
public static void printMonthBody(int year, int month)
{
int i, numDaysOnLine = 0;
int startDay = getStartDay(year, month);
int numberOfDaysInMonth = getNumberOfDaysInMonth(year, month);
// Print startDay number of "empty" days
for (i = 0; i < startDay; i++)
{
System.out.print(" "); // Use 4 spaces for an "empty" day
numDaysOnLine++; // Keep track of # days printed on current line
}
for (i = 1; i <= numberOfDaysInMonth; i++)
{
System.out.printf("%4d", i); // Print i in 4 spaces
numDaysOnLine++; // Keep track of # days printed on current line
if ( numDaysOnLine % 7 == 0 )// Use next line after 7 days
System.out.println();
}
System.out.println();
}
|
|
DEMO:
test
functionality using
dummy
getStartDay( ) and
getNumberOfDaysInMonth( )
Flesh out
the incomplete
methods:
how to find the
number of days in a
given month
- How to
find the
# days in
a month
(
numberOfDaysOnMonth(year, month)):
public static int getNumberOfDaysInMonth(int year, int month)
{
int numDays = 0;
switch (month)
{
case 1: numDays = 31; break;
case 2: numDays = isLeapYear(year) ? 29 : 28; break;
case 3: numDays = 31; break;
case 4: numDays = 30; break;
case 5: numDays = 31; break;
case 6: numDays = 30; break;
case 7: numDays = 31; break;
case 8: numDays = 31; break;
case 9: numDays = 30; break;
case 10: numDays = 31; break;
case 11: numDays = 30; break;
case 12: numDays = 31; break;
}
return numDays;
}
|
|
Flesh out
the incomplete
methods:
how to determine if a year
is a leap year
DEMO:
test
functionality using
dummy
getStartDay( )
Flesh out
the incomplete
methods:
how to find the
start day of a
month
- We
only need
find the
start day of
a month:
Days: 0 1 2 3 4 5 6
1 2 3 4 startDay = 3
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28
|
- In order to find
the
start day of
a month,
we need the following
information:
- The text book
chose
this
day:
January 1 1800 was a Wednesday
|
|
Flesh out
the incomplete
methods:
how to find the
start day of a
month
Flesh out
the incomplete
methods:
how to find the
start day of a
month
- We can write
getStartDay( )
as follows:
public static int getStartDay(int year, int month)
{
final int START_DAY_FOR_JAN_1_1800 = 3; // Jan 1 1800 is Wednesday
// Get total number of days from 1/1/1800 to month/1/year
int totalNumberOfDays = getTotalNumberOfDays(year, month);
// Return the start day for month/1/year
return (totalNumberOfDays + START_DAY_FOR_JAN_1_1800) % 7;
}
|
- The method
getTotalNumberOfDays(month, year)
will
find the
# days between:
Jan 1 1800 --- month 1, year
|
|
We will flesh out the
getTotalNumberOfDays(year, month)
next.
Flesh out
the incomplete
methods:
how to find the
start day of a
month
- We find the
total number of days
since
Jan 1, 1800 as
follows:
Calculation:
# days in the years # days in the months
Jan 1 1800 <--------------> Jan 1 year <------> Month 1 year
x y
public static int getTotalNumberOfDays(int year, int month)
{
int total = 0;
// Get the total # days from 1/1/1800 to 1/1/year
for (int i = 1800; i < year; i++)
if (isLeapYear(i))
total = total + 366; // Leap year
else
total = total + 365; // Normal year
// Get the total # days from Jan/1/year to month/1/year
for (int i = 1; i < month; i++)
total = total + getNumberOfDaysInMonth(year, i);
return total;
}
|
|
DEMO:
demo/06-methods/08-stepwise-refinement/Calendar.java
Advantages of the
divide-and-conquer
technique
- Divide-and-conquer
breaks up a large problem
into smaller
more manageable
subproblems.
- Each subproblem
can then be
implemented using a
method.
|
- Individual methods can be
tested
on its own
(shown in
BlueJ !)
- Methods that you
write during the
divide-and-conquer/stepwise refinement can
often be
re-used in the
problem solving process:
- The isLeapYear( )
method was used in:
-
getNumberOfDaysInMonth(int year, int month)
-
getTotalNumberOfDays(int year, int month)
|
|
- This way of write code
will often result in
clear and understandable
programs
- Better Facilitating Teamwork:
When a large problem is divided into subprograms,
subproblems can be assigned to different
programmers. This makes it easier for programmers to work in teams
|
❮
❯