Пора избегать объектно-реляционного сопоставления

TL; DR, Упростите свои программы, избегая использования ORM.

Объектно-реляционное сопоставление или ORM - одна из тех конструкций, которые, как разработчики программного обеспечения, могли бы принести пользу, если бы ее просто никогда не существовало.

Три года назад, разочарованный тем, сколько раз мне приходилось возвращаться к документации ORM Django, Майлз Бирн предложил мне прочитать Вьетнам компьютерных наук. Это был освежающий опыт, который выразил мое отвращение к ORM.

Вьетнам компьютерных наук появился в 2006 году, и он по-прежнему очень актуален. После эффекта Линди он, вероятно, будет оставаться актуальным и через десять лет. Если вы когда-либо взрывали гнев из-за каких-то неожиданных последствий использования ORM, я бы порекомендовал выделить некоторое время в течение следующей недели, чтобы прочитать его и понять структурные ограничения ORM.

Четыре веских причины отказаться от ORM

1. ORM ПОВЫШАЮТ СЛУЧАЙНУЮ СЛОЖНОСТЬ (ПРОСТОЕ НЕ ПРОСТО)

ORM просты в использовании, но они сопряжены с множеством случайных сложностей, которые рано или поздно проявятся в наших программах. В этом случае легко не значит просто.

Случайная сложность в словах Рича Хикки:

Вывод конструкций, которые мы создаем в наших программах, является источником сложности. Мы будем называть эту сложность случайной. Случайные сложности не входили в то, что пользователь просил нас сделать. Мы выбрали инструмент. Ему присуща некоторая сложность. Это связано с проблемой. Я не вставлял здесь определение, но "случайно" на латыни означает ваша вина.

email = User.find(id=1).email

Хорошо, это было легко. Мне просто нужно было получить объектUser к id, а затем получить его адрес электронной почты.

А теперь попробуйте ответить на эти вопросы:

  • Было ли открыто соединение с базой данных при выполнении этой строки кода или оно было открыто ранее?
  • Используем ли мы соединение из пула соединений с базой данных?
  • Сколько данных мы получили из базы данных?
  • Нужны ли нам все данные, полученные из базы данных?
  • Эта строка кода извлекает данные из базы данных или обращается к внутреннему кешу?
  • Если есть кеш, когда он будет обновлен?
  • Эта строка кода автоматически фиксируется в базе данных?

Прочитав эту единственную строчку кода, я не могу ответить ни на один из этих вопросов.

Теперь давайте попробуем ответить на предыдущие вопросы с помощью этого кода:

conn = psycopg2.connect('postrges://...')
with conn.cursor() as cur:
    conn.execute('SELECT email FROM users WHERE id=1')
    email = conn.fetchall()
conn.commit()

Этот фрагмент кода создать сложнее, потому что он требует понимания того, что мы делаем. Но это намного проще, чем предыдущий «однострочный».

Из нового кода мы можем ответить на все вопросы.

Вот еще один пример:

team_names = User.find(id=1).teams.map(team => team.name)

Попробуйте ответить на этот вопрос:

  • Сколько запросов к базе данных делается в этом «однострочном»?

2. ОРМ ВСЕГДА РАЗРЫВАЕТ СВОЙ НЕЯТНЫЙ КОНТРАКТ.

Каждый раз, когда мы вводим зависимость, мы соглашаемся со следующим негласным соглашением:

Привет, разработчик, если ты будешь использовать меня как стороннюю библиотеку, я сделаю тебе жизнь проще:

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

- Я предоставлю такой хороший API и документацию, что вам редко (если вообще когда-либо) понадобится понимать, как я делаю то, что делаю. Поверьте мне, я вас прикрыл.

Неявное ценностное предложение ORM состоит в том, что он абстрагирует все, что связано с данными, с помощью знакомого объектно-ориентированного интерфейса.

Это просто неправда.

ORM не заменяют базы данных. Если и когда нам нужно использовать все возможности базовой базы данных, ORM не справится, что приведет к необходимости писать необработанные запросы к базе данных.

При использовании ORM недостаточно знать, как использовать функцию базы данных. Нам также необходимо знать, как лучше всего реализовать это с помощью DSL (предметно-ориентированного языка). Перемещение между DSL базы данных и DSL ORM - бесполезные накладные расходы.

Когда есть сомнения, нет никаких сомнений.

Если вы в настоящее время используете ORM и не можете от него избежать; при обсуждении того, писать ли необработанный SQL или изучать DSL ORM, вы зашли слишком далеко - всегда используйте необработанный SQL.

3. ORM ЯВНО НАЗНАЧАЕТ БОЛЬШЕ ЦЕННОСТИ КОДА, ЧЕМ ДАННЫЕ

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

Используя ORM, мы беззвучно кричим: «Источником истины является код, а база данных - всего лишь артефакт!»

Это не правильно. Очень неправильно. Между кодом и данными данные являются активом; код - это ответственность. Код - это просто инструмент для предоставления данных различным заинтересованным сторонам. Мы должны принимать архитектурные решения, соответствующие этому взгляду на мир.

4. ORM ОБЪЕДИНЯЕТ СЛИШКОМ МНОГО КОМПЕТЕНЦИЙ

Когда нас продают по ORM, мы обычно покупаем сразу три конструкции:

  • Миграция базы данных
  • Обработка соединений с базой данных с предопределенным или настраиваемым пулом соединений
  • Запросы чтения / записи базы данных с предопределенной или настраиваемой логикой фиксации

Обычно мы размещаем эти три конструкции в том же месте, что и бизнес-логика (код приложения), что особенно болезненно для миграций базы данных.

Размещая миграции в коде приложения, мы связываем жизненный цикл схемы базы данных с жизненным циклом приложения. Заметно хуже, если мы хотим создавать другие приложения на основе той же базы данных (поскольку мы не сможем отделить жизненный цикл нового приложения от цикла, в котором выполняется миграция базы данных).

Построение системы

Сложность в нашем коде - это ответственность. Как разработчики, мы значительно усложняем наш код, используя ORM.

Via negativa (меньше значит больше) : Избегая использования ORM и понимая, какие функции нам необходимо реализовать в наших приложениях, мы можем построить прочную основу для наших инженерная команда. Это открывает более глубокие обсуждения архитектуры, например, следует ли отдавать предпочтение объектам, а не данным, что приводит к более сильной системе.

В этой первой из четырех частей мы выяснили, почему нам нужно избегать использования ORM. В следующих трех частях мы рассмотрим инструменты и дадим практические советы о том, как удалить ORM с помощью миграции базы данных с помощью различных инструментов, самостоятельной обработки соединений с базой данных и управления запросами к базе данных.

использованная литература

  1. Вьетнам компьютерных наук (Тед Ньюард).
  2. Simple Made Easy (Rich Hickey). Расшифровка стенограммы.