Section12.14Case Study: Building a Multi-File Program - Part 3
Once all of the functions other than main have been built and tested, we can switch our focus back to finalizing the βrealβ program. Like any function the main function should be a reasonable length. It will be responsible for multiple jobs in that all of the work of the program starts from it. But it should not be directly responsible for any complex work. Ideally, that work is already contained in other functions that will serve as abstractions in main.
#include <iostream>
import DateFunctions;
using namespace std;
int main() {
string startDate;
cout << "Enter a start date in the format MM/DD/YYYY: ";
cin >> startDate;
//Echo input since activecode does not show it
cout << endl << "You entered: " << startDate << endl;
string endDate;
cout << "Enter an end date in the format MM/DD/YYYY: ";
cin >> endDate;
//Echo input since activecode does not show it
cout << endl << "You entered: " << endDate << endl;
try {
int startDayCount = dateToDays(startDate);
int endDayCount = dateToDays(endDate);
int daysBetween = endDayCount - startDayCount;
cout << "The number of days between the two dates is: "
<< daysBetween << endl;
} catch (const logic_error& e) {
cout << "There was an error: " << e.what() << endl;
cout << "Please try running the program again." << endl;
}
}
There is some repetition in the way we handle the inputs. So we could refactor the input code into a function getInput that takes a prompt string as an argument and returns the string entered by the user. That function is not really a βdateβ function, so it probably does not belong in the library. Instead, we can put it in the main file. (It also will be hard to unit test since it gets input from stdin).
Remember that sometimes we write functions mainly as an abstraction. Other times, the main purpose is to reuse a block of code without writing multiple copies of it.
The initial design process usually focuses more on building the abstractions. All of the opportunities to avoid code duplication may not become apparent until we start implementing the code.
If you look at the final implementation of getMonth, getDay, and getYear, you will see that they presented another opportunity to add a function to avoid repeating code. They all need to verify that the string they are focused on is all digits. Rather than write the same "loop through each character and verify that it is a digit" logic three times, that logic has been moved to a function.
The updated main.cpp will then look like the code below. It needs to be compiled with our library that has the date functions. The full version of that file can be found in SectionΒ 12.15.