Learning Python

  • Finished readingIntroducing Python
  • Implement most of the exercises from Introducing Python into IPython Notebook
  • Do CoderByte challenge and Coding Kata
  • Implement BART real-time trip estimator
    • Create a graph of all of the BART stations
    • Figure out which real-time estimate (which direction) to use
  • Implement web scraper for (healthcare / software engineering) using scrapy
  • Implement Blackjack with command line input
  • Analyze healthcare dataset using Pandas

Software engineering goals 2015

Software Engineering

  • Finish notes on Design Pattern
  • Understand DDD and implement possible bits
  • Learn Ruby on Rails, then Go, and finally Python; know Java (understand syntax)
    • Simple to-do app for RoR
    • BART real-time calculator for Go
    • Analyze healthcare costs with Python
  • Use Typescript for personal project, then reservation-next
  • Implement a developer tool (ES Autocorrect) - understand AST

Notes on Python

Note: Some of the points made below are specific to Python 3

  • Math:
    • Exponentiation (2 ** 3 == 8)
    • 35 / 5 = 7.0 (division runs float by default)
    • 7.0 / 2 = 3.5
    • 7 / 2 = 3.5
    • 7 // 2 = 3 (takes the floor of the integer)
  • Equality:
    • Just "=="; no "===" (will throw an error)
  • Basic functions:
    • # single line comment
    • print() - equivalent to console.log
    • int() - typecast into integer
      • note: doesn't work like parseInt - will throw an error if you try to do something like int("hi5")
    • str() - typecast into a string (even works on lists)
    • list() - typecast into a list
    • range() - gives you a list from 0 up to but not including the number passed in
      • range(4,8) # [4,5,6,7]
      • range(3) # [0, 1, 2]
  • Booleans are True or False (must be capitalized)
    • None, 0, empty list / dicts / string are False. All others are True.
  • None is an object (is this like a null object?)
  • Strings are immutable; you cannot do implicit conversion between string and integers (unlike Javascript which does type coercion)
  • Lists are mutable; Tuples are immutable and take less space in memory
    • append() equivalent to push() in JS array
    • pop() removes and returns the last element 
    • a_list_of_numbers.sort(Reverse=True) (sort in memory)
    • sorted(a_list_of_numbers) - returns a new sorted list
    • Concise syntax for doing slices [start:end:step]
      • a_list[::] - shorthand for copying a list
    • You can do destructuring (aka unpacking) for list and tuples
    • list.extend() li.extend(li2) (adds elements of the second list into the first list)
  • Dictionaries are key-value in-memory stores (similar to Plain Old Javascript Object POJO)
    • Note: Unlike Javascript, there is no implicit string conversion on the keys which means you can use variables for the key
    • dict1.update() adds key-value pairs from the second dict to the first dict
  • Remove elements from list or dicts with del keyword (e.g. del li[2])
  • Functions have positional (which one came first) and keyword (what name is assigned to the argument) arguments 
    • Example of keyword arguments:
      • def func1(name, age):
      • func1(age=24, name="will")
    • def varArgs(*args):
    • def kwArgs(**kwargs):
    • def bothArgs(*args, **kwargs) (I believe the positional args globber must come before the keyword args globber)
    • Automatically uses local scope in function. To refer to global scope, must use global keyword
    • Lambdas / anonymous functions:
      • (lambda x: x > 2)
  • List comprehension is a way to create a list through another list
  • Module system: Module is a Python file (you don't need to specify the .py file extension)
    • Syntax for importing
      • import random - for importing an entire module
      • from math import ceil, floor - import specific functions from a module
      • import math as m - alias an import
  • Template string is """ and """
    • Allows you to do multi-line strings
    • Sometimes used for commenting
  • Conditionals:
    • if x > 10:
    • elif x > 0:
    • else:
  • For loop:
    • for dog in ["alfred","beagle"]:
      • print(dog)
  • Being Pythonic
    • Use snake_case for identifiers
    • Check for existence in list: (e.g. 3 in integer_list)


Sources:

  • Introducing Python: Modern Computing in Simple Packages
  • TDD Python
  • Django docs https://docs.djangoproject.com/en/1.8/intro/overview/

Notes on Refactoring to Patterns

  • Replace Constructors with Creation Methods (also known as Static Factory Method) - Use a static or nonstatic method to create instances. For example: TodoStore.createItem(data)
    • If you have too many Creation Methods, you can apply Extract Factory and create a factory. (e.g. if you have a Todo class with 5 methods each to create a different type of todo item, you create a Factory that holds all these creation methods so the intent of the original Todo class is clear).
  • Move Creation Knowledge to Factory When you have too many classes that unnecessarily know how to create instances of a class, you combine all those creational methods to a single Factory class
    • Creation Method - a static or nonstatic method returns an instance of a class
    • Factory - a class that implements one or more Creation Methods
    • Factory Method - "a nonstatic method that returns a base class or interface type and that is implemented in a hierarchy to enable polymorphic creation" (p 71). https://en.wikipedia.org/wiki/Factory_method_pattern
    • Abstract Factory - "an interface for creating families of related or dependent objects without specifying their concrete classes" (Design Patterns, 87). https://en.wikipedia.org/wiki/Abstract_factory_pattern#Pseudocode
      • Every Abstract Factory is a Factory but not conversely.
  • Encapsulate Composite with Builder Simplify the creation of a composite (e.g. a parent DOM node with a couple of children DOM nodes) by using a Builder to deal with the complex details.
    • If you have a class with many options, then you would need a lot of constructors to cover the combinations. So Instead, you use a Builder factory which allows you to set the options one by one. https://en.wikipedia.org/wiki/Builder_pattern
    • A Builder class will have one method to actually get the instance which is called as the last step to the Builder.
  • Compose Method Turn a long block / function definition into a series of well-named small-bite function calls.
  • Replace Conditional Logic with Strategy - Instead of using conditional logic to determine which algorithm to use - you delegate to a strategy instance.
    • Strategy Pattern has the program select the appropriate strategy at run time. Only use Strategy pattern when you are going to change the algorithms a lot. Javascript example at: http://www.dofactory.com/javascript/strategy-design-pattern
      • defines a family of algorithms,
      • encapsulates each algorithm, and
      • makes the algorithms interchangeable within that family.
  • Replace State-Altering Conditionals with State - Similar to Strategy but with a different intent. State is concerned with WHAT you can do and Strategy is considered with HOW you do something
    • Extract class to a State Class
    • Copy each method that modifies state in the host class to the new State class
    • Create subclass for each type of state
    • Copy each method for the subclass state and simplify the method from conditionals
    • Repeat for each state subclass and method that modifies state
  • Replace Conditional with Polymorphism
    • If your host class (the context) has subclasses, and the different subclasses matches the variations of algorithms then this is a good choice for refactoring (p. 130)
  • Replace Type Code with Subclasses - If the conditions to select the variations of the algorithm is based on type code, this is the preferred refactoring. 
  • Replace Conditional Dispatcher with Command - Command pattern separates who requests a command and who executes the command.
    • Use this when:
      • You need to dynamically modify the conditional logic for dispatching
      • You have to scroll a lot to understand the conditional & dispatching actions
  • Misc notes:
    • Abstract vs. concrete: abstract type is a type in a nominative type system which cannot be instantiated directly
    • Nominal vs. structural: nominal (Java) vs structural / duck typing (Typescript)
    • Template method pattern "is a behavioral design pattern that defines the program skeleton of analgorithm in a method, called template method, which defers some steps to subclasses" (source: Wikipedia).  first a class is created that provides the basic steps of an algorithm design. These steps are implemented using abstract methods. Later on, subclasses change the abstract methods to implement real actions. Thus the general algorithm is saved in one place but the concrete steps may be changed by the subclasses.
    • Algorithm is just a step-by-step of instructions
    • invariant (or standard), and which are variant (or customizable)
    • Composite pattern is constructing a tree-like structure of objects (e.g. a parent DOM node with two DOM child elements)

Creational Patterns: creating instances

Structural Patterns: class and object composition

Behavioral Patterns: communication between objects

Note: Quotes are from the book Refactoring to Patterns by Joshua Kerievsky.

Highly recommend this resource on Design Patterns: https://sourcemaking.com/design_patterns

Design patterns are a language weakness: http://www.norvig.com/design-patterns/design-patterns.pdf

Pattern hierarchy: http://stackoverflow.com/questions/3883692/strategy-pattern-vs-command-pattern