And you should adhere to as well, if you would like to work with me
- Never hardcode. Make good utilization of argparse and configuration yaml.
- Configuration yaml is more preferable to argparse. Argparse is for just passing the configuration file.
- Every piece of software should be runnable using a single hierarchical dictionary passed as configuration
- Every configuration dictionary must contain a name that uniquely identifies the class that the dictionary is meant to be consumed by.
- Parent classes should be able to instantiate the correct child using the hierarchical configuration. Use factory pattern for this feature.
- Nested objects intake hierarchical dictionaries where the nest structures are preserved. For example, if class A contains class B and class C, the configuration of class A = {‘name’=’class_a’, ‘class_b_config’: {‘name’: ‘class_b’, …}, ‘class_c_config’: {‘name’: ‘class_c’, …}, …}
- Build the git repository judiciously. Use project-wide cookiecutters for adhering to the following best practices:
- Make good utilization of the setuptools and dependency resolvers like setup.py or poetry.
- Every repository must contain a Dockerfile where the code is guaranteed to work. Build the Dockerfile from public slim images. If a Dockerfile is built from a derived image, provide the dockerfile of that derived image as well.
- Every repository must contain a Makerfile with at least two commands: install, and test. Use Makerfile as an opportunity to demonstrate common entry points of your codebase.
- The repository must be small. Use gitignore. Avoid putting any large binary file in the repository.
- There should be at least one example of full-stack configuration yaml file in the repository.
- Keep an eye on readability and maintainability:
- With the advent of displays, maximum line-length should be 119, not 79.
- Never write the same code twice.
- Make a function out of multiply used code-blocks and call it from different places. Remember this when augmenting others’ code and try to re-utilize their code as much as possible.
- One function should do only one logical task. This is helpful when others need to use the functionalities.
- Never dynamically create variable/method/functions. If such cases must exist, they must be declared in the readme file with the proper justification on why it is needed.
- In general, I do not like codes with a lot of try-except blocks. But, exceptions are NEVER to be silently passed.
- Try not to return more than one variable from a function. If necessary, use a namedtuple or a dictionary.
- Functions should be defined with a default value to their inputs whenever possible.
- Never use wildcard import (from … import *). This type of code is difficult to maintain. Import each object by name, or, import the module name and access the objects from the modules.
- Writing unit tests for each object/function is usually overkill. Find a few use-cases that can cover 100% of the code and use those as tests.
- Avoid sticky code. Sticky codes are the ones that break when moved from one place to another. Usually, they have dependencies on global variables coming outside of the declared interfaces. So, always communicate among objects through established interfaces and hide the details of implementations. Use classes for encapsulation.
- Every class definition and its methods must accompany a docstring.
- Create classes only when it is necessary (Typically to preserve the contexts or states, to avoid sticky codes, or to establish natural relationships).
- Deep learning, in general, is a streamed optimization process. So I prefer to write deep learning code as a stream of data that is processed through a sequence of generators.
- Any mathematical/code-ninja trick should accompany a short, no-more-than-one-line comment explaining what is intended. This improves readability a lot.
- Try to use PEP-8 as long as it is not in direct opposition to the above points.
I’ve found the following book as a great primer and reference for some cool design patterns. I try to adopt them as appropriate for python:
Head First Design Patterns: A Brain-Friendly Guide, by Eric Freeman and Elisabeth Robson