# Organizing Code Keeping your code: * readable * correct * robust * testable * maintainable --- # Part 1: Readable Code Follow [PEP-8](https://www.python.org/dev/peps/pep-0008/). You spend a lot more time reading code than writing it. Spend some time making your code readable and you'll save lots of time and frustration later. Readability leads to understanding, understanding leads to reliable programs. * use good names * use [PEP-8](https://www.python.org/dev/peps/pep-0008/) as a guideline * add whitespace to break things up --- ## Naming Conventions ```python animal # Variables are lowercase with underscores. feed_animal() # So are functions. AnimalFile # Class names are camel case. BAD_ANIMALS # Contants are uppercase. ``` This makes them easy to tell apart. --- ## Don't Write Java in Python This looks like Python: ```python def do_this(and_this): return and_this ``` This doesn't: ```python def DontDoThis(orThis) return len(orThis) ``` CamelCase is only for classes: ```python class DogFood: ... ``` Same goes for file names: ``` this_is_good.py ThisLooksLikeJava.py ``` --- ## Functions are Verbs Use verbs as function names: ```python person = get_person(db, username) ``` ```python if is_student(person): # Do student specific thing. ``` --- ## Plurals are Plural This: ```python for name in names: ``` reads better than: ```python for name in name_list: ``` --- ## Use Dictionaries Instead of if/else Instead of: ```python def get_mode_name(mode): if mode == 0: return 'stopped' elif mode == 1: return 'playing' elif mode == '3': return 'recording': else: raise ValueError('Unknown mode {}'.format(mode)) >>> get_mode_name(1) playing ``` do: ```python MODES = { 0: 'mode', 1: 'playing', 3: 'recording', } >>> MODES[1] playing ``` --- # Part 2: Organizing Your Code (Well organized code is also more readable.) --- ## Contruct Your Program From Parts * functions, modules, packages * dictionaries, lists, sets Make parts that are easy to fit together and combine in different ways. Make every part of the program a building block for building more program. --- ## Modules and Packages You've already written a module! A module is a Python file. A package is a directory of modules. ### `__init__.py` * is the top level module in a package * should only contain imports (no code or data) Example: https://github.com/olemb/mido/ --- ## Keep Related Things Together --- ## Contain the Mess Some parts of your code are always going to be messy. Quarantine the mess: * put it in a function or module * make a well defined inteface for it The rest of your code will now be cleaner. --- ## Avoid Global Variables This raises many questions: ```python def greet(name): print(config['greeting'], name) ``` * what is `config`? * where does it come from? * will it change? * what else is in `config`? A function should know only what it needs to know: ```python def greet(name, greeting='Hello'): print(greeting, name) greet('Steve', greeting='Howdy') ``` --- ## Don't Repeat Yourself (DRY) * don't do the same thing in many places * don't copy and paste code to make a slightly different function * when you see repetition, it might be time for a function --- ## But Don't Contort Yourself To avoid this repetition: ```python MODE_NUMS = { 'stopped': 0, 'playing': 1, 'recording': 3, } MODE_NAMES = { 0: 'stopped', 1: 'playing', 3: 'recording', } ``` you could add code that adds the flipped values: ```python MODES = { 'stopped': 0, 'playing': 1, 'recording': 3, } # Add reverse lookup. MODE_NAMES = {value: name for name, value in MODES.items()} ``` but it's not worth it for such a small table and it makes the code harder to understand. --- ## Break It Info Functions * if you have too many levels of indentation * if a function gets too long * if a function does more than one thing If you find it hard to name a function it may be doing more than one thing. --- ## Interactive Example Time Recommended video: Transforming Code into Beautiful, Idiomatic Python (1 hour talk by Raymond Hettinger) https://www.youtube.com/watch?v=OSGv2VnC0go