Code smells, fifth part
By Detlef Wuppermann
In our first four parts of our series we discussed a small (Python) script. We went through the most obvious code smells and fixed them in every step.
from datetime import datetime, timedelta
import sys
import requests
from requests.auth import HTTPBasicAuth
from configuration import http_user_service_url, http_user_service_username, http_user_service_password,
userdata_filename, age_in_years
import csv
authentication = None
min_age = None
file_handler = None
writer = None
def setup():
global authentication
global min_age
global writer
global file_handler
authentication = HTTPBasicAuth(http_user_service_username, http_user_service_password)
min_age = datetime.now() - timedelta(days=age_in_years * 365)
file_handler = open(userdata_filename, 'w')
writer = csv.writer(file_handler)
def tear_down():
file_handler.close()
def is_user_from_country(user):
if user['country'] == "Spain":
return True
LOG.debug(f"User with id ${user['id']} is not from Spain.")
return False
def is_user_old_enough(user):
global min_age
birth_date_str = user['birth_date']
birth_date = datetime.fromisoformat(birth_date_str)
is_old_enough = birth_date < min_age
if not is_old_enough:
LOG.debug(f"User with id ${user['id']} is not old enough and will be skipped.")
return is_old_enough
def get_all_users():
global authentication
LOG.debug(f"Fetching data from user service with response code {response.code}.")
response = requests.get(http_user_service_url, auth=authentication)
if response.status_code != 200:
LOG.error(f"Could not make a successful request to ${http_user_service_url}. The error message is {response.text}.")
sys.exit(1)
response_dict = response.json()
all_users = response_dict['results']
def write_user(user, user_count):
new_user = {
"name": f"{user["title"]} {user["first_name"]} {user["last_name"]}",
"street": user["street"],
"city": f"{user["postal_code"]} {user["city"]}",
"country": user["country"],
}
writer.writerow(user.keys())
def filter_users_of_legal_drinking_age():
all_users = get_all_users()
filtered_users_count = 0
for user in all_users:
if not is_old_enough(user):
continue
if not is_user_from_country(user):
continue
write_user(user, filtered_users_count)
filtered_users_count = filtered_users_count + 1
LOG.debug(f"{filtered_users_count} from {len(all_users)} total users found.")
if __main__ == main():
setup()
filter_users_of_legal_drinking_age()
tear_down()
We went a long way. Maybe now is a good moment to think about the quality of our code should have.
If you are developing just a script like this one, I think it should be good enough (apart from some minor issues that I want to address real quick later on).
If you are developing a bigger application, we should look further and divide our code into different files.
Maybe, we should also think of using a framework that provides us with a certain functionality that might come in handy.
Also, important for bigger applications, or even required by your company’s policy, are unit tests. These not only help you to identify bugs in your code earlier (and hopefully before deploying to production), but also help you with structuring your code in a more maintainable manner. We will jump into this topic in our segment “unit testing”.