Description
The words 'handler', 'callback', ... are often used to add a notion of where a variable/function is going to be used. However, this is very much as useless as naming a variable after its type.
As an example, consider some library to represent countries on a geographical map or so...
# library code
class Country(Widget):
...
def on_click(self, click_handler):
self.click_handlers.append(click_handler)
And we want to use this library to e.g. draw dots on the respective countries.
# main code
# example: BAD
def my_click_handler(source, click_event):
paint_circle(source.country_colors, click_event.coordinates)
for _, country in world_map.items():
country.on_click(my_click_handler) # BAD: I already expect that `on_click` accepts a click handler
In this code, the my_click_handler
name is meaningless. When reading the main file, you have to read up to the body of the click handler function to know what should happen when a country is clicked.
Imagine a more extreme example:
def divide(nominator, denominator):
return nominator / denominator
class Vehicle:
def speed(self):
nominator = sum(self.distances)
denominator = time.now() - self.journey_start.time
return divide(nominator, denominator) # BAD: this is a repetition of the function parameter names
In both cases, the information in the variable names (my_click_handler, nominator, denominator) are mere repetitions of the parameter names of the called function. This information is already present in the function signature itself, and must not be repeated.
Rather, when the names are chosen to reflect the role the variable/function plays in the program, it becomes much more meaningful:start_time
# example: GOOD
# - the function name reflects what I want to _achieve_ with it
# - the function parameter tells me that I expect a _country_
def mark(country, click_event):
paint_circle(country.colors, click_event.coordinates)
for _, country in world_map.items():
country.on_click(mark) # GOOD: name gives new information in terms of
class Vehicle:
def speed(self):
total_distance = sum(self.distances)
elapsed_time = time.now() - self.journey_start.time
return divide(total_distance, elapsed_time) # GOOD: this represents the physical truth of the program
This naming pattern happens very often for the simple reason that it seems that the role of the variable is determined by the called function (a dependency, external to our own context), and needs no thought.
However, this does not add information and does not help the reader of the code to understand it. Rather, choosing the name according to the role within the context of the own problem domain gives the reader insight in its effective meaning.
Activity