Почему не я люблю декораторы и метаклассы

Опубликовано 14 September 2015 в Python

Я не люблю декораторы и метаклассы. Почти любое использование декоратора и любое использование метакласса ухудшает читаемость кода. Их трудно использовать без усложнения кода. Они приводят к трудновыявляемым багам. Так что их использование должно быть обосновано. И их не нужно использовать там, где можно легко и безболезненно обойтись без них.

Если сравнить использование остальных конструкций языка с использованием рогатки, то использование декоратора - это стрельба из пушки, а метаклассы - из системы залпового огня Град. Последствия их неправильного использования влияют на кодовую базу примерно также. Декоратор разламывает несколько функций и методов, метакласс разрывает в клочья несколько классов.

Так как их использовать правильно? И какие основные ошибки? Метаклассы - очень тонкая материя. Для них я не возьмусь давать общие советы. Разве что только один: прежде чем использовать метаклассы, попробуйте решить проблему без них; если не получилось, попробуйте еще раз; и только после этого используйте метаклассы. Ну и перед тем как приступить, сообщите об этом решении остальным членам команды: "Ребята, для этой задачи я вынужден использовать метаклассы."

С декораторами проще. Я стараюсь следовать двум правилам:

  1. Не меняйте интерфейс функции. Будьте людьми, не добавляйте и не убавляйте количество, не меняйте название и порядок принимаемых функцией параметров. Если так нужно сделать, то декоратор - плохая идея. Для обычной функции лучше использовать functools.partial, для метода - написать в классе еще один метод с нужным интерфейсом.
  2. Не превращайте функцию в класс или класс в функцию. Кроме редких случаев делать это плохая идея. Если уж надо обернуть функцию в класс декоратором, то переопределите ему __call__.

И напоследок. Старайтесь делать все проще. Читаемость кода - один из важнейших показателей его качества. Сложные конструкции хороши на собеседовании. В продакшене исповедуйте принцип разумного консерватизма.

---
Возник вопрос? Мне всегда можно написать в Twitter: avkorablev