Defensive Programming

Reporting (un)expected state

  • Assertions check for user defined conditions and raise an exception if the condition is False. The syntax is:

    assert expression0
    
    assert expression1, expression2
    
    # Which is equivalent to:
    
    if __debug__:
        if not expression0: raise AssertionError
    
    if __debug__:
        if not expression1: raise AssertionError(expression2)
    
  • Raising Exceptions

    In a more complex case you could raise a custom exception that carries the exact meaning you wish to transfer:

    class mySpecialError(Exception):
       """ This error is raised in a special situation.  """
       pass
    
    if myValue < myLimit:
       raise mySpecialError()
    
  • Use loggers to easily turn on and off your debug writes.

    import logging
    logging.warning('Warn!')        # Printed by default
    logging.info('Info!')           # Need to ask for more verbose
    logging.debug('details...')     # Need to ask for much more verbose
    
    • The basic idea of loggers is to provide a framework that makes it convenient to choose the current verbosity of the program depending on simple centralized run-time setting.

    • The logger framework can do formatting of the messages, such as including the time.

Checks while writing

Using On-line linting and IDEs can help you fix bugs as you type!

  • Pylint is an off-line tool that can check your code for formatting and for certain logical errors that could hint at hidden problems.

  • IDEs like spyder, pycharm, eclipse and vscode can warn you of undefined and unused variables, bad syntax and perform further diagnostics of your code while you write.

Divide and conquer

  • Separate objects and implement clear interfaces

  • Unit testing

    • There are a number of python frameworks for unit testing, e.g. the built in unittest and pytest.

    • Preferrably run automatically in a continuous integration setup

Document well

  • You can give type hints about what types are expected, but it is only documentation, not enforced by the runtime.

  • Docstrings should include i.a. information about the parameters and return values of functions.