2. Работа программиста Алгоритмы и структуры данных Взаимодействие в команде Документация Исправление ошибок Изменения и дополнения запланированные неожиданные миграция кода и рефакторинг
3. Организация кода Разделение кода на модули Разделение функциональности на функции и классы В конечном счете всё комбинируется компилятором или средой исполнения Как именно делить? Как именно комбинировать?
4.
5. ООП Method dispatch Ключ: Класс экземпляра Имя метода Тип параметров (для мультиметодов) Расширение и переопределение [только] через подклассы Не зря пользователи динамических языков широко применяют альтернативные подходы super(…)
6. О чем речь в докладе PyProtocols Надстройка над ООП Протоколы (интерфейсы) и адаптеры Комбинация адаптеров PEAK-Rules Дополняет и усиливает любой подход Generic functions Самая мощная реализация GF ООП всего лишь частный случай Остальное тоже частный случай
19. Коротко о главном Протокол ≈Интерфейс Протокол это объект обозначающий набор требований Документация Один протокол может подразумевать другой протокол Подклассы в ООП Если объект соответствует одному протоколу, его можно адаптировать к другому
20. Базовые операции [1] Затребовать от объекта соответствие протоколу stream = adapt(stream, IStream) Объявить экземпляры класса соответствующими протоколу declareImplementation(Stream, [IStream]) declareAdapter(NO_ADAPTER_NEEDED, [IStream], forTypes=[Stream])
21. Базовые операции [2] Объявить способ адаптации между протоколами: declareAdapter(lambda file: file.open(), [IStream],forProtocols=[IFile]) Цепочки адаптеров выстраиваются автоматически Есть еще
23. Проверка интерфейсов / типов Обычная претензия к динамическим языкам: Что будет если методу передать неверный параметр? Класс как протокол Следующий шаг: protocolForType(file, ['read'])
24. Пример №1 from protocols import * class C(object): pass obj = C() assert adapt(obj, C) is obj
25. Рефакторинг Благодаря адаптации старый и новый код могут легко взаимодействовать Связующий код находится отдельно и его меньше Ни старые ни новые библиотеки не загрязнены проверками Когда рефакторинг завершен, очистить код от поддержки старых вызовов тривиально
26. Расширяемость Как сделать возможным взаимодействие с произвольными данными? Например: Вывод на печать Сериализация данных Преобразование данных Предоставление и поддержка разноуровневыхAPI Типичное решение – инверсия контроля (callbacks)
28. Контекстное переопределение? Как быть если нужно переопределить часть функциональности да еще и только временно? Как поддержать расширения не предугадывая и не ограничивая их? Это редко встречается потому что в традиционном ООП это дается только большой кровью
29. Контекстное переопределение! Протокол это всего лишь объект – создаем сколько хотим Например для каждой задачи печати Исходный набор адаптеров получается сам собой Даем остальному коду переопределять любые из адаптеров – как угодно Изменения сами попадут в нужное место Паттерн ООП «это невозможно»
30. Идеи применения Адаптация к MIME типам text/html text/* */* text/x-rst text/html application/pdf Page text/x-rst … Page application/json Адаптация к возможностям браузера Адаптация к устройствам вывода Model View Controller
32. История вопроса CLOS – Common Lisp Object System Dylan, Smalltalk, S#, Perl6, Cecil, Nice Multiple dispatch Не просто перегрузка методов Python 3000 RuleDispatch
33. Что такое generic function Функция которая переопределяется в зависимости от её аргументов не только по типу первого аргумента не только по типам аргументов не только переопределяется Метод в ООП это частный случай GF single dispatch только по типу
34. Где это уже было? str, int, bool, repr, pprint, Pickle, copy_reg Математические операции Сравнение
35. PEAK-Rules rules Любая функция может быть превращена в родовидовую (если есть func_code) Даже алгоритм диспетчеризации можно расширять или заменять AOP Собственные типы методов
36. Пример№6 frompeak.rulesimport * @abstract defxmlstr(ob): “Convert any object to XML” @when(xmlstr, (str,)) def xmlstr_nop(ob): return ob
38. Реализация: if elifelifelifelif else? Как в классическом ООП Конфликты Порядок проверок условий Отношения следования assert implies((int, str), (int,)) @when(implies, …)
40. Уникальные возможности Примеры критериев: uri.fragment is not None hasattr(ob, ‘read’) issubclass(A, B) Любые комбинации: isinstance(a, int) and a > 0 В коде выглядит так: @when(func, “issubclass(A, B)”)
41. eval? Нет. Строки разбираются Разбиваются на отдельные условия Приводятся к ДНФ По возможности упорядочиваются Компилируются в байт-код Повторяющиеся условия вычисляются лишь однажды Это отдельный движок (обратно совместимый)
43. Всё – частный случай Объекты и наследование adapt – generic function
44. Еще раз Алгоритмы и структуры данных Взаимодействие в команде Документация Исправление ошибок Изменения и дополнения запланированные неожиданные миграция кода и рефакторинг Организация кода
45. Я ищу программистов на Python Направления работы Веб-сервис платформы (без акцента на SOAP или WS-*) Кросс-платформенные настольные приложения Масштабируемые решения Чего попроще Отличные условия Интересные, толковые проекты