Breaking Tasks Into Functions, Explained with Code Examples

UPI Study › Courses › C++ Programming › Free lessons › Lesson 8.8 Free with a free account

Breaking Tasks Into Functions

C++ Programming · Chapter 8: FunctionsSection 8.8 · lesson 58 of 84video coming soon

← Recursive CallsNext lesson: Bundling Related Fields With Structs →

Earn 3 college credits for C++ ProgrammingRecommended for credit by NCCRS · Computer Science 242 · self-paced · one payment, lifetime access

In this lesson

An applied challenge in decomposition.

  • Find the functions hidden in a specification
  • Test each for a single responsibility
  • Choose signatures; split across header and source files
  • Dispatch from a menu, and test functions on their own

Transcript

Everything said in the video, section by section (1,778 words). Read along, or search it.

Lesson Overview

Judgment Over New Syntax

No new syntax appears in this lesson. Everything needed has already been covered. What hasn't been covered is the judgment that turns one paragraph of requirements into a set of functions. Functions that each do one thing, can each be tested alone, and fit together, without knowing much about each other. That judgment is the whole subject here, and it's learned by working an example all the way through.

The Specification

A Marks Analyzer Brief

Here's the specification, exactly as it might arrive. A marks analyzer. Accept up to 50 marks, one at a time, finishing early when the user enters minus 1. Reject any entry outside 0 to 100, explain why, and ask again for the same position. Report the count, the average, the highest and the lowest. Grade each mark: A for 90 and above, B for 80, C for 70, D for 60, and F below that. Show how many marks fall in each band, with a bar. Let the user search for a mark. And present all of this as menu options, usable in any order, until the user quits. Notice how little it says about how anything should be organized.

Finding Functions

Underline Every Action in the Spec

The temptation is to start typing at requirement one, and stop at requirement seven. You'd get one enormous main, in which nothing can be tested separately. A better first move costs five minutes, and no typing. Underline every action in the specification. Each one is a candidate function, because a function is precisely a named action. Accept marks becomes read marks. Reject out-of-range values becomes is valid mark. Report the average becomes average of. Highest and lowest become two functions. Assign a letter becomes grade for. Count each band becomes tally grades. And search becomes position of. The menu isn't an action on data. It becomes the structure that calls the others.

One Responsibility

The One-Sentence Test Without And

Here's the test for whether a function is doing too much. Try to describe it in one sentence, without using and. Works out the average of a set of marks passes. Works out the average, and prints it, and warns if it's below 50, fails. That's three functions wearing one name. Two decisions are worth defending. Highest and lowest are two functions, not one. A single function would need somewhere to put two answers. And counting the bands doesn't repeat the grading rules. Tally grades calls grade for, so the grade boundaries exist in exactly one place.

Design Rule

Return Values or Print Output

Each function needs a decision that shapes everything downstream. Does it return a value, or produce output? The tempting answer, do both, is almost always wrong. A function that computes and returns can be used anywhere: printed, stored, compared, passed on, or tested. A function that computes and prints can only ever be used to print. It can't be tested without capturing its output, and the moment somebody needs the same number elsewhere, the calculation gets written a second time. So the calculating functions return, and say nothing. Print summary and print distribution display, and return nothing. No function appears in both groups. Read marks and read menu choice sit between the two, because obtaining input is inherently both. Keeping them few and small limits the awkwardness.

Signatures

Building the Header From Types

The remaining questions for each signature are mechanical. What must the function be given, and what type is its answer? Working through the list produces the header of the finished program. Two shared constants: the maximum number of marks, and the number of grade bands. Then a declaration for every function: what it's called, and how to call it. Average of returns a double, because an average of whole numbers is rarely whole. Grade for returns a char, because the answer genuinely is one letter. Position of returns an int, using minus 1 for absent, a value that can never be a real answer. The functions that only look at the marks take a const array, so they can't alter them. Every array is followed by a count, because an array carries no length into a function. And tally grades returns nothing: it has 5 answers, so it fills a caller-supplied array.

Call Graph

Drawing Which Function Calls Which

Before writing anything, draw which function calls which. Main calls the six functions in the middle column. Read marks calls is valid mark. Print summary calls average of, highest of and lowest of. And tally grades calls grade for. The five on the right call nothing, and depend on nothing, which is exactly what makes them easy to test. Arrows only ever point one way. No function needs to know about the one that called it. A picture with few arrows is a good design. One where everything points at everything is a warning.

File Layout

Splitting Into Three Files

Eleven functions plus main is more than belongs in one file. The conventional split uses three. Marks dot h holds the declarations and shared constants, with no bodies. It answers, what can I call, and how? Marks dot cpp holds the body of every declared function. It answers, how does each one work? That's of no interest to the caller. Main dot cpp holds main, the menu loop, and the data. It answers, what does this program do? Both source files include the header in quotation marks, which means look beside my file first. Each compiles alone, and the linker joins them. With a build tool, changing one function body recompiles only marks dot cpp.

Include Guards

Preventing Duplicate Header Definitions

A header pasted into a file twice defines everything in it twice, and duplicate definitions are an error. That happens more easily than it sounds: a file includes two headers, and one of them already includes the other. Here's the real message from including limits dot h twice. Clang names the redefinition, points at both include sites, and calls the header unguarded. An include guard prevents it in three lines. If not defined marks H, define marks H, then the declarations, then end if. The first time the header is pasted in, the marker doesn't exist yet, so it's defined, and the body is included. Every later time, the marker already exists, and the whole body is skipped. The marker must be unique across the whole program. The file's own name in capitals is the usual choice.

Main Program

A Short Menu Dispatch Loop

With every action written and tested, main becomes short enough to read at a glance. Each menu option does one thing: call a function. Choice 1 reads marks. Choice 2 prints the summary, unless no marks have been entered yet. Choice 3 tallies and prints the distribution. 4 searches, and 5 quits. Three things are worth copying into your own menus. The default case catches anything unexpected, instead of ignoring it. Quitting works by setting the loop's own condition, so there's exactly one way the loop ends. And the guards against an empty list live here, in the dispatch, rather than inside every calculation. That keeps those functions single-purpose.

Sample Run

Rejecting 120 and Searching Marks

Here's a real run. The user chooses 1 and enters marks, and at position 4 types 120. It's rejected, and the prompt returns to mark 4, rather than moving on. That works because read marks advances the count only when a value passes is valid mark. One line, working because validation is a separate function with one job. The summary reports 6 marks, an average of 75, a highest of 91, and a lowest of 55. The distribution shows a bar for each band. Searching for 79 finds position 3, counting from zero, and 99 is absent: minus 1.

Testing

A Second Main Runs Seven Checks

Here's the payoff for every decision so far. Because the calculating functions return values and print nothing, they can be checked without running the menu, without typing input, and without looking at any output by eye. Write a second main, in a file of its own, built instead of main dot cpp. It calls each function with known values, and compares the answer with what it should be. 100 is a valid mark. 101 is rejected. 90 is an A, and 89 is a B. 99 is absent from the sample. Seven of seven checks pass, and the exit code is zero.

Test Design

Choosing Values at the Edges

Choose test values at the boundaries. Testing that 75 gives a C proves almost nothing. Every plausible implementation gets the middle of a band right. What finds faults is the edges: 90 and 89, 60 and 59, 0 and 100, a list with one element, and a list with none. The pair grade for 90, and grade for 89, is precisely the off-by-one a wrong comparison operator would produce. And the test program returns a non-zero exit code when anything fails. That lets an automated system run it, and know whether the program is healthy, without a human reading the output.

Graded Exercise

Fuel Log Analyzer Assignment

Now the graded exercise: a fuel log analyzer. Apply the same process: decompose first, decide signatures, split across files, then write and test. Accept up to 100 entries, each the liters filled and the distance since the last fill, ending on a sentinel. Reject zero or negative values, and re-ask the same entry. Work out each entry's efficiency in kilometers per liter, and report the totals and the overall efficiency. Classify each entry as good, at 18 or more, fair, from 14 up to 18, or poor, below 14, with a bar for each band. And find the best and worst entries, from a menu. Submit three files with a correct include guard, a test file with at least 10 checks, four of them at boundaries, and a one-page note stating each function's responsibility.

Common Mistakes

Three Places Marks Get Lost

Marks are most often lost in three places. A function that calculates and prints. It can't be tested, and it costs marks in two criteria at once. Classification rules written twice, once when labeling an entry, and again when counting the bands. Call the labeling function from the counting one, as tally grades does. And tests that only use comfortable values. The interesting ones are 14 and 13.9, 18 and 17.9, a log with one entry, and a log with none.

Quick Check

Which Test Catches Greater-Than?

Quick check. Suppose gradeFor's A rule says mark > 90, instead of mark >= 90. Which test catches it: 75 is a C, 89 is a B, or 90 is an A? Pause and think. The check that 90 is an A. With greater-than, 90 drops to a B, so that check fails, while 75 and 89 still pass. That's why the tests sit on both sides of every boundary.

Key Takeaways

From Specification to Tested Functions

To summarize. Underline the actions in a specification. Each is a candidate function. Give each one a single responsibility, describable in one sentence without and. Calculations return values, and display functions print. Put declarations in a header with an include guard, and bodies in a source file. And test at the boundaries, with a non-zero exit code on failure.

About C++ Programming at UPI Study

C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. It carries a NCCRS credit recommendation for 3 semester credits.

Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Why take it here

Why students take C++ Programming with UPI Study

Your first real programming languageC++ teaches how programs really work: variables, control flow, functions, memory and objects. It is the base for data structures, algorithms, systems and game programming, and for most computer-science degrees.
Credit at a fraction of the priceThe same 3 credits can cost $750 or more at a US college. Here it is one payment, self-paced, with lifetime access.
Finish your degree soonerTransfer credits reduce the courses you still owe, so you can graduate earlier or lighten a heavy semester.
Strengthen an applicationA completed college-level course on an official transcript shows admissions and scholarship committees you can do the work.
Study on your own scheduleNo start dates, no deadlines. Watch the lessons, practice, and take the final when you are ready.
130,000+students helped with college creditsACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Where the credit goes

Universities that work with NCCRS

C++ Programming carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.

FAQ

Questions students ask us

About Breaking Tasks Into Functions

How do I find which functions to write from a program specification in C++?
Underline every action in the specification, because each action is a candidate function. For a marks analyzer, "accept marks" becomes readMarks, "reject out-of-range values" becomes isValidMark, and "assign a letter" becomes gradeFor. The menu is not an action on data, so it becomes the structure in main that calls the others.
How do I know if a C++ function is doing too much?
Try describing the function in one sentence without using "and." "Works out the average of a set of marks" passes. "Works out the average, prints it, and warns if it is below 50" fails, since that is three functions sharing one name. Calculating functions should return values, and display functions should print.
What goes in the header file and what goes in the source file when splitting a C++ program?
The header holds the function declarations and shared constants, with no bodies. The source file holds the body of every declared function. Main.cpp holds main and the menu loop. Both source files include the header with quotation marks, and an include guard such as #ifndef MARKS_H, #define MARKS_H, and #endif prevents duplicate definitions.
How do I test C++ functions on their own, and which values should I test?
Write a second main in its own file, built instead of the normal main. It calls each function with known values and compares the result with the expected answer. Functions that return values and print nothing make this possible. Choose boundary values such as 90 and 89, 0 and 100, and lists with one or zero elements. Return a non-zero exit code on failure.

About the C++ Programming course

How many college credits is C++ Programming?
C++ Programming (Computer Science 242) carries a NCCRS credit recommendation for 3 semester credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
How much does C++ Programming cost and what is included?
$250, paid once, with lifetime access: all 84 video lessons, a practice quiz after each, the graded work and final exam, and an official transcript when you finish. Students who want several courses choose UPI Study PRO instead.
Which universities accept UPI Study credits?
UPI Study has signed partner agreements with universities such as Thomas Edison State University, University of the People and Charter Oak State College, and works with universities such as Penn State, SNHU and SUNY. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities. Use "Find my college" on this page to check yours.
How long does C++ Programming take?
It is self-paced with no deadlines. The 84 lessons total about 0 hours of video; most students add reading and practice time and finish in a few weeks to a few months, on their own schedule.
How are the exams done?
Quizzes and assignments are online in the course. The final exam is taken online with proctoring; a person on the UPI Study team checks assignments, usually within two days.
How do my credits reach my college?
When the course shows 100% complete, request the official transcript from your dashboard. It is sent to the college you name, and you can send it to more than one. Check your college first with "Find my college" on this page, or ask Athena.

Ready for the full course? Earn 3 credits in C++ Programming.

84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.

C++ Programming
3 credits · NCCRS
Enroll →