When learning to program, beginners often struggle with a fundamental concept that affects how testable and reusable their code becomes. This confusion centers around two different approaches to getting results from functions:
def calculate_total(price, tax_rate):
result = price + (price * tax_rate)
print(f"Total: ${result}") # Prints directly to consoledef calculate_total(price, tax_rate):
return price + (price * tax_rate) # Returns the value
# Somewhere else in the code:
total = calculate_total(100, 0.08)
print(f"Total: ${total}") # Caller handles printingThe confusion becomes critical when trying to write unit tests:
def test_calculate_total_that_prints():
# How do you test this? The function just prints!
# You'd need to capture stdout, which is complex and brittle
calculate_total(100, 0.08) # Prints "Total: $108.0"
# No way to easily verify the calculation is correctdef test_calculate_total_that_returns():
# Simple and clear!
result = calculate_total(100, 0.08)
assert result == 108.0 # Easy to verify the calculationBeginners often think these two approaches are equivalent because:
- Both show the same output to the user - they see the same text on screen
- They don't initially think about testing - unit testing concepts come later
- They focus on the immediate result - "it works" seems sufficient
- They don't consider reusability - what if you need that calculated value elsewhere?
Functions that return values are trivial to test with assertions. Functions that only print require complex output capture mechanisms.
A returned value can be used in further calculations, stored in variables, or passed to other functions. A printed value disappears into the console.
The calculation logic is separate from the presentation logic. The function does one job well.
You can chain functions together when they return values:
tax = calculate_tax(price, rate)
shipping = calculate_shipping(weight, distance)
total = price + tax + shippingThis repository contains examples in both Java and Python that demonstrate:
- Functions that return values vs. functions that print
- How to test functions that return values
- Real-world examples showing why returns are more flexible
- Common mistakes beginners make
- Exercises to practice the concepts
Located in /java/ - uses traditional Java syntax and JUnit for testing
Located in /python/ - uses Python idioms and unittest framework
- Read the language-specific README in either
/java/or/python/ - Run the example programs to see the difference in action
- Look at the test files to understand how return values make testing easy
- Try the exercises to practice identifying and fixing these issues
A function should do one thing well. If a function calculates something, it should return that calculation. If you want to display it, do that as a separate step. This separation makes your code more testable, reusable, and maintainable.
The moment beginners understand this distinction, their code quality improves dramatically because they start thinking about functions as reusable building blocks rather than just sequences of instructions that produce output.