Design Patterns and Python OOP - Objects By Design.notes

Saturday, March 26, 2005

TITLE OF PAPER: Design Patterns and Python OOP - Objects By Design
URL OF PRESENTATION: _URL_of_powerpoint_presentation_
PRESENTED BY: Alex Martelli
REPRESENTING: Himself

CONFERENCE: PyCon 2005
DATE: Wednesday, March 23, 2005
LOCATION: GWU Cafritz Conference Center, Marvin Theatre

--------------------------------------------------------------------------
REAL-TIME NOTES / ANNOTATIONS OF THE PAPER:
{If you've contributed, add your name, e-mail & URL at the bottom}

OOP as delegation
    intrinsic/implicit
        instance delegates to its class
        class delegates to descriptors or to base classes
    overt/explicit
        containment
        delegation to self (but not in real life, haha)
    inheritance: more rigid, "is-a" relationship
    hold/wrap: more flexible, "uses-a" relationship (aka "has-a" ?)

Pydioms: Hold vs Wrap
    Hold: Object O has subobject S as an attribute or property
        use self.S.method or O.S.method
        yields coupling in the wrong axis, i.e. every call to a method has to
            know exactly how to reach that method
    Wrap: hold (often via private name) plus delegation (so you use O.method)
        explicit (def method(self...): ... self.S.method(...)
        automatic (delegation in __getattr__)
        gets coupling right (Law of Demeter), i.e. every call doesn't need to
            know how to find every method
        as a guideline, if you have more than one dot ('.') in an expression,
            rethink it

Wrapping to restrict
    Allow access to only some of the features of an object.
    You can't do that with just inheritance (nicely).
    Standard __getattr__ method doesn't work with special methods, which are
        looked up in the class.

Self-delegation--keep your implementationy assumptions localized, and call abstract, conceptual methods on yourself when possible
    Template Method Design Pattern (TMDP)
        "template" word is way overloaded
    Classic version
        Abstract base has organizing methods
        Subclasses have hook methods that implement functionality
        Client code calls the organizing methods on the subclasses
    Mixin version
        mixin base's OM, concrete classes' hooks
        Same general idea as the classic version
    Example: Standard library's Queue class (Classic version)
        Queue.put delegates to _put
        Queue is not abstract
            it is used as-is
            must implement the hook methods as a result
        Subclasses can customize the queueing discipline
            Override methods or data
    Example: DictMixin (Mixin version)
        Abstract, meant for multiple inheritance
        You must supply the hook methods: the elementary dict methods
            at least __getitem__, keys
        Sample subclass: Chainmap, which looks things up in a chain of
            dictionaries

State and Strategy Design Patterns
    Not unlike a "Factored-out" TMDP
        OM in one class, hooks in others
        OM calls self.somedelegate.dosomehook()
    Classic vision
        Strategy: One abstract class per decision
        Factors out object behavior
        State: Fully encapsulated, strongly coupled to context, self-modifying
    Example
        Imaging having a class with an "organizing method" (a method which calls a bunch of hook methods on a delegate), putting the delegate in an instance var, and then assigning to the top-level object's __class__ to change its behavior on the fly, without changing the hooks!

Object Oriented Programming for Polymorphism
    Intrinsic/implicit/classic
        single or multiple inheritance
    Pythonic (based on Duck Typing)

Restricting attributes
    Using __setattr__ so that only attributes that exist can be rebound
        Avoids all the issues of __slots__
    Not sure why we'd ever want this... :)

Null Object Design pattern
    Instead of None, an object that is "innocuously polymorphic"
    It can act like any object, kind of.
    This can hide bugs!
    Example: A NoLog logging object
        Allows one to implement non-verbose logging semantics without spreading
        special cases whereever you log.

OOP for instantiation
    Singleton (there can be only one)
        If one already exists, you get that one.
        Problem, what happens when you have a subclass? Do you get the
            superclass version or not?
    Monostate (Borg)
        Many instances share a single state
        No new instance ever has a "problem"

Q:  Why would you ever subclas


--------------------------------------------------------------------------
REFERENCES: {as documents / sites are referenced add them below}
aleaxit@gmail.com

--------------------------------------------------------------------------
QUOTES:

"How a duck learned to type I don't know..."  Alex


--------------------------------------------------------------------------
CONTRIBUTORS: {add your name, e-mail address and URL below}
Nick Bastin (nick.bastin@gmail.com) <http://www.nickbastin.com>
Linden Wright (lwright@mac.com)
Abhay Saxena <ark3@email.com>
Nate Silva <nate@northwe.st>
Erik Rose <corp@grinchcentral.com>

--------------------------------------------------------------------------
E-MAIL BOUNCEBACK: {add your e-mail address separated by commas }



--------------------------------------------------------------------------
NOTES ON / KEY TO THIS TEMPLATE:
A headline (like a field in a database) will be CAPITALISED
    This differentiates from the text that follows
A variable that you can change will be surrounded by _underscores_
    Spaces in variables are also replaced with under_scores
    This allows people to select the whole variable with a simple double-click
A tool-tip is lower case and surrounded by {curly brackets / parentheses}
    These supply helpful contextual information.

--------------------------------------------------------------------------
Copyright shared between all the participants unless otherwise stated...