Side Effects

© 2020 Morgan C. Benton code4your.life

What are "SIDE EFFEcts"

I hate this term.

 

Usually we think of "side effects" as the unwanted impacts of a medication or some actions.

 

However, in programming it is the opposite. In software, "side effects" describe intended outcomes and are what make software useful to people.

© 2020 Morgan C. Benton code4your.life

Examples of Side Effects

Side effects are generally unpredictable and involve read/write or input/output operations, such as:

  • obtaining user input, e.g. from a form
  • displaying output on the screen
  • reading or writing a file from a disk
  • reading or writing data from a database
  • getting data from a remote URL

 

The technical term for this is non-deterministic behavior

© 2020 Morgan C. Benton code4your.life

Deterministic

Systems or processes that always produce the same result, i.e. predictable:

  • 2 + 2 = 4
  • capitalize("bob") => "Bob"
  • data transformation
  • math

non-deterministic

Systems or process that produce unpredictable, sometimes random, results:

  • user input
  • HTTP requests
  • reading/writing to disk/DB
  • displaying to a screen
  • printing to paper
  • audio/video playback

Non-deterministic behavior?

© 2020 Morgan C. Benton code4your.life

"side effects"

Good things about
side effects

Side effects are what makes software useful.

It doesn't matter how robust your machine learning algorithm, or meteorological model, or gaming physics engine if the results of those computations can't be written to a disk, displayed on a screen, or transmitted across a network, your software does nothing useful.

© 2020 Morgan C. Benton code4your.life

BAD things about
side effects

Side effects are hard to test.

If you can't predict what a user is going to type into a form, or whether writing to the database is successful, or whether data requested from a URL returns as expected, it is hard to know if errors are caused by bad code or by some other failure of the system.

Such errors can diminish or eliminate the positive effects of software.

© 2020 Morgan C. Benton code4your.life

© 2020 Morgan C. Benton code4your.life

for x in range(1, 101):
  if x % 15 is 0:
    print('FizzBuzz') # <== side effect
  elif x % 3 is 0:
    print('Fizz') # <== side effect
  elif x % 5 is 0:
    print('Buzz') # <== side effect
  else:
    print(x) # <== side effect
def fizzbuzz(x):
  return 'FizzBuzz' if x % 15 is 0 else x

def fizz(x):
  return 'Fizz' if x % 3 is 0 else x

def buzz(x):
  return 'Buzz' if x % 5 is 0 else x

for x in range(1, 101):
  print(fizz(buzz(fizzbuzz(x)))) # <== side effect

Mostly Untestable

Mostly Testable

Code Examples

guidelines

© 2020 Morgan C. Benton code4your.life

  • ALL useful code will contain some side effects
  • Restructure your code to move side effects "to the edges," i.e. to the very beginning or end of a process
  • Side effects can almost always be separated from the rest of your code
  • Wrap the steps of your process in functions that can be tested and composed to accomplish your goal
  • Write automated unit tests for the functions that do not contain side effects

"Pure" functions

© 2020 Morgan C. Benton code4your.life

"Pure" functions:

  • Do NOT contain side effects
  • Do NOT mutate (i.e. make changes to) any global variables
  • Return exactly one value
  • Are deterministic, i.e. given the same input, they always return the same output

examples of converting impure functions to Pure

© 2020 Morgan C. Benton code4your.life

user input

"""
  Process: User types in a number representing MPG,
           which gets converted to KPL and printed.
"""

# CONSTANTS
KPM = 1.60934  # kilometers/mile
GPL = 0.264172 # gallons/liter

# IMPURE
def convert():
  mpg = input('What is your MPG?')
  print('Your KPL is: ' + (mpg * KPM * GPL))

# PURE
def convert(mpg):
  return mpg * KPM * GPL

mpg = input('What is your MPG?')
print('Your KPL is: ' + convert(mpg))

© 2020 Morgan C. Benton code4your.life

reading File input

"""
  Process: Open a file that contains a list of
           tempertature readings, and calculate
           the average.
"""

# IMPURE
def calculateAvgTemp():
  f = open('temps.txt') # <== side effect
  temps = f.read().split()
  avg = 0
  for x in temps:
    avg += float(x) / len(temps)
  print(avg) # <== side effect


# PURE
def calculateAvgTemp(data):
  temps = data.split()
  avg = 0
  for x in temps:
    avg += float(x) / len(temps)
  return avg

f = open('temps.txt')
print(calculateAvgTemp(f.read()))

© 2020 Morgan C. Benton code4your.life

25.8
15.6
22.0
19.2
23.3
21.9

temps.txt

Making an HTTP Request

"""
  Process: Retrieve the current weather for Washington, DC
           from the metaweather.com free REST API, search
           the results to find today's weather and output
           the weather state.
           See: https://www.metaweather.com/api/
"""
# Import 3rd party library for making HTTP requests
from requests import get
from datetime import datetime

# CONSTANTS
URL = 'https://www.metaweather.com/api/location/2514815/'
TODAY = datetime.today().strftime('%Y-%m-%d')

# IMPURE
def getTodaysWeather():
  result = get(URL) # <== side effect
  data = result.json()
  for day in data['consolidated_weather']:
    if day['applicable_date'] == TODAY:
      print(day['weather_state_name']) # <== side effect

# PURE
def getTodaysWeather(days):
  for day in days:
    if day['applicable_date'] == TODAY:
      return day['weather_state_name']
    else:
      return 'Unknown'

data = get(URL).json()
print(getTodaysWeather(data['consolidated_weather']))

© 2020 Morgan C. Benton code4your.life

Summary

  • A "side effect" in software is non-deterministic behavior, usually associated with input/output
  • Side effects are what makes software useful, BUT
  • Side effects are HARD TO TEST
  • Whenever possible:
    • Isolate side effects from the rest of your program
    • Write pure, easily testable functions
    • Follow the TDD process

© 2020 Morgan C. Benton code4your.life

Made with Slides.com