Skip to main content

Section 12.8 Bottom-Up Design

The other major strategy for program design is bottom-up. This method involves starting with the lowest-level functions, which handle simple, specific tasks, and then combining them to form higher-level functions. We of course still need some understanding of the problem we are trying to solve, but we do not start out by trying to solve that entire problem at once.
This can be a useful approach when we do not perfectly understand a problem, or we don’t see a clear path to a solution. In these cases, it can be easier to identify simple, concrete tasks that will need to happen than to reason about larger, more abstract parts of the problem. The hope is that as we design (or even build) the functions for low-level tasks, we will identify ideas for higher-level functions that combine those basic tasks.
The downside of bottom-up design is that it is less goal directed: instead of starting from the exact high-level behavior we want, we are trying to piece together the solution from the ground up. While doing that, we are more likely to design functions that do not fit well together or end up being totally unnecessary.

Example 12.8.1. A Bottom-Up Design.

A bottom-up design for our date program would start by trying to identify small bits of work that we think will need to get done. Maybe we don’t initially think of turning each date into a number of days since 0/0/0. But we do realize that we will need to break a string like "3/4/2023" into its component parts. So we might start with:
  • β˜… Get the month as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the month (3 in this case). int getMonth(string date)
  • β˜… Get the day as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the day (4 in this case). int getDay(string date)
  • β˜… Get the year as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the year (2023 in this case). int getYear(string date)
Once we have those functions, we maybe get a sense of what we could do with them. It feels pretty clear that we are going to need to figure out how many days are in a given month. So we might add a function to handle that:
  • Get the month as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the month (3 in this case). int getMonth(string date)
  • Get the day as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the day (4 in this case). int getDay(string date)
  • Get the year as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the year (2023 in this case). int getYear(string date)
  • β˜… Get the number of days in the given month. Inputs: an integer month; Output: an integer representing the number of days in the given month. int daysInMonth(int month)
Then, maybe we realize it would be good to combine the month/day into a single total number of days. So 1/3 would be 3 days, 2/1 would be 32 days (31 for January plus one in February), etc... That might lead us to adding a totalDays function that takes the month and day. It is seems like that function will rely on daysInMonth, so we will consider that older function a building block for the new function:
  • Get the month as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the month (3 in this case). int getMonth(string date)
  • Get the day as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the day (4 in this case). int getDay(string date)
  • Get the year as an integer. Inputs: a string like "3/4/2023"; Output: an integer representing the year (2023 in this case). int getYear(string date)
  • β˜… Get the total number of days represented by a given month/day combo. Inputs: an integer month, an integer day; Output: an integer representing the total number of days. int totalDays(int month, int day)
    • Get the number of days in the given month. Inputs: an integer month; Output: an integer representing the number of days in the given month. int daysInMonth(int month)
At this point we will stop the process. Another step might mix the year value in with the total from the month/day. And eventually we would need to get the user input.

Insight 12.8.2.

The benefit and challenge of bottom up design both stem from starting from the details. We need less big-picture understanding to make progress, but because of that we are more likely to build functions that do not end up being useful in the final program.
You can see that our first steps did not require fully understanding the problem. We just needed to identify some bit of work that needed to be done.
However, because we were looking for easy building blocks, we ended up taking an indirect route to where we needed to go. The daysInMonth function can be used to help build the program, but it might not be strictly necessary.

Checkpoint 12.8.1.

You have attempted of activities on this page.