Search

2.5 — Why functions are useful, and how to use them effectively

Now that we’ve covered what functions are and some of their basic capabilities, let’s take a closer look at why they’re useful.

Why use functions?

New programmers often ask, “Can’t we just put all the code inside the main function?” For simple programs, you absolutely can. However, functions provide a number of benefits that make them extremely useful in programs of non-trivial length or complexity.

  • Organization -- As programs grow in complexity, having all the code live inside the main() function becomes increasingly complicated. A function is almost like a mini-program that we can write separately from the main program, without having to think about the rest of the program while we write it. This allows us to reduce a complicated program into smaller, more manageable chunks, which reduces the overall complexity of our program.
  • Reusability -- Once a function is written, it can be called multiple times from within the program. This avoids duplicated code (“Don’t Repeat Yourself”) and minimizes the probability of copy/paste errors. Functions can also be shared with other programs, reducing the amount of code that has to be written from scratch (and retested) each time.
  • Testing -- Because functions reduce code redundancy, there’s less code to test in the first place. Also because functions are self-contained, once we’ve tested a function to ensure it works, we don’t need to test it again unless we change it. This reduces the amount of code we have to test at one time, making it much easier to find bugs (or avoid them in the first place).
  • Extensibility -- When we need to extend our program to handle a case it didn’t handle before, functions allow us to make the change in one place and have that change take effect every time the function is called.
  • Abstraction -- In order to use a function, you only need to know its name, inputs, outputs, and where it lives. You don’t need to know how it works, or what other code it’s dependent upon to use it. This lowers the amount of knowledge required to use other people’s code (including everything in the standard library).

Although it doesn’t look like it, every time you use operator<< or operator>> to do input or output, you’re using a function provided by the standard library that meets all of the above criteria.

Effectively using functions

One of the biggest challenges new programmers encounter (besides learning the language) is understanding when and how to use functions effectively. Here are a few basic guidelines for writing functions:

  • Statements that appear more than once in a program should generally be made into a function. For example, if we’re reading input from the user multiple times in the same way, that’s a great candidate for a function. If we output something in the same way multiple times, that’s also a great candidate for a function.
  • Code that has a well-defined set of inputs and outputs is a good candidate for a function, particularly if it is complicated. For example, if we have a list of items that we want to sort, the code to do the sorting would make a great function, even if it’s only done once. The input is the unsorted list, and the output is the sorted list.
  • A function should generally perform one (and only one) task.
  • When a function becomes too long, too complicated, or hard to understand, it can be split into multiple sub-functions. This is called refactoring. We talk more about refactoring in lesson 3.10 -- Finding issues before they become problems.

Typically, when learning C++, you will write a lot of programs that involve 3 subtasks:

  1. Reading inputs from the user
  2. Calculating a value from the inputs
  3. Printing the calculated value

For trivial programs (e.g. less than 20 lines of code), some or all of these can be done in function main. However, for longer programs (or just for practice) each of these is a good candidate for an individual function.

New programmers often combine calculating a value and printing the calculated value into a single function. However, this violates the “one task” rule of thumb for functions. A function that calculates a value should return the value to the caller and let the caller decide what to do with the calculated value (such as call another function to print the value).


2.6 -- Forward declarations and definitions
Index
2.4 -- Introduction to local scope

69 comments to 2.5 — Why functions are useful, and how to use them effectively

  • [C++]
    #include iostream

    int main(){
       std::cout << "Hello world" << std::endl;
    }

    [/C++]

  • RHOULAN DHAMAR WANTO

    please help Alex
    please help me with this

    (Equilateral Triangle validation and perimeter) Implement the following two
    functions:
    // Returns true if all the sides of the triangle
    // are same.
    bool isValid(double side1, double side2, double side3)
    // Returns the perimeter of an equilateral triangle.
    double perimeter(double side1)
    The formula for computing the perimeter is perimeter = 3 * side. Write a
    test program that reads three sides for a triangle and computes the perimeter if the
    input is valid. Otherwise, display that the input is invalid.

    • Anon

      #include <iostream>

      bool isValid(double side1, double side2, double side3)
      {
            //if side1 == side2 then they have the same length, and if side2 and side 3 have the same length,
            //it follows that side1 == side2 == side3 and therefore it is equilateral
            return (side1 == side2) && (side2 == side3);
      }

      double perimeter(double side1)
      {
            return side1 * 3;
      }

      int main()
      {
            //you could refactor a way to take the input for all 3 sides as a function
            std::cout << "Please enter side1 of your triangle:";
            double side1{};
            std::cin >> side1;
            std::cout << "Please enter side2 of your triangle:";
            double side2{};
            std::cin >> side2;
            std::cout << "Please enter side3 of your triangle:";
            double side3{};
            std::cin >> side3;
            if (isValid(side1, side2, side3))
            {
                std::cout << "The perimeter of an equilateral triangle with side length " << side1 << " is " << perimeter(side1) << ".";
            } else
            {
                std::cout << "The triangle is not equilateral.";
            }
            return 0;
      }

Leave a Comment

Put all code inside code tags: [code]your code here[/code]