Python Forum
Function responsibility in code - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Function responsibility in code (/thread-14029.html)



Function responsibility in code - CodeWolf - Nov-12-2018

I've heard the whole "design functions to do one thing well" mantra, but it's still a little vague to me. Recently I've been working on an input processing script which is based off of instructions from a book. Right now I'm worried if I've split up the functions too much. This is what I have so far:

def check_input(digit_input):
    if digit_input.isdigit() is not True:
        print("Error: input contains non-numbers. Exiting.")
    else:
        if len(digit_input) == 6:
            return digit_input
        else:
            print("Error: number of digits is not six. Exiting")


def input_to_list(digit_input):
    digit_list = list(digit_input)
    return digit_list


def chksum_extraction(digit_list):
    check_sum = digit_list.pop(-1)
    return check_sum
    return digit_list


digit_input = input("Enter six digit ID: ")
check_input(digit_input)
I think knowing whether or not this is organized well will give me a concrete example when working on future programs.


RE: Function responsibility in code - Larz60+ - Nov-12-2018

here's a good rule to 'try' to go by: https://legacy.python.org/dev/peps/pep-0020/
Sometimes its not always possible.
But using too many functions in my book is worse than not enough.
line 19 is unreachable, delete it.


RE: Function responsibility in code - Gribouillis - Nov-12-2018

A general rule is that functions that don't print anything are more reusable than functions that print something. There are two ways to design a function to validate input: either it returns a boolean indicating if the input is valid or not, or it raises an exception on invalid input. Raising an exception is more pythonic and it gives you the opportunity to carry some data with the exception, so I would write things like
class InputError(RuntimeError):
    pass

def validate_input(digit_input):
    if not digit_input:
        raise InputError("Empty input.")
    if not digit_input.isdigit():
        raise InputError("Input contains non-numbers.")
    if len(digit_input) != 6:
        raise InputError("Expected six digits in input.")
    return True

digit_input = input("Enter six digit ID: ")
try:
    validate_input(digit_input)
except InputError as err:
    print("{} Exiting".format(err))
    raise SystemExit(-1)
print("ID is valid:", digit_input)
The functions input_to_list() and checksum_extraction() are not used in your code. I think the first one should not exist. It is longer to write input_to_list(s) than list(s) and everybody interpretes list() as a conversion to list.


RE: Function responsibility in code - stullis - Nov-13-2018

You definitely understand the concept of Single Responsibility. Each function only performs one action and is thereby responsible for one thing.

To assuage your concern about splitting them out too much, another piece of advice I've heard (and adopted) is that functions should be atomic. An atomic function is ideally less than seven lines of code (not always feasible). It's strange at first but it does make the code base easier to maintain.

The principle benefit of these two idea in conjunction is that smaller functions with single responsibilities are easier to test and troubleshoot. Plus, they're so small that they get reused numerous times; thus, fixing one line of code can fix a variety of problems throughout the program.

If your function's purpose is merely to call up another function without passing a dummy argument, you're better off just using the other function:

# Better off just calling list() instead.
def convert_to_list(item):
    return list(item)

# Passing a dummy argument to another function is worthwhile though
# because it decreases the number of arguments needed for the function call.
def passing_dummy(item):
    return sum(item, 5)



RE: Function responsibility in code - CodeWolf - Nov-13-2018

Thanks all! I'm glad to have learned of some better ways to do things.