tags:

views:

43

answers:

5

I'm writing a console based program for my coursework, and am wondering how best to structure it so that it is both stable and efficient. I currently have

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    int choice;
    do
    {
        cout << "\E[H\E[2J" // Clear the console
                   << "Main menu" << endl << endl
                   << "Please select one of the following options by entering it's "
                   << "number in the prompt below and pressing [ENTER]. "
                  << endl << endl
                  << "1. Pay my bill as a guest" << endl
                  << "3. Log in" << endl
                  << "2. Create an account" << endl
                  << "4. Quit program" << endl;

     cin >> choice;
    switch (choice)
    {
        case 1: // Pay the bill as a guest to the system

        case 2: // Log in to the system

        case 3: // Create an account with the system

        case 4: // Quit the program

        default: // Prompt the user to choose again
    }
} while !(default);

// Await user input to terminate the program
cout << "Please press [ENTER] to continue...";
cin.get();
return 0;
}

The purpose of the above code is to provide a list of options for the user to choose from, with the do-while loop working alongside the default statement in the switch to catch any unexpected input. Each case would call a function that presented another menu with it's own list of options, which would be structured using the same do-while, switch method. My concern is that as my program grows, the number of function calls being nested within other functions is going to increase, so that I would eventually end up with a function being called from within a function being called from within a function and so on. This would obviously have severe implications for the maintainability of the program, with the function calls moving further and further away from main(), and the output of these functions weaving a tangled path about the program.

Question: Is it possible to structure my program in such a way as to return execution to main() as often as possible, or is the problem described above simply a consequence of this kind of programming?

NB: I ask this question in the understanding that user-defined functions are supposed to be ancillary to main(), and that they should perform a task before returning control to main() as the earliest possible convenience. I've only been at this a couple of months now so please bear with my ignorance/misunderstanding. Also, ignore any potential compiler errors in the code, I've not tested it yet and it's only provided as an aide to my conceptual question.

A: 

The complexity of the code will correlate to the functionality offered by the program. I would not worry about this right now, revisit refactoring once you have two or three hundred lines.

+1  A: 

There is nothing particularly wrong with what you've done.

I don't see why it harms maintainability to have functions called from functions and so on. If anything it AIDS maintainability as you can move common code operations into seperate functions. This way you make a fix in one place and instantly fix the rest of the places its used as well.

Goz
A: 

Well, you can implement your menu structure as a state-machine, so you will be almost always in your main loop. But this can bring your code to the lower level, because you will be effectively programming not in C++ but in your state-machine processor-near code. If your state machine will be good enough, this is not a problem.

Or you can a simple menu-runner class, which will output as a result a request for submenu, so you will just exchange (perhaps using a stack) the description of the currently running menu.

By the way, I don't see any problems in deep nesting of the functions.

Vlad
+1  A: 

Another possible approach is to make a class defined as a list of (menu_option, function) pairs and the know-how to turn them into menus. Then the function can be a call to another class instance's menu or it can do some operation on your database. That lets you keep your data organized away from the business "how to display this menu" logic and add menus and menu items easily.

Don't worry about that or your current approach spending too much time away from main though. As you've structured it, your program won't automatically turn itself into a horrible mess just because you're calling functions from functions. More functions will tend to add to maintainability, as long as you keep them focused.

Think of it this way: a function does one thing, but at a higher level of abstraction than its body. So main() runs your program. create_account() will create an account, which is part of running the program. create_account itself calls several other things that do the building blocks necessary for creating an account. Is determining the new account's name one thing? It goes in its own function. Determining the index of the new account in the database? Too low-level. Put it in the "stuff it in the database" function.

Nathon
+1  A: 

I would apply some OO-design and create a menu-class which basically stores items/sub-menus in a vector. This would make it easy to extemd to hierarchical menus

S.C. Madsen