Change the future

Friday 2:35 p.m.–3:05 p.m.

Encapsulation with descriptors

Luciano Ramalho

Audience level:
Novice
Category:
Best Practices/Patterns

Description

Python has no private fields, but the property decorator lets you replace public attributes with getters and setters without breaking client code. And the descriptor mechanism, used in Django for model field declarations, enables wide reuse of getter/setter logic via composition instead of inheritance. This talk explains how properties and descriptors work by refactoring a practical example.

Abstract

Update: the slide deck is complete and has been successfully tested 4 times (twice with English-speaking audiences). See it at Speakerdeck.

Update 2: after testing this talk with Brazilian and Australian audiences I have reduced its scope, simplifying the code and removing the metaclass portion to make it fit comfortably in 30 minutes. It is now a novice talk.

This talk reveals the real meaning of the deceptively simple syntax of Django model classes, Colander schemas and similar declarative APIs.

If you are new to Python, it is easy to overlook the descriptor mechanism, since it is not found in some other popular languages (but it is in modern JavaScript ).

This is a practical talk where new concepts are introduced when they are needed to solve a concrete problem.

Talk outline (times in minutes)

  1. (2') Introduction, motivation and scenario

  2. (3') Modelling a line item as a simple class with public attributes; adding getters and setters, Java style.

  3. (4') The class is refactored to use properties to enforce business rules (for example, the quantity must be greater than zero). This works but introduces repetitive code.

  4. (7') Repetition is removed by implementing custom descriptors. Overview of what is descriptor, UML diagram, relationship between descriptor instances and the managed class and managed attributes.

  5. (8') Descriptor implementation details: where to store value of the managed attribute and how to generate a name for the target attribute. Initial problem solved.

  6. (4') What now? Limitations of the solution. The high (conceptual) cost of overcoming these limitations: class construction details. Invitation to learn about metaclasses. References.

  7. (12') If given a 45' slot I will show a metaclass to provide finer control of the storage of the values in the managed instances. The metaclass is then "hidden" behind a base class to be extended in classes that want the descriptor functionality, providing the same apparent simplicity of Django models.