Contact Us

Case: Context Manager Scoping

Writing clean, maintainable code is an art and a science---it is a challenging skill that is difficult to learn except through experience. We have collected a number of coding examples that demonstrate good coding practices.

Background

A context manager was used for file loading but included code that was unrelated. At some later point a developer deleted more code than he intended.

Problem

Section of code with large context manager scope:

  with open(f_path) as f:
    parsed_data = json.loads(f)
    processed_data = process(parsed_data)
    plot(processed_data)
    start_scanner(processed_data)

After a few weeks:

  with open(f_path) as f:
    parsed_data = json.loads(f)
    processed_data = process(parsed_data)
    plot(processed_data)
    result = start_scanner(processed_data)
    if result == 'success':
      processed_result = process_result(result)
    else:
      raise Exception
    ...
    with open(output_file) as f:
      f.write(processed_result)
    ...

Although there is no consequence of leaving the file open for the entire block, it implies that everything within the context manager is dependent on the file. In reality, only one line is related. Additional code that is added later tends to just get stuck into the bottom of the context manager. This often also adds extra indents that are unnecessary and makes the code unreadable.

Solution

Being sloppy about lexical scoping of code severely impacts code quality. We all know that loose coupling is a good thing. It is often thought of in the context of architectural design decisions, but how about low level lexical design decisions?

Section of code with correct context manager scope:

  with open(f_path) as f:
    parsed_data = json.loads(f)
  processed_data = process(parsed_data)
  plot(processed_data)
  start_scanner(processed_data)