4/2/2019
Error:
Exception:
python, has InsertNameHereError
, R has stop()
and warning()
. The names may change, but the idea is still the same. Errors can’t be handled, exceptions can be handled.
Try-Catch-Finally
# main.py try: bids = calculate_bid(adgroup_id=an_id) except ValueError as err: print("An invalid value provided, defaulting to 0 bid. ", err) bids = 0 except: print("Unexpected error:", sys.exc_info()[0]) raise
raise
do?# bid_calculator.py def calculate_bid(adgroup_id): if type(adgroup_id) != int: raise ValueError("adgroup_id must be an integer") if adgroup_id < 0: raise ValueError("adgroup_id must be greater than 0") raise NotImplementedError("Get to work.")
ValueError("adgroup_id must be an integer")
ValueError("adgroup_id must be greater than 0")
NotImplementedError("This method is not implemented. Get to work.")
null
exceptions?
If you don’t believe me, believe Sir Charles Antony Richard Hoare, developer of the QuickSort
algorithm. Null References: The Billion Dollar Mistake
def get_reciprocal(x): if x == 0: return None return 1 / x def double_a_number(x): return 2 * x def pass_a_number(x): return x def manipulate_number(x): reciprocal = get_reciprocal(x) another_step = pass_a_number(reciprocal) double_reciprocal = double_a_number(another_step) return double_reciprocal
Boundaries are effective construct that can help protect from headaches. Some migraine reducing techniques include:
# main.py def is_most_recent_version(file): existing_file_meta_data = dbx.get_meta_data(file.name) if existing_file_meta_data is None: return True if existing_file_meta_data.date > file.date: return False return True if __name__ == "__main__": dbx = dropbox.Dropbox(config.access_token) file_list = get_files_for_upload() for file in file_list: if (is_most_recent_version(file)): dbx.file_upload(file)
# DocumentWarehouse.py class DocumentWarehouse: def __init__(self, access_token): self.dbx = dropbox.Dropbox(access_token) def should_be_updated(self, file): meta = self.dbx.get_meta_data(file.name) if meta is None: # No file in DBX return False if meta.date > file.date # existing file is more recent return False return True def upload_file(self, file): self.dbx.upload_file(file)
# main.py (refactored) import DocumentWarehouse if __name__ == "__main__": dw = DocumentWarehouse(config.access_token) file_list - get_files_for_upload() for file in file_list: if dw.file_should_be_updated(file): dw.upload_file(file)
from abc import abstractmethod class DocumentWarehouse: @abstractmethod def should_be_updated(self, file=str): pass @abstractmethod def upload_file(self, file=str): pass
from DocumentWarehouse import DocumentWarehouse from dropbox import dropbox class DropboxWarehouse(DocumentWarehouse): def __init__(self, access_key): self.dbx = dropbox.Dropbox(access_key) def should_be_updated(self, file=str): meta = self.dbx.get_meta_data(file.name) if meta is None: # No file in DBX return False if meta.date > file.date: # existing file is more recent return False return True def upload_file(self, file=str): self.dbx.upload_file(file)
from DocumentWarehouse import DocumentWarehouse from aws import s3 class S3Warehouse(DocumentWarehouse): def __init__(self, access_key): self.s3 = s3(access_key) def should_be_updated(self, file=str): meta = self.s3.get_details(file.name) if meta.file_exists == False: return True if meta.date > file.date: # existing file is more recent return False return True def upload_file(self, file=str): self.s3.save_file(file)
Now, we can swap our storage provider with a single line of code…
if __name__ == "__main__": dw = DropboxWarehouse(config.access_token) file_list - get_files_for_upload() for file in file_list: if dw.file_should_be_updated(file): dw.upload_file(file) ########################## if __name__ == "__main__": dw = S3Warehouse(config.access_token) file_list - get_files_for_upload() for file in file_list: if dw.file_should_be_updated(file): dw.upload_file(file)
polymorphism
- is the provision of a single interface to entities of different types or the use of a single symbol to represent multiple different types
design-by-contract
- prescribes that software designers should define formal, precise and verifiable interface specifications for software components, which extend the ordinary definition of abstract data types
Each language may (or may not) implement some form of this. Some terms you might hear: