2.3 Loose Coupling, Strong Cohesion

Introduction

When designing functions, we want to look beyond the constraints of the current problem, and we want to generalize the function so as to solve, not only the current problem, but the class of problems. Two very important design principles to be applied in designing functions to achieve this is Loose Coupling and Strong Cohesion.


Loose Coupling

Loose Coupling is the degree of independence of a function from other functions. If we have a number of functions which all depend on each other to work, then we have not done a good enough job of generalizing their functionality.

Example (bad):

Let's consider an example where the requirement is to add two numbers together. Let's take a look at the following badly designed function

def addition():
    num_1 = float(raw_input("Enter Number One"))
    num_2 = float(raw_input("Enter Number Two"))
    addition = num_1 + num_2
    print addition

One might take a look at this function and notice the duplication of the code to get user input, and realize that it is lacking error checking in the situations where non-numeric input is entered by the user. We might then split this function into two separate functions.

def get_number(question):
    response = raw_input(question)
    num = 0
    try:
        num = float(response)
    except:
        num = 0
    return num

def addition():
    num_1 = get_number("Enter Number One")
    num_2 = get_number("Enter Number Two")
    addition = num_1 + num_2
    print addition

Now, we have two separate functions which handle separate functionality. Have we achieved Loose coupling? Well, firstly consider that the addition() function cannot be used without the get_number() function. This dependance means that we do not have loosely coupled functions. Secondly, we are printing the answer to standard input instead of returning the answer to the addition. This means that we are forced to only display the answer, and never use it for further processing.

Let's have a look at this rewritten to achieve loose coupling.

Example (good)

def get_number(question):
    response = raw_input(question)
    num = 0
    try:
        num = float(response)
    except:
        num = 0
    return num

def addition(numbers):
    total = 0
    for i in numbers:
        total = total + i
    return total

num_numbers = get_number("How many values would you like to add? ")
numbers = []
for i in range(0, num_numbers):
    numbers.append(get_number("Please enter a number: "))
answer = addition(numbers)
print "The answer to the addition is: %d" % (answer)

There are a few things to notice here:

  • The addition() function no longer calls the get_number() function, meaning there is no dependency between the two functions.
  • The addition() function takes in an array of numbers to add together. The requirement was to add two numbers together, which we can still do, but now we have generalized the function so that we can solve adding two numbers, three numbers, 100 numbers, 1000 numbers etc.
  • The answer to the addition is returned, meaning we can do with it as we please.

Strong Cohesion

Strong Cohesion is the degree to which the internal functionality is related. When designing a function, we want each line in the function to directly relate to the purpose of that function. If we have pieces of code within the function which do not relate to the purpose of the function, it might be indicative that the unrelated code could potentially be pulled out and formed into a new function.

Let's re-examine the example code above in terms of String cohesion.

Example (bad)

def addition():
    num_1 = float(raw_input("Enter Number One"))
    num_2 = float(raw_input("Enter Number Two"))
    addition = num_1 + num_2
    print addition

Although there are only four lines of code in this function, there are elements in this function which are not directly relevant to the problem of addition. For example, the first two lines include code to read user input and convert a string to a float. This does not relate directly to the problem of addition, which this function is meant to address. Thus, we have not achieved Strong Cohesion in this function.

Example (good)

def addition(numbers):
    total = 0
    for i in numbers:
        total = total + i
    return total

In this version of the function, we also have four lines of code, but this time, each line directly relates to adding numbers together. There is no superfluous code which detracts from this in any way, and so, we can say that we have Strong Cohesion in this function.

Remember, we always want to achieve Loose Coupling and Strong Cohesion.


Exercises

Correct the following functions:

  1. Exponent

    def exponent(): num = int(raw_input("Enter in a number: ")) exponent = int(raw_input("Raise the number to the power of: ")) answer = pow(num, exponent) print answer

  2. Concatenation

    def concatenation(): string1 = raw_input("Enter in a string: ") string2 = raw_input("Enter another string: ") full_string = "%s %s" % (string1, string2) print full_string

Continue to next section


Comments

comments powered by Disqus