DEV Community

Discussion on: School project

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

Hi Ted,

Welcome to C++, and to dev.to!

Here's some thoughts for you. I'll refer to line numbers in your code. Assume // looped calculator is on line 1.

1) You don't need an empty #include line. That's only needed if you're actually including some other file, such as a header. However, I suspect you actually meant that to be #include <iostream>, yeah?

2) I get twitchity every time I see this much code in int main(). I highly recommend breaking this up into functions. For example, you might have one function for displaying instructions, one for prompting the user and getting their input, and one for the actual calculation.

The reason we do this is to make the code easier to read and maintain. int main() should only handle the main execution flow (e.g. the program loop) and calling the other functions.

3) The other reason you need functions is to make the code DRY (Don't Repeat Yourself). See how you have the same code on 33-68 and 77-114? That's a maintenance nightmare, because any change you make to the code must be replicated in more than one place!

Now, if any bit of code is only a couple of lines long, and only appears 2-4 times, you generally shouldn't worry about breaking it off into a separate function. (There is such a thing as DRY spaghetti.) Use discernment. Still, something as complex as your calculation switch statement should absolutely be abstracted out to a function.

4) cin::get() is pain. Consider using getline instead; it doesn't involve any of the clear() or ignore() madness. (See the documentation)

Collapse
 
larssonted profile image
Ted Larsson

Yes I thought there might be ways to clean it up a bit. I handed it in as it is and I got an A on it so I'm happy. But I would like to learn to do clean coding since I plan to do coding for a living in the future, would you put the functions in a separate header or above main or under main?

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

C++, like its predecessor C, is a "top-down" language, so you have to declare a function before you use it. However, as you may know, you have two options.

You could declare the entire function above where it's used...

#include <iostream>

int foo(int l, int r) {
    return l+r;
}

int main() {
    std::cout << add(1, 2) << std::endl;
}

...or, use function prototypes...

#include <iostream>

int foo(int, int); //pre-declare the function here

int main() {
    std::cout << add(1, 2) << std::endl;
}

// implement the function here...
int foo(int l, int r) { 
    return l+r;
}

Which you use is entirely a matter of style and preference. In practice, prototyping is (for me, at least) a bit easier to keep track of, as you don't have to care which functions call which. You can prototype all (but main), and then use them at will. However, the downside to this is that if you change the function's name, argument types, or return types, you have to change it in two places, not just one. (Of course, if you forget, you'll merely get a compiler error.)

You could also move them to separate headers or classes. This can certainly make large code cleaner, but with something this small, it would merely make it spaghetti. There's no hard-and-fast rule for whether code should go in main.cpp or another header, but I think there are a few good guidelines that usually work:

  1. If your function is only used in one file, then it should live in that one file. Don't split things up unnecessarily.

  2. A single header should have one primary purpose. If you were building a more feature-full, production-ready calculator, you would NOT put your user-input functions in the same header as your actual math calculation functions.

  3. Don't get classes involved unless you actually have a need for objects (see Object-Oriented Programming). It's tempting to turn every header file, or header/implementation file pair, into a class. Don't. If the functions don't need their own private data stored between calls, you don't need a class/object.

As you can tell, those guidelines can actually feel contradictory at times. After you've been coding for a while, you'll start to develop an instinct about it (what we call "code smell"). When it's wrong, you'll just sense that it's wrong. (Seriously...it's weird, but it works.)