How to Write a Function
Functions allow you to name groups of statements, which is the foundation of readable code.
From Statements to Intent
A program can be viewed in two ways. At a detailed level, it is a sequence of statements that a computer follows. At a higher level, it is a message that explains an intended process to the people who read and maintain it. Functions help connect these two views by giving a name to a group of statements.
A function is a named group of statements. The name lets a reader understand the purpose of that group without immediately examining every statement inside it. Instead of seeing a long sequence of implementation details, the reader can follow a sequence of meaningful names.
The main readability benefit of a function is not merely that statements are grouped together. The benefit is that the group has a name that communicates what the group does.
Naming a Group of Statements
To organize a program into functions, identify statements that belong to one clear task and give that group a descriptive name. The name should describe what the function does, rather than how its internal statements accomplish that task. A focused function has a single, well-defined purpose.
Turning Grade Processing into Named Steps
Imagine a program that processes student grades. How can its overall purpose become easier to read?
Identify related work: Group the statements that calculate an average, determine a letter grade, and display the results.
Give each group a descriptive name: Use the names calculate_average, determine_letter_grade, and display_results to communicate the purpose of the three groups.
Read the high-level flow: A reader can now understand the main sequence as calculating the average, determining the grade, and displaying the results without first tracing every internal statement.
The named functions transform a long sequence of grade-processing statements into a readable description of the program's logical flow.
Following the Execution Path
A function name does not replace the work of the statements inside the function. It provides a clear entry point to that work. When the program calls a function, execution moves into the function, carries out the statements inside it, and then returns to the point where the call was made. The program continues from there.
What do you think happens?
A main program calls determine_letter_grade and then display_results. After determine_letter_grade finishes, what is the next high-level step?
Reveal answer
Answer: The program continues with display_results.
A function carries out its internal statements and then returns execution to the point where it was called. The reader can therefore follow the sequence of named calls as the program's high-level path.
Reading function calls in order provides a high-level execution path. You can follow the main logic through the names first, then inspect a function's internal statements only when you need its implementation details.
Readable Structure Before and After
A monolithic block places every statement in one long sequence. To understand its overall purpose, a reader must trace through the individual lines. Dividing the same logic into named functions creates layers: the function names show the program's structure, while the statements inside each function preserve the details.
| Organization | What the reader must do | What the structure communicates |
|---|---|---|
| Monolithic block | Trace individual statements to understand the overall purpose | The details are present, but the high-level intent is difficult to see |
| Named functions | Read the function names first and inspect details when needed | The logical sequence and purpose of each step are visible |
Names That Support Maintenance
Meaningful names continue to help after the program has been written. When a bug appears, a descriptive function name can indicate which part of the program to investigate. Instead of scanning a monolithic block, you can focus on the function whose stated purpose is connected to the problem.
Names also act as documentation when you return to the program later. Code that is easy to read is easier to fix when bugs appear, easier to modify when requirements change, and easier to learn from during later review. A function name should therefore be specific enough to communicate purpose, while the function itself should remain focused on one well-defined task.
Using a vague function name
The reader still has to inspect the implementation details to understand the function's purpose.
Fix:
Choose a descriptive name that communicates the function's purpose at a glance.Naming a function after its implementation details
The name becomes less useful as an explanation of the program's intent.
Fix:
Describe what the function does, not how it does it.Putting several unrelated purposes into one function
The function becomes harder to understand and makes the program's logical sequence less clear.
Fix:
Keep each function focused on a single, well-defined purpose.Ignoring function names while debugging
This wastes effort in code that may be unrelated to the bug.
Fix:
Use descriptive names to identify the part of the program that is most likely worth investigating first.
Practice the Design Choice
A student-grade program contains three related stages: it calculates an average, determines a letter grade, and displays the results. Explain how you would divide these stages into functions and why your names would help someone read or debug the program.
Hints
- Give each distinct stage a name that communicates its purpose.
- Keep the names focused on what each function does.
- Describe how the sequence of names would show the program's high-level flow.
- Find a group of statements with one clear purpose.
- Choose a name that describes what that group does.
- Keep the function focused on that single purpose.
- Read the function names in sequence to check whether the program's high-level intent is clear.
- When debugging, begin by investigating the function whose purpose is connected to the problem.
Key Takeaways
- A function gives a name to a group of statements.
- A descriptive name communicates purpose without requiring the reader to inspect implementation details.
- Function calls create a readable high-level sequence: execution enters the function, completes its statements, and returns to the calling point.
- Organizing code into focused, well-named functions transforms a monolithic block into a logical narrative.
- Meaningful names make debugging, modification, and later code review easier.
Key Takeaways
- Functions allow you to name groups of statements so readers can understand program intent more easily.
- A function call provides a named checkpoint in the program's execution path.
- Descriptive names reveal what a function does without forcing readers to study its internal details.
- Focused functions with meaningful names make debugging, maintenance, and future review more efficient.