Orm что это
Orm что это
Так нужен ли ORM в крупном и сложном Enterprise-проекте?
Недавно на Хабре мелькал вопрос — так нужен ли на самом деле ORM в крупном и сложном проекте? Ведь он часто медленный, громоздкий, поддерживает только некоторое подмножество SQL, не поддерживает специфический и очень удобный синтаксис, например, Oracle (тот же connect_by для иерархических запросов) и прочее и прочее.
Высказывалось мнение, что ORM в действительности нужен только в примитивных проектах, для сокращения размера кода, а в реально большом и сложном проекте лучше обойтись без него. Я скажу за большие проекты — за мелкие пусть скажут другие 🙂 Оговорюсь, что рассуждения и примеры строю на Java / Oracle, классическая связка.
Почему необходим ORM
Сам по себе ORM, именно как mapping, в крупных проектах нужен как раз очень сильно.
Представьте себе — у меня есть очень крупная система, и есть в ней таблица orders, на ней скажем, 50 колонок (на самом деле у нас 150, ну да ладно. Нормализаторы, молчать! Про нормальные формы я тоже знаю). И вот надо представьте, что вам выбрать один ордер и показать его на экране. Допустим, вы пишете селект, вопрос — дальше что делать с его результатами, в промежуточном слое, в server-side Java? Вы не же вызываете хранимую процедуру или запрос напрямую с, скажем, JSP страницы (я надеюсь), вам все равно надо получить данные и передать их как-то, в виде какой-то структуры данных.
Так что же, передавать их в виде массива, ArrayList-a, ассоциативного массива как [имя колонки: значение]? Это громоздно, неудобно, и очень легко ошибиться. А если вам надо несколько ордеров, тогда что, создавать вложенные коллекции для конвертации результатов? Это по своему вредному влиянию будет уже напоминать известный антипаттерн «Строковая типизация». Использовать коллекцию векторов или ассоциативных массивов там, где можно использовать коллекцию объектов типа Order.
Мы нашли пример случая, нам нужен объект Order, имеющий все нужные property, и, следотельно, нам нужен код, который умеет конвертировать результаты SQL запроса в объекты (коллекцию таких объектов).
Далее, очевидно, что писать руками все запросы трудно и нудно, легко ошибиться, т.к. в Java они будут представляться или в коде в виде строк (а значит, никакой статической типизации и compile-time проверок), и их надо держать либо в Java коде (если они мелкие, и все равно получается замусоривание Java кода), либо, если побольше, выносить в отдельные XML файлы.
Здесь небольшое лирическое отступление. Спор — держать ли SQL код коротких запросов прямо в Java коде, или же выносить их в отдельные файлы в Enterprise-e идет уже долго.
Аргумент за то, чтобы держать из внутри Java кода — вместе используемый код находится рядом, код SQL запроса легче найти и посмотреть, чем если он лежит где-то отдельно, в случае изменений в VCS надо будет не забыть изменить только один файл, а не два.
Аргумент за разделение по разным классам — многострочные SQL запросы сильно замусоривают Java код (в том числе потому, что Java не поддерживает полноценно многострочные строковые литералы в отличие от, скажем, того же Groovy) + если они определены как константы класса, то при изменении содержимого этой константы сделать java hotswap, например, уже не получится. Я сам обычно смотрю по обстоятельствам 🙂
В общем, ORM в больших проектах нужен для упрощения рутинной части. Без него — никуда 🙂
Почему нужен чистый SQL
Безусловно, обойтись ТОЛЬКО ORM не получится. Есть у нас масса мест, где сложная логика написана в запросах хранимых процедурах в 500-1000 строк на PL/SQL, ибо написанная через ORM /Java она бы занимала в 10 раз больше места и работала в 2 раза медленнее (при этом, она была бы еще и менее понятна, т.к. есть такая логика, которые в терминах реляционной алгебры описывается проще, чем в терминах ООП :), и такая логика ложится на ORM со скрипом). Сколько нибудь сложные запросы с подзапросами, юнионами, хитрыми джойнами тоже писать через чистый ORM громоздко. Оптимизировать запросы, работающие с таблицами где, хотя бы, несколько сотен миллионов записей, без доступа к планам SQL оптимизатора и статистики/средствам мониторинга уровня СУБД (для Oracle это Explain Plan, tkprof, Grid Control) тоже крайне сложно. Так что без SQL тоже — никуда 🙂
Можно поговорить о том, как все-таки немного подсластить работу с чистыми SQL-запросами в крупном проекте.
ORM или как забыть о проектировании БД
От автора
Что такое ORM?
Прежде чем учить кого-то уму-разуму стоит понять что представляет из себя термин ORM. Согласно аналогу БСЭ, аббревиатура ORM скрывает буржуйское «Object-relational mapping», что в переводе на язык Пушкина означает «Объектно-реляционное отображение» и означает «технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования»… т.е. ORM — прослойка между базой данных и кодом который пишет программист, которая позволяет созданые в программе объекты складывать/получать в/из бд.
Все просто! Создаем объект и кладем в бд. Нужен этот же объект? Возьми из бд! Гениально! НО! Программисты забывают о первой буковке абравиатуры и пхнут в одну и ту же табличку все! Начиная от свойств объектов, что логично, и, заканчивая foreign key, что никакого отношения к объекту не имеет! И, что самое страшное, многие тонны howto и example пропагандируют такой подход… мне кажется что первопричина кроется в постоянной балансировке между «я программист» и «я архитектор бд», а т.к. ORM плодятся и множатся — голос программиста давлеет над архитекторским. Все, дальше боли нет, только imho.
«Кто Вы, Мистер Брукс?» или «Что такое объект?»
Тяжкое наследие ООП
Критикам посвящается
После высказывания своих мыслей руководителю я получил вполне ожидаемую реакцию: «Зачем так усложнять? KISS!»
Пришлось «набраться опыта»:
Были случаи с циклическими связями между объектами содержащими среди свойств fkey и задачей «бекапа/сериализации» этого безобразия в xml/json. Нет, бекапы то делаются, вот восстанавливать потом это безобразие чертовски сложно… необходимо жестко отслеживать какие свойства создаются при восстановлении/десериализации, а потом повторно проходить по объектам и восстанавливать связи между ними. Придерживаясь правила выше — надо сначала восстановить объекты, а уж потом связи между ними. Т.к. хранится эта информация в разных таблицах/сущностях — логика была линейной и простой.
На каждый выпад «возьми монгу и не парься» или «документо-ориентированые бд рулят» я всегда приходил к одному и тому же результату который еще никто покрыть не смог:
Я смогу создать схему в реляционной бд которая будет сохранять произвольную структуру данных (произвольные документы), а вот сможете ли вы в документо-ориентированой бд гарантирвать целостность данных на уровне реляционых бд? Я не смог достич такого уровня.
Никого не смущает множественные куски повторяющихся документов с произвольным уровнем вложенности? Не, я знаю что их хранение оптимизировано и вобще, тебе какая разница? Но все же.
SERM, ORM и HM: что это такое, в чем разница и особенности работы с репутацией по каждому направлению
Последние мировые события заставили многих предпринимателей и маркетологов, которые до этого года игнорировали продажи и представление бренда в интернете, обращаться за услугами по управлению репутацией.
Нам поступают запросы представить бренд в интернете, улучшить рейтинг на конкретных отзовиках, рассказать о новом товаре, улучшить выдачу или убрать из выдачи поисковиков негативную публикацию о бренде, компании или персоне и т.п. Все эти заявки поступают на услугу SERM.
Только в ходе обсуждения проекта мы выясняем, действительно ли клиенту нужен SERM или же он имел ввиду ORM или HM. В связи с этим и возникла идея написать статью, в которой подробно, но самыми простыми словами объяснить разницу между ORM, SERM и HM. Расписать плюсы и минусы каждого направления по управлению репутацией и их особенности.
Агенты влияния работают в социальных сетях, на форумах, в блогах, в комментариях под статьями, отзывами, на сервисах вопросов и ответов. Они советуют, обсуждают, сравнивают и спрашивают о предмете продвижения, управляют диалогами, формируют мнение так искусно, что, порой, догадаться, что здесь и сейчас проходят работы по скрытому маркетингу, невозможно.
Новым брендам или продуктам, выходящим на рынок. Успешно работает для любого направления бизнеса.
Целью управления репутацией в интернете является поиск и нейтрализация негативных публикаций, а также публикация хороших упоминаний для формирования положительного восприятия бренда. В идеале, еще и оптимизация положительных публикаций для повышения позиций в поисковой выдаче.
Существует два принципа работы: машинный и ручной.
Через сервисы мониторинга упоминаний о бренде товаре или услуге можно отслеживать новые комментарии. Сервисы сканируют определенные сайты каждые 10-15 минут и оповещают о новых отзывах. Вся полученная информация сортируется и анализируется. После специалист по репутационному маркетингу пишет комментарии, отвечает на запросы пользователей и отзывы, подсказывает, как решить возникшие проблемы. Добавляет положительные отзывы.
Согласовываются определенные площадки, на которых будут отслеживаться появление новых сообщений и отзывов. Специалист по репутационному маркетингу с оговоренной частотой просматривает сайты, пишет комментарии, отвечает на запросы пользователей и отзывы, помогает разрешить проблемы. Добавляет положительные отзывы, чтобы поддерживать рейтинг на оговоренном уровне.
Бывает, что агентства или фрилансеры недобросовестно относятся к размещению положительных отзывов и публикуют похожие или даже одни и те же на разных сайтах с одного компьютера и IP.
Администраторы рекомендательных сервисов мгновенно распознают фейковые отзывы по IP, характеристикам системы и прочим параметрам. В лучшем случае просто удаляют заказные отзывы, но все чаще стали помечать такие отзывы “метками позора”. Каждый пользователь, который посмотрит отзывы перед решением о покупке, будет знать, что компания сама пишет положительные отзывы и доверять им не стоит.
Поэтому, приняв решение о публикации положительных отзывов через фрилансеров или агентства, рискуете не улучшить репутацию, а окончательно ее загубить. Советуем детально проговорить все вопросы, связанные с размещением положительных отзывов и следить за исполнением договоренностей.
Любому бизнесу в сегменте B2C и для B2B-компаний вне зависимости от области ведения бизнеса. ORM подходит также общественным и политическим деятелям, узконаправленным специалистам.
Вытеснить негативные публикации из выдачи поисковых систем, заполнив выдачу положительными упоминаниями.
Первым делом необходимо определиться с поисковыми запросами, по которым и будут проводиться мероприятия по управлению репутацией в поисковых машинах. После этого сделать мониторинг по каждому поисковому запросу и определить тональность публикаций. Существует множество сервисов, которые формируют списки URL в топ 10-250 выдачи Яндекс и Google. Также есть сервисы, которые определяют тональность публикаций, но с очень высокой погрешностью. Поэтому определять тональность лучше вручную.
После того, как выявили все негативные и нейтральные публикации в выдаче поисковиков, начинаются работы над увеличением количества положительных упоминаний и вытеснения негативных за пределы топ 10-30. 50.
К сожалению, большинство предпринимателей и маркетологов не понимают, что же это такое SERM, предполагая, что достаточно заказать положительные отзывы и проблема с негативом в поисковиках решится сама собой.
Вот лишь часть работ, которые проводятся в рамках услуги по управлению репутацией в поисковой выдаче:
Список можно продолжать, причем регулярно появляется новый инструмент, который влияет на выдачу поисковых систем. Из перечня мероприятий, проводимых в рамках услуги по SERM, видно, что в него входят работы по ORM, HM и PR маркетингу.
SERM подходит абсолютно любому бизнесу или персоне без исключений.
Если тезисно объяснить разницу между ORM, SERM и HM, то это будет выглядеть так:
Назовите пожалуйста сервисы для работы с SERM (мониторинга выдачи и определения тональности) Заранее спасибо!
Тональность, прямо очень желательно, определять глазками. Ни один сервис не работает без погрешностей и поэтому, все равно, приходилось перепроверять каждую ссылку.
Отслеживать новые упоминания можно на этих сервисах (информацию собирали и анализировали месяца 4 назад. Цены сейчас могут отличаться):
1. Google Alerts – система оповещений Google https://www.google.ru/alerts
Мгновенные извещения о новых публикациях в интернете по заданным запросам. Уведомления приходят на почту. Настраивается до 1000 оповещений. Можно выбрать частоту отправки, язык и страну поиска, источники поиска (новости, форумы, соцсети, блоги и пр).
2. Babkee – система мониторинга социальных медиа и СМИ http://www.babkee.ru/
Сервис собирает и обрабатывает упоминания с названием компании, сайта или бренда. Отчет формируется в графике с частотой упоминания, тональностью, площадки, указывается возраст и пол автора. Сервис бесплатный.
3. Brand Analytics – система мониторинга и анализа бренда в социальных медиа и СМИ https://br-analytics.ru/
Сервис Brand Analytics ищет публикации о бренде, персоне, даже событии, товаре или услуге в социальных медиа и онлайн-СМИ. Результат мониторинга выдается в виде графиков и отчетов, в которых отражены горячие обсуждения и свежие публикации, автоматически определяется тональность сообщений. Демонстрационный доступ на 7 дней. Далее придется платить от 700 до 94 000 руб в месяц.
4. Репутометр – сервис мониторинга репутации онлайн http://reputometer.ru/
Сервис отслеживает появление новых материалов по репутационным запросам. Мониторит отзывы и комментарии в поиске Яндекс и Google. Присылает уведомления при появлении новой информации. Отчеты показывают изменения доли негативной информации с ходом времени. Есть «Бесплатный» пакет для ознакомления с сервисом, «Стандарт» за 10$ и профессиональный «Агентство» за 100$.
5. BrandSpotter – мониторинг социальных медиа, аналитика, реагирование и управление репутацией https://youscan.io/ru/
Сервис мониторит социальные сети, микроблоги, форумы, в том числе англоязычные, ищет публикации о бренде и продукте на территории Украины, Узбекистана, Казахстана. Сервис находит позитивные и негативные высказывания, определяет слова, которые упоминаются вместе с названием бренда наиболее часто. Бесплатный тестовый доступ в течение 7 дней. Далее тарифы от 29 830 до 114 460 рублей в месяц.
6. Repometr – Система автоматического мониторинга отзывов о компании
Бесплатный сервис собирает отзывы о компании только с Google и Яндекс карт, Yell, Zoon и 2GIS. Сервис собирает отзывы и оценки в одном интерфейсе. Можно формировать отчеты и получать их автоматически.
7. SemanticForce – система мониторинга и анализа онлайн-медиа в режиме реального времени https://semanticforce.net/ru/
Платная система мониторнга для всех соц. медиа и онлайн-СМИ. Система фильтров для поиска, в том числе по стране, региону, языку, тональности и поиск по конкретным рубрикам. Отчеты предоставляют в виде интерактивных графиков, таблиц, которые можно экспортировать в Excel.
8. IQBuzz https://iqbuzz.pro/
Сервис, который мониторит новостные ленты, соцсети и блоги. Это платный инструмент и количество компаний, которые сервис может анализировать, зависит от купленного тарифа. Вся информация хранится в архиве и не уничтожается. Статистика формируется по полу и возрасту авторов комментариев.
9. YouScan https://youscan.io/ru
YouScan отслеживает публикации в новостях, блогах и соцсетях. Сервис платный. Статистика формируется по полу и возрасту авторов отзывов. Имеет похожий функционал с IQBuzz, но интерфейс более корявый. Из преимуществ в базе есть площадки, которых нет в IQBuzz.
10. «Крибрум» http://www.kribrum.ru/
Сервис мониторинга социальных сетей отслеживает и анализирует упоминания бренда, продуктов, услуг и персон. Сервис автоматически создает отчеты, в которых указаны отзывы и их эмоциональная окраска. Информация предоставляется в виде графиков.
11. Starcomment – отслеживание комментариев и мониторинг информации в социальных сетях. https://starcomment.io/
Starcomment мониторит сообщения и отзывы во Вконтакте, Инстаграм, Одноклассники, Фэйсбук, Твиттер и youtube. Моментальные уведомления приходят на e-mail и в Telegram. Стоимость от 290 до 1 900 руб в месяц. Сервис доступен бесплатно в течение 5 тестовых дней.
12. Медиалогия – мониторинг упоминаний брендов в сомедиа https://www.mlg.ru/
Сервис следит онлайн за всеми упоминаниями по любым темам, брендам, блогерам. Есть автоматическая оценка тональности упоминаний и ручная оценка. Использует лингвистический модуль для анализа ключевых тем соцмедиа. Фильтр сообщений по дате, аудитории, просмотрам, вовлеченности и темам. 7 дней бесплатно. Далее от 20 000 до 80 000 рублей в месяц.
13. SmiMonitor – Центр мониторинга и анализа СМИ
Полный мониторинг репутации в СМИ: интернет, ТВ, радио, журналы, переодические издания. Анализируется и архив вещания ТВ и радио. Заявки рассматриваются в индивидуальном порядке. В отчете представляют информацию по тональности, частотности и цитируемости продвижения.
14. ПрессИндекс – Мониторинг и анализ СМИ
Сервис отслеживает сообщения о бренде в СМИ, соцмедиа, глянце и других пиар-публикациях. Формируют статистику в виде графиков с эмоциональным окрасом упоминаний. Отчеты приходят по SMS или e-mail. Есть контроль активности конкурентов и оценка осведомленности о бренде. Стоимость рассчитывается индивидуально, по запросу. Можно заказать бесплатный тестовый мониторинг.
ORM: почему эта задача не имеет решения, но делать с этим, тем не менее, что-то нужно
Современные информационные технологии поражают своей мощью, ошеломляют открывающимися возможностями, обескураживают заложенным в них техническим совершенством, но есть один смехотворный пункт, об который IT раз за разом снова и снова ломает зубы. Показать пользователю данные из базы, получить от него ввод, положить обратно в базу, показать результат. Поля ввода, кнопочки, галочки, надписи — казалось бы, что в них может быть такого запредельно сложного, чтобы потребовалось городить головоломные конструкции типа фреймворков поверх шаблонизаторов поверх фреймворков поверх транспайлеров? И почему несмотря на все колоссальные усилия мы имеем то, что игрушечные примеры по туториалу, конечно, делаются легко и приятно, но как только инструментарий сталкивается с реальными задачами реальной жизни… как бы это сказать помягче… с ростом сложности решаемых задач наблюдается сильная нелинейность возрастания сложности реализации. Ладно бы речь шла о чём-то действительно головоломном уровня теоретической физики или космической техники, так ведь нет же — кнопочки и галочки. Почему эта ерунда десятилетиями продолжает отравлять жизнь гражданам и трудовым коллективам?
Причин, наверно, как всегда оно бывает, много. Наверно все они так или иначе достойны рассмотрения, но здесь и сейчас мы поговорим о задаче объектно-реляционного отображения (Object-Relational Mapping, ORM), которая всегда в каком-либо виде стоит за всеми этими «кнопочками и галочками».
Что мы знаем про ORM
Почему всё так причудливо
Идейная основа теории и практики реляционных баз данных — исчисление предикатов, то есть раздел математики. Что касается ООП, то аналогичная по прочности идейная основа там отсутствует. Базовую идею ООП можно попытаться сформулировать примерно так: поскольку мир состоит из объектов, то его, этот мир, было бы удобно моделировать созданием объектов внутри программной системы. В этом понимании сразу две ошибки. Во-первых, мир сам по себе не состоит и никогда не состоял из объектов. Во-вторых, извините, но зачем программа обязательно должна моделировать мир? То есть мы имеем концептуально неверное утверждение, прекрасно дополняемое бессмысленной постановкой задачи.
Всякий ORM – попытка чётко протянуть унифицированное соответствие между, по сути, разделом математики и рыхлым набором разнообразных практик, основанном на соображениях удобства, исторически сложившихся подходах, а также зачастую на легендах, мнениях авторитетов, да и просто заблуждениях. In vitro это можно заставить работать, но in vivo оно обречено выглядеть жалко и приносить больше горя, чем радости.
О неизбежности объектной ориентированности
Тем не менее, необходимость объектной ориентированности нашего софта — наша неизбежная реальность. Неизбежность эта основана в первую очередь на том, что оперирование объектами составляет суть и основу любой нашей деятельности. Мир сам по себе не состоит из объектов, но для того, чтобы что-то в этом мире понять и что-то с этим миром сделать, мы сами для себя объявляем его части объектами, называем их именами, пытаемся понять их поведение, прикладываем к ним усилия для получения желаемых результатов. Это наш способ функционирования, и уйти от него невозможно, да и не нужно. Всё есть объект не потому, что так оно и есть на самом деле, а потому, что мы по-другому не можем. То, что никоим образом не может являться объектом, полностью лежит за пределами нашей способности осмысления и не может служить предметом приложения наших усилий.
Даже если программа написана без использования техник ООП, в ней неизбежно присутствуют объекты (в широком смысле этого слова), манипулируя которыми разработчик решает свою задачу — переменные, типы данных, операторы, алгоритмы, синтаксические конструкции, функции, модули. С точки зрения пользователя программа тоже есть набор объектов, с которыми он взаимодействует — кнопки, надписи, поля ввода, страницы, сайты, да и вся система целиком.
Что мы храним в своих базах данных
Как говорилось выше, реляционные базы данных основываются на исчислении предикатов. Предикат — это сформулированный и в нашем случае сохранённый на носитель факт. На всякий случай замечу, что реляционность базы данных — это не только и не столько про связи между таблицами по внешним ключам. В правильной терминологии отношениями (relations) называется то, что мы по-простому называем таблицами. То есть даже если в вашей базе всего одна таблица с двумя колонками (например, имя и номер телефона), у вас уже реляционная база, устанавливающая отношение между двумя множествами, в данном случае множествами имён и номеров телефонов. Реляционная база не хранит объекты, она хранит факты. Хранимые факты, конечно же, имеют предмет («о чём этот факт?»), и когда мы пытаемся научить систему отвечать на этот вопрос, у нас появляются сущности, то есть объекты, с которыми связаны факты. Если работать правильно, структура базы у нас рождается из серии ответов на вопрос «какого рода факты мы намерены сохранять?», и лишь на следующем этапе у нас появляется нечто, напоминающее объекты, придающие фактам предметность. Можно, конечно, проектировать и «от объектов», но я бы не рекомендовал так делать иначе как на лабораторных работах по предметам, не связанным напрямую с проектированием баз данных. Слишком велика опасность тяжёлых архитектурных просчётов. Кроме того, это как минимум неудобно.
Небольшое лирическое отступление про объектные базы данных. Очень простая мысль: если мы устали от проблем с ORM, то, может быть, нам сделать что-нибудь с той его частью, которая «R»? Пусть наша база данных будет не жёстким и требовательным реляционным чудовищем, а чем-нибудь модным молодёжным, специально заточенным на хранение объектов. Какая-нибудь бессхемная NoSQL-база, например. Но в конечном итоге внезапно оказывается, что NoSQL-ные ORM ещё кривее и противоестественнее, чем старые добрые SQL-ные. Да и вообще, иметь и с удовольствием эксплуатировать бессхемную СУБД мы можем, но бессхемных данных в природе не бывает. Нет ничего более беспомощного, безответственного и безнравственного, чем ORM для бессхемных баз данных.
Хороший ORM
Хороший ORM – отсутствующий ORM. Ну серьёзно. Посмотрите на любую из своих использующих ORM систем и честно попытайтесь ответить себе на вопрос: какие профиты приносит этот монстр? Чем обусловлено его применение кроме как несбывшимися обещаниями счастья и многократно дискредитировавшими себя предрассудками? Безусловно, найдутся некоторые полезные удобняшки, но что они на фоне привносимых архитектурных деформаций и постоянно возникающих на ровном месте проблем с производительностью?
Как правило, «низкоуровневый» API базы данных прост, удобен, полн и консистентен. Обычно хватает пальцев рук для того, чтобы перечислить все функции. Выучить их — не бог весть какая задача.
Попробую набросать набор архитектурных принципов, позволяющих замэппить объекты на базу данных без использования ORM:
Итого
ORM – очень больная для нашей индустрии тема. В эпоху, когда облачный искусственный интеллект бороздит просторы квантового блокчейна, подавляющее большинство трудовых ресурсов занято прикручиванием бизнес-логики и пользовательского интерфейса к базам данных. Миллионы строк ужасного кода, забивание гвоздей микроскопами, боль и отчаяние повсеместно сопровождают этот творческий процесс. Один из корней этого печального положения дел — чрезвычайно стойкое заблуждение, что универсальный ORM в принципе возможен. А он невозможен, и этому есть фундаментальная причина, не подлежащая устранению. Осознание этого факта — первый шаг по направлению к выходу из этого кошмара. Выход — возможен, альтернативы — есть, но сначала — осознать, прочувствовать и научиться держать в фокусе внимания.
Обзор ORM для C#: что подойдет для проекта
Одна из проблем использования языков объектно-ориентированного программирования (ООП) и баз данных в сложности их согласования между собой. Знание языка структурированных запросов (SQL) и умение писать запросы позволяют взаимодействовать с БД напрямую. Но использование «чистого» SQL может занять довольно много времени, предъявляя повышенные требования к навыкам специалиста.
Облегчить рабочий процесс может объектно-реляционное отображение (ORM). Сторонники этой технологии заявляют, что она повышает производительность, улучшает архитектуру приложений, повторно использует код и поддерживает приложение с течением времени. По мнению критиков, отрицательным аспектом ORM является производительность.
В этой статье наше backend-направление расскажет про ORM на базе C#, плюсы и минусы этой технологии, чтобы оценить ее полезность при разработке приложений. Материал предназначен для разработчиков, желающих погрузиться в принципы подбора ORM.
Что такое ORM?
ORM — это технология программирования, которая создает слой между реляционными базами данных и объектно-ориентированными языками программирования без необходимости написания SQL-запросов.
Отображение стандартизирует интерфейсы, сокращая количество шаблонов и ускоряя время разработки.
Технология преобразует множество состояний и кодов, создавая структурированную карту, которая помогает разработчикам лучше ориентироваться в структуре базы данных.
Рис. 1 Основной принцип работы ORM
Отображение объясняет, как объекты связаны с разными таблицами, используя эту информацию для преображения данных между ними. ORM генерирует код SQL для реляционной базы данных (вставка, обновление, создание и удаления данных) в ответ на изменения, которые приложение вносит в объект данных. Сопоставление ORM будет управлять потребностями приложения в данных, избавляя от написания низкоуровневого кода.
Как работает ОRМ?
ORM выстраивает модели объектно-ориентированной программы с высоким уровнем абстракции. Другими словами, она создает уровень логики без основных деталей кода. Отображение описывает отношения между объектом и данными, не зная, как эти данные структурированы. Далее модель можно использовать для подключения приложения к коду SQL, который необходим для управления операциями с данными. Этот «сантехнический» тип кода не нужно переписывать, что значительно экономит время разработки.
Типы ORM
ORM используют две разные стратегии: шаблон активной записи и шаблон отображения данных.
Шаблон активной записи (Active record). Эта стратегия сопоставляет данные со структурой объектов в коде. Разработчик управляет данными, используя классы и структуры. У этого метода есть проблемы, поскольку структура базы данных тесно связана с кодом, это затрудняет удаление базы данных и перенос ее в другое приложение.
Шаблоны отображения данных. Шаблон разделяет бизнес-логику и БД в объектах. В результате становится проще изменять базы данных и использовать одну и ту же логику программирования.
Плюсы и минусы ORM
ORM избавляет разработчиков от написания большого количества кода и необходимости работы с SQL, как правило, однообразного и подверженного ошибкам. Весь генерируемый ORM код выверен и оптимизирован, поэтому в целом не требует дополнительного тестирования.
К основным минусам можно отнести потерю производительности. Большинство ORM обрабатывают гораздо больше сценариев использования данных, чем нужно каждому отдельному приложению.
Чаще вопрос о целесообразности использования ORM затрагивается в больших проектах с высокой нагрузкой. Конечно, работа с БД посредством грамотно написанного SQL-кода будет намного эффективнее, но не стоит забывать и о времени, которое может сэкономить вам ORM. Кроме того, большинство современных объектно-реляционных отображений позволяют разработчику при необходимости самому задавать код SQL-запросов. Без сомнений, для небольших проектов использование ORM более оправдано, чем разработка собственных библиотек для работы с БД.
Мы провели опрос среди разработчиков SimbirSoft и узнали, как часто они используют ORM на проектах. Вот что получилось:
В нашей команде ORM-системы довольно популярны и часто применяются на проектах: за них проголосовали 80,8%, против — 19,2%. Наши разработчики также отмечают, что ORM-системы эффективны в случаях, когда система не высоконагруженная и когда необходим быстрый запуск типового решения.
Обзор ORM
Итак, мы познакомились с общим понятием ORM-систем, принципом их работы, теперь рассмотрим некоторые из них более подробно.
Если необходимо расширить код и сделать его более функциональным, то EF Core позволит это осуществить, благодаря открытому исходному коду и расширяемого ядра.
С EF Core, как и с другими ORM, разработчики могут использовать свои базы данных, включая объекты C#. Это отличная новость для тех, кому часто приходится писать весь необходимый код доступа к данным с нуля при работе на других языках.
Самостоятельное написание такого кода доступа к данным может оказаться сложной задачей. Реляционные БД отображают информацию в виде таблиц, например, электронных. Объектно-ориентированные языки, такие как C#, представляют свои данные в виде графиков.
Часто отладить работу кода и данных бывает затруднительно. Отсюда и необходимость в ORM. Такие инструменты, как EF Core, берут модель данных, состоящую из объектов C#, и преобразуют ее в реляционную форму, отражающую схему реляционной БД.
Эта микро-ORM приобрела большую популярность и даже была включена в качестве опции ORM в Visual Studio при создании нового проекта. Одним из ее преимуществ является функциональность маппера, которая во многом похожа на LINQ в ядре EF, а также предоставляет методы расширения, упрощающие отправку операторов T-SQL в базу данных.
В науке микроуровни — это очень маленькие единицы мышления и коммуникации, а макроуровни — более крупные. Мезоуровни лежат где-то посередине.
Если Dapper — это микро-ORM, а EF — макро, то с архитектурной точки зрения LINQ to DB — это мезо-ORM. Она позволяет работать с выражениями LINQ в отличие от строк SQL или T-SQL, сохраняя при этом тонкий слой абстракции между кодом и базой данных. Запросы основаны на объектах и поэтому проверяются компилятором C#. LINQ to DB гораздо легче, чем LINQ для SQL или Entity Framework. В LINQ to DB нет отслеживания изменений, поэтому важно выявлять их самостоятельно. Однако эта ORM обеспечивает усиленный контроль и гораздо более быстрый доступ к данным — у Dapper он самый быстрый из всех ORM на основе LINQ.
Одной из ее значимых особенностей является реализация автоматического интерфейса.
Рассмотрим кейс одного из наших заказчиков, где бизнес-логика (БЛ) была написана на SQL. Со временем проект развивался и бизнес-логика разрасталась, многократно усложнялась — появилось множество нюансов, разновидностей, особенностей поведения сущностей и др. В результате к началу совместной работы БЛ стала практически неподдерживаемой, так как SQL — упрощенный язык, там нет возможностей для ООП. В проекте гибкая бизнес-логика имела большее значение, чем быстродействие системы. С учетом этого мы решили постепенно переписывать бизнес-логику на C# + Entity Framework (EF).
Иногда ORM может показаться огромной неповоротливой машиной. А если использовать методы-расширители, то возникает ощущение неполноты (меньше кода, чем в той же EF).
Рассмотрим пример с обновлением ID пользователя. В первом случае обновление умещается в 1 строку кода.
В Entity нужно создать контекст, заложить операцию, далее уничтожить контекст (но это лучше делать через using). Кроме того, нужно учитывать все, что находится в ChangeTracker:
Заключение
ORM-системы позволяют ускорить разработку, улучшить читаемость кода и его эстетическую сторону, но каждый инструмент следует применять только там, где это действительно необходимо.
Спасибо за внимание! Надеемся, что наш опыт вам пригодится.
Что такое антикризисный ORM и почему он пришел на смену обычному SERM
Боитесь негативных отзывов и пытаетесь манипулировать поисковой выдачей? Разбираемся, почему это не работает и как быть.
Основатель международной группы компаний Reputation Earth
Эксперт в области удаления информации, кризисного реагирования. Создатель online-сервисов: digitalsharks.ru — удаление информации, leveli.ng — полезные ответы на отзывы.
SERM умер, да здравствует AORM
Как без манипуляций управлять репутацией бренда, чтобы избежать негатива
Если негатив попадает в поисковую выдачу, это всегда проблема. Но в кризисные моменты, когда топ забит нелестными упоминаниями бренда, дело осложняется. Требуются большие усилия, чтобы ответить всем авторам, показать своё видение ситуации и рассказать, как решаются проблемы.
В идеале так нужно делать, но иногда выбирают более лёгкий путь — вложить деньги в SERM.
Что такое SERM и почему к нему столько вопросов
Если коротко, SERM — это манипуляция поисковой выдачей в пользу бренда. Копирайтеры быстро пишут статьи, отзывы и посты, а оптимизаторы всеми правдами и неправдами выводят их в топ поисковиков.
Формально эти материалы отвечают требованиям «Яндекса» и Google, но совсем не интересны пользователям. А если какой-то текст нужен только поисковым роботам, он всегда проиграет тем, которые читают живые люди.
Чтобы позитивные материалы оставались в топе, их поддерживают искусственно. Это требует значительного бюджета — сотен тысяч рублей в месяц, а в запущенных случаях и того больше.
SERM в кризис — попытка скрыть негатив, вывесив перед пользователями имитацию позитивного имиджа.
Это напоминает логику некоторых региональных чиновников перед визитом московского начальства. Известно, что высокий гость проедет по центральной и прилегающим улицам, но вот беда: там полно аварийных домов. «А давайте распечатаем на полотне изображения отремонтированного здания и повесим их на „аварийку“. Заболтаем проверяющего, он и не успеет понять, в чём подвох», — предлагает кто-то. И его поддерживают.
Что такое репутационный кризис
Под кризисом я понимаю любой негативный инфоповод: отзыв о плохом сервисе или репортаж о проблемах бренда, попавший в СМИ. Это точка трансформации, ведущая или к обновлению, или к смерти.
Смерть в данном случае — это конец карьеры (Харви Вайнштейн) или закрытие бизнеса даже с вековой историей (News of the World или Thomas Cook). А обновление — качественные изменения, подразумевающие, что больше таких ошибок допущено не будет.
Boeing впервые с 1997 года понесла рекордные убытки из-за проблем с моделью 737 MAX, а глава корпорации ушёл в отставку. Но это не конец: компания взяла курс на обновление и заявила, что усилит контроль на производстве.
Бренд электронных сигарет Juul получил много критики, поэтому отказался от позиционирования для подростков и агрессивной рекламы. После этого мнение о нём стало более позитивным.
В этой истории Boeing и Juul объединяет стремление исправить ошибки, показать аудитории, что им можно доверять. Это и есть антикризисный ORM (online-reputation management), или AORM.
Если SERM стремится скрыть проблемы, то антикризисный ORM берёт контроль над ситуацией, выводит её в позитив.
Стратегия AORM может применяться на всех трёх этапах кризиса:
Репутационный кризис — это индикатор, что в бизнесе не всё работает как надо. Ситуацию можно изменить или игнорировать, но второй путь неизбежно ведёт к стагнации.
Антикризисный ORM показывает аудитории, что бренд выбрал путь изменений и поэтому заслуживает доверия и поддержки.
Антикризисная коммуникация на примере «ВкусВилла»
В 2018 году Роспотребнадзор возбудил административное дело против сети магазинов здорового питания «ВкусВилл». Ситуация была серьёзной: ведомство вынесло 147 постановлений о штрафах на сумму 6,3 млн рублей.
Давайте разберём шаги разных сторон, связанные с антикризисной коммуникацией. Обратите внимание: мы просто смотрим, что было сделано, а не выносим приговор.
Расстановка сил
Вероятно, «ВкусВилл» не переживал подобных кризисов с 2009 года. Проблема ещё и в условном «сопернике» — мало кто в такой ситуации решится действовать против Роспотребнадзора. Потому что это государственный регулятор, а в общественном сознании бытует чёткое мнение: если там что-то решили, значит, так и есть.
Но бизнес и не стал бороться против Роспотребнадзора. Вместо этого PR-отдел компании сконцентрировался на удержании клиентов.
Активная стадия кризиса
«ВкусВилл» выпустил в своём блоге статью «Мы любим Россию!». В материале компания рассказала о своих стандартах: как отбираются продукты и какой путь они проходят перед тем, как попасть на полки. Но самое интересное здесь — это комментарии к материалу о проверке Роспотребнадзора.
Оказывается, основные замечания связаны с тем, что продукция слишком натуральная. В продуктовой линейке «ВкусВилла» просто нет консервантов, красителей, ароматизаторов и так далее. Поэтому даже небольшое нарушение процедуры забора проб на анализы по микробиологии в магазинах может привести к неверным результатам.
Иными словами, результаты ведомства только подтвердили покупателям высокое качество продукции ретейлера.
Далее в тексте сравнили технологии «ВкусВилла» и Роспотребнадзора. Результат оказался не в пользу ведомства. Правда, с некоторыми замечаниями сеть согласилась и отметила, что устранит нарушения. Но было заявлено, что добавлять в продукцию консерванты, чтобы исправить ситуацию с микробиологией, «ВкусВилл» не намерен.
Посткризис
Бренд сохранил лояльность клиентов. Статью прочитали почти 90 тысяч раз — отличный показатель для корпоративного блога. Компания продолжила работу, получив опыт противодействия кризису. Была создана специальная страница на сайте, где подробно рассказывается о контроле качества.
У аудитории всегда есть запрос на альтернативную точку зрения. Клиенты её получили, и мнение ретейлера уравновесило позицию Роспотребнадзора.
В этой ситуации, невзирая на мнение государственного регулятора, потребители поддержали доводы бренда. С точки зрения антикризисного ORM ход оказался абсолютно верным.
Как это работает в малом бизнесе
Часто можно услышать: «На международном уровне нормально видеть крутую стратегию антикризисного управления репутацией. Но всё это не для России, не для нашего малого и среднего бизнеса». Я совершенно не согласен с этим мнением.
Антикризисный ORM — это про подход к решению проблем. А вопрос с выбором инструментов здесь вторичен.
Возьмём ещё реальный случай, с которым столкнулся знакомый ресторатор из Москвы.
Как всё начиналось
Случилась неприятность — несколько гостей ресторана отравились. У пострадавших есть чеки и заключение врача, они оставили негативные отзывы. Ресторан не сетевой, поэтому вопрос репутации для него стоит критически остро.
Чтобы предупредить надвигающийся кризис, рестораторы объясняют сотрудникам возможные риски, рассказывают, как себя вести и что говорить клиентам. Бизнес готовится противостоять ситуации.
Активная стадия
Было решено, что нужно начать с извинений. Представитель ресторана лично связался с каждым пострадавшим, побеседовал, предложил помощь и рассказал, как выявляется причина отравления. Важный момент: это была не разовая акция, связь поддерживалась на протяжении всей болезни клиентов.
На каждый отзыв и пост в соцсетях дали комментарий: «Расследование проводится, пострадавшим предложили помощь». На все вопросы отвечал официальный представитель ресторана, подробно и обстоятельно.
Было решено не выносить тему с отравлением в медиа — там для этого не было создано контекста.
Действия после кризиса
С каждым пострадавшим удалось прийти к примирению: где-то просто извинились, а кому-то выплатили компенсацию. На подконтрольных социальных площадках рассказали о результатах проведённого расследования. Оказалось, что в инциденте виноваты производители продукции, с ними прекратили сотрудничество.
На последнем этапе пострадавших попросили удалить негативные отзывы о случившемся. Они согласились, ведь ситуация исправлена.
Это был сравнительно лёгкий вариант развития событий. А если предположить, что информация оказалась в СМИ и вся эта история попала к блогерам? В таком случае стоило сделать официальное заявление, чтобы авторы дополнили материалы. А на посткризисном этапе — выпустить рассылку с подробными результатами расследования.
Репутацию создаём мы сами. Никакое агентство не будет за вас разбираться с продуктами, общаться с потерпевшими и договариваться с ними о тех или иных действиях.
Подытожим
Традиционный SERM стремится манипулировать выдачей, работая против поисковых роботов и интересов простых пользователей. Это замкнутый круг:
Неприятности с репутацией могут случиться даже при самом добросовестном подходе к делу, от этого никто не застрахован. Для бренда важно в любой ситуации стараться урегулировать проблемы и исправить их. Поэтому антикризисный ORM — это стратегия ответственного бизнеса. Выигрышная и единственно правильная.
* Решением суда запрещена «деятельность компании Meta Platforms Inc. по реализации продуктов — социальных сетей Facebook* и Instagram* на территории Российской Федерации по основаниям осуществления экстремистской деятельности».
Search Engine Reputation Management — управление репутацией в поисковых системах. Комплекс мероприятий для исключения из поисковой выдачи негативных сигналов, очерняющих репутацию бренда, фирмы или продукта.
Проверка благонадёжности контрагента — распространённый в деловом обороте процесс сбора и анализа доступной информации о юридическом лице или индивидуальном предпринимателе. Позволяет задолго до начала совместной деятельности с контрагентом оценить перспективы возможного сотрудничества.
Использование ORM при разработке корпоративных приложений
Есть много споров о плюсах и минусах ORM, попробуем сделать акцент на плюсах при его использовании в ERP приложениях.
Я 5 лет разрабатываю платформу для ERP, разработал три версии платформы. Всё начиналось с EAV, после была нормальная модель, хранимые процедуры, view-хи, и сейчас эволюционировало до использования ORM. Позвольте поделиться опытом, почему ORM — хорошо.
Для демонстрации преимуществ такого подхода я разработал небольшое приложение для риэлтерского агентства (вдохновение черпал из Циан, из него же и модель данных) и попробую описать, почему благодаря ORM я все сделал за 1 день.
Я являюсь сторонником CodeFirst подхода, т.к. это единственно правильно для планирования структуры бизнес-приложения.
В нашей последней платформе мы после долгого выбора решили использовать ORM DataObjects.Net, но суть статьи будет понятна для приверженца любой ORM, будь то NHibernate, Entity Framework и т.д.
Итак, спланируем простое приложение для агентства недвижимости:
Риэлтор агентства недвижимости (Агент) — вносит в систему предложения по аренде и ждет запросов от арендаторов.
Арендатор просматривает предложения, отбирает по множеству критериев интересные для него и обращается к агенту для заключения сделки.
Дизайн модели данных
Создание модели — это создание классов на C#, добавление свойств-полей, атрибутов, комментариев.
в коде это выглядит примерно так:
Наследование
При работе с ORM мы можем воспользоваться таким мощным инструментом ООП как наследование.
Для базового класса предложения об аренде создаем наследников: Предложения квартир и Предложения комнат
При очевидной простоте, этот подход позволяет радикально сократить количество кода и упростить разработку схожих сущностей, особенно эффективно это при разработке похожих документов, отличающимися несколькими полями.
Инкапсуляция
Кроме знакомой многим инкапсуляции из мира ООП, при использовании ORM мы инкапсулируем ещё и физическую модель хранения данных. Можем использовать любую схему наследования для одного и того-же бизнес кода. Т.е. меняем структуру бд, не изменяя код приложения, ну или почти не изменяя.
Из предыдущей структуры классов не совсем понятно, как будут выглядеть таблицы, содержащие данные предложений от арендодателя, а выглядеть они могут тремя различными способами, в зависимости от значения атрибута указывающего схему наследования:
ClassTable
Используется по умолчанию, и создает по таблице на каждый класс, начиная с корня иерархии
SingleTable
Одна таблица для всех классов иерархии
ConcreteTable
По таблице на каждый не абстрактный класс
Зачем всё это нужно?
В некоторых случаях удобно хранить нормализованные данные, а в других, для оптимизации, удобнее денормализировать таблицы. Преимущество ORM в том что это можно сделать очень просто — всего лишь изменив одну строчку — в нашем случае будет заменено на и соответственно. При этом, т.к. мы пишем запросы не на SQL, то все запросы будут автоматически транслированы для использования соответствующей схемы наследования. Т.е. отчет по предложениям об аренде/квартир/комнат написанный на LINQ и работающий через ORM будет работать с каждой схемой и не потребует никаких доработок.
Добавление бизнес-логики
События форм
Например, изменяем на форме Стоимость, сразу же, налету, пересчитывается Процент. И наоборот. А вот как лаконично это выглядит в коде:
Полиморфизм
В предыдущем примере мы написали событие только для одной сущности RentOfferBase, это событие будет работать и с наследниками, но что если у нас несколько сущностей с ценой/комиссией? Каждый раз писать один и тот же код?
Выделяем интерфейс
и переписываем событие в виде
Теперь этот код сработает для любой сущности реализующей интерфейс IWithComission. При этом, если потребуется внести изменения в логику расчета процентов, то сделать это нужно в единственном месте, во всех остальных местах всё применится автоматически. Например, создадим сущность для заявки на покупку квартиры.
Такой подход позволяет значительно уменьшить количество кода и обеспечить удобную поддерживаемость продукта.
События сущностей
События сущностей очень похожи на события форм, но срабатывают транзакционно в момент изменения сущности. Это некий аналог триггеров бд, но в отличие от триггеров и аналогично событиям форм позволяют использовать ООП подход. Например, нам нужно контролировать изменение сущностей на статусе “закрыт” так, чтобы никто кроме администратора не мог их изменять. Довольно простой код
Который проверяет что если изменяемая сущность находится на статусе “Закрыт” и пользователь не принадлежит роли админ — то генерируется исключение. Аналогично событиям форм события сущностей будут применяться ко всем сущностям совместимым с ними, в данном случае реализующими интерфейс IWithStatus.
Разделение кода
В некоторых подходах используется RichDomainModel, у нас же она Anemic
и это значит, что в классе сущности практически отсутствует бизнес логика. (Для этого есть События Форм/Сущностей/Фильтры и т.п.)
Преимущество такого подхода в возможности модификации поведения внешних сущностей. Например, одна компания разработала модуль Адресов и поставляет его как библиотеку, мы не имеем доступа к исходному коду этой библиотеки и хотим добавить какое-нибудь поведение на форму, например при выборе некорректного адреса предупреждать.
Для этого мы можем написать событие формы, которое будет применено к внешнему компоненту.
Фильтры
Например, для ограничения видимости неактуальных заявок, для менеджера применяется следующее выражение фильтрации из кода:
Это простой фильтр, используемый для ограничения прав доступа только к своим заявкам, либо к заявкам на статусе “Актуально”
Этот фильтр сейчас не привязан явно ни к какой сущности, generic параметр говорит лишь о том, что использовать его можно для RentOfferBase и любого из его наследников. Для кого он будет реально применен будет определяться позже, в момент настройки приложения.
Так же мы можем задать фильтрацию одного поля формы в зависимости от другого
Здесь мы фильтруем станции метро в зависимости от выбранной ветки, указав в атрибутах сущности и поля, которые используются в качестве источников значений и объектов фильтрации.
Внесение изменений в систему
ERP система, в отличие от остальных приложений, требует частого внесения изменений в бизнес-логику и модель данных, а этот процесс должен быть простым и надежным.
Но как же быть с обновлениями?
Миграция
ORM — отвратительный анти-паттерн
От автора перевода: Написанный далее текст может не совпадать с мнением автора перевода. Все высказывания идут от лица оригинального автора, просьба воздержаться от неоправданных минусов. Оригинальная статья выпущена в 2014 году, поэтому некоторые фрагменты кода могут быть устаревшими или «нежелаемыми».
Вступление
Как работают ORM
Во-первых, рассмотрим на примере как работает ORM. Давайте использовать Java, PostgreSQL и Hibernate. Допустим, у нас есть единственная таблица в базе данных, называемая post:
Теперь мы хотим манипулировать этой таблицей CRUD-методами из нашего Java-приложения (CRUD расшифровывается как create, read, update и delete). Для начала мы должны создать класс Post (извините, что он такой длинный, но это лучшее, что я могу сделать):
Перед любой операцией с Hibernate мы должны создать SessionFactory:
Эта фабрика будет выдавать нам “сеансы” каждый раз, когда мы захотим работать с объектами Post. Каждая манипуляция с сеансом должна быть заключена в этот блок кода:
Когда сеанс будет готов, вот так мы получаем список всех записей из этой таблицы:
Когда мы хотим выполнить обратную операцию и отправить объект в базу данных, мы делаем все то же самое, но в обратном порядке. Мы создаем экземпляр класса Post, заполняем его данными и просим Hibernate сохранить его:
Так работает почти каждая ORM. Основной принцип всегда один и тот же — объекты ORM представляют собой немощные/анемичные (прямой перевод слова anemic) оболочки с данными. Мы разговариваем с ORM фреймворком, а фреймворк разговаривает с базой данных. Объекты только помогают нам отправлять запросы в ORM framework и понимать его ответ. Кроме геттеров и сеттеров, у объектов нет других методов. Они даже не знают, из какой базы данных они пришли.
Вот как работает object-relational mapping.
Что в этом плохого, спросите вы? Все!
Что не так с ORM?
Серьезно, что не так? Hibernate уже более 10 лет является одной из самых популярных библиотек Java. Почти каждое приложение в мире с интенсивным использованием SQL использует его. В каждом руководстве по Java будет упоминаться Hibernate (или, возможно, какой-либо другой ORM, такой как TopLink или OpenJPA) для приложения, подключенного к базе данных. Это стандарт де-факто, и все же я говорю, что это неправильно? Да.
Я утверждаю, что вся идея, лежащая в основе ORM, неверна. Его изобретение было, возможно, второй большой ошибкой в ООП после NULL reference.
ORM, вместо того чтобы инкапсулировать взаимодействие с базой данных внутри объекта, извлекает его, буквально разрывая на части прочный и сплоченный живой организм.
На самом деле, я не единственный, кто говорит что-то подобное, и определенно не первый. Многое на эту тему уже опубликовано очень уважаемыми авторами, в том числе OrmHate автора Martin Fowler (не против ORM, но в любом случае стоит упомянуть), Object-Relational Mapping is the Vietnam of Computer Science от Jeff Atwood, The Vietnam of Computer Science автора Ted Neward, ORM Is an Anti-Pattern от Laurie Voss и многие другие.
Однако мои аргументы отличаются от того, что они говорят. Несмотря на то, что их доводы практичны и обоснованны, например, “ORM работает медленно” или “обновление базы данных затруднено”, они упускают главное. Вы можете увидеть очень хороший, практический ответ на эти практические аргументы, от Bozhidar Bozhanov в его блоге ORM Haters Don’t Get It.
Суть в том, что ORM вместо того, чтобы инкапсулировать взаимодействие с базой данных внутри объекта, извлекает его, буквально разрывая на части прочный и сплоченный живой организм. Одна часть объекта хранит данные, в то время как другая, реализованная внутри механизма ORM ( sessionFactory ), знает, как обращаться с этими данными, и передает их в реляционную базу данных. Посмотрите на эту картинку; она иллюстрирует, что делает ORM.
Я, будучи читателем сообщений, должен иметь дело с двумя компонентами: 1) ORM и 2) возвращенный мне объект “ob-truncated”. Предполагается, что поведение, с которым я взаимодействую, должно предоставляться через единую точку входа, которая является объектом в ООП. В случае ORM я получаю такое поведение через две точки входа — механизм ORM и “предмет”, который мы даже не можем назвать объектом.
Из-за этого ужасного и оскорбительного нарушения объектно-ориентированной парадигмы у нас есть много практических проблем, уже упомянутых в уважаемых публикациях. Я могу добавить еще только несколько.
SQL-speaking объекты
Как я также упоминал в этой статье, каждый объект должен работать по контракту и реализовывать интерфейс. Давайте начнем наш дизайн с двух интерфейсов. Конечно, наши объекты будут неизменяемыми. Вот как будут выглядеть Posts :
Вот как будет выглядеть один Post :
Вот так мы будем перечислять все записи в таблице базы данных:
Вот так создаётся новый Post :
Я собираюсь использовать jcabi-jdbc в качестве оболочки JDBC, но вы можете использовать что-то другое, например jOOQ, или просто JDBC, если хотите. На самом деле это не имеет значения. Важно то, что ваши взаимодействия с базой данных скрыты внутри объектов. Давайте начнем с Posts и реализуем его в классе PgPosts (“pg” означает PostgreSQL):
Далее давайте реализуем интерфейс Post в классе PgPost :
Вот как будет выглядеть сценарий полного взаимодействия с базой данных с использованием только что созданных нами классов:
Как насчет производительности?
Обратите внимание: этот декоратор ничего не знает о PostgreSQL или JDBC. Он просто декорирует объект типа Post и предварительно кэширует дату и заголовок. Как обычно, этот декоратор также неизменяем.
Теперь все записи, возвращаемые iterate() этого нового класса, предварительно снабжены датами и заголовками, полученными за одно обращение к базе данных.
Используя декораторы и несколько реализаций одного и того же интерфейса, вы можете создать любую функциональность, которую пожелаете. Что наиболее важно, так это то, что, хотя функциональность расширяется, сложность дизайна не возрастает, потому что классы не увеличиваются в размерах. Вместо этого мы вводим новые классы, которые остаются сплоченными и прочными, потому что они маленькие.
Что касается транзакций
Затем, когда вы хотите обернуть несколько манипуляций с объектами в одну транзакцию, сделайте это следующим образом:
Этот код создаст новую запись и опубликует комментарий к ней. Если один из вызовов завершится неудачей, вся транзакция будет откачена.
Мне этот подход кажется объектно-ориентированным. Я называю это “объектами, говорящими на SQL”, потому что они знают, как разговаривать на SQL с сервером базы данных. Это их мастерство, идеально заключенное в их границах.
Выборка данных с ORM — это просто! Или нет?
Введение
Практически любая информационная система так или иначе взаимодействует с внешними хранилищами данных. В большинстве случаев это реляционная база данных, и, зачастую, для работы с данными используется какой-либо ORM фреймворк. ORM устраняет большую часть рутинных операций, взамен предлагая небольшой набор дополнительных абстракций для работы с данными.
Мартин Фаулер опубликовал интересную статью, одна из ключевых мыслей там: “ORM’ы помогают нам решать большое количество задач в энтерпрайз приложениях… Этот инструмент нельзя назвать симпатичным, но и проблемы, с которыми он имеет дело, тоже не милашки. Я думаю, что ORM заслуживают больше уважения и больше понимания”
Мы очень интенсивно используем ORM во фреймворке CUBA, так что не понаслышке знаем о проблемах и ограничениях этой технологии, поскольку CUBA используется в различных проектах по всему миру. Есть много тем, которые можно обсудить в связи с ORM, но мы сосредоточимся на одной из них: выбор между “ленивым” (lazy) и “жадным” (eager) способами выборки данных. Поговорим о разных подходах к решению этой проблемы с иллюстрациями из JPA API и Spring, а также расскажем, как (и почему именно так) ORM используется в CUBA и какие работы мы ведем, чтобы улучшить работу с данными в нашем фреймворке.
Выборка данных: ленивая или нет?
Чтобы вытащить экземпляр этой сущности из БД, нам нужно всего лишь вызвать один метод объекта EntityManager :
Все становится немного интереснее, когда появляется отношение “один-ко-многим”:
Если нам нужно извлечь из БД экземпляр пользователя, возникает вопрос: “А адреса тоже выбираем?”. И “правильный” ответ здесь: “Зависит от. ” В некоторых случаях нам адреса будут нужны, в некоторых — нет. Обычно ORM предоставляет два способа выборки зависимых записей: ленивый и жадный. По умолчанию в большинстве ORM используется ленивый способ. Но, если мы напишем такой код:
Так, а если попробовать другой тип выборки?
Ну… нельзя сказать, что это сильно поможет. Да, избавимся от ненавистного LazyInit и не надо проверять, прикреплена сущность к сессии или нет. Но теперь у нас могут возникнуть проблемы с производительностью, потому что адреса нам нужны не всегда, а мы все равно выбираем эти объекты в память сервера.
Ещё идеи?
Spring JDBC
Некоторые разработчики настолько устают от ORM, что переключаются на альтернативные фреймворки. Например, на Spring JDBC, который предоставляет возможность преобразования реляционных данных в объектные в “полуавтоматическом” режиме. Разработчик пишет запросы для каждого случая, где нужен тот или иной набор атрибутов (или один и тот же код повторно используется для случаев, где нужны одинаковые структуры данных).
Это дает нам большую гибкость. Например, можно выбрать только один атрибут, не создавая соответствующий объект-сущность:
Или выбрать объект в привычном виде:
Также можно выбрать и список адресов для пользователя, нужно только написать чуть больше кода и правильно составить SQL запрос, чтобы избежать проблемы n+1 запроса.
Тааак, опять сложновато. Да, мы контролируем все запросы и то, как данные отображаются на объекты, но надо писать больше кода, учить SQL и знать, как запросы выполняются в базе данных. Лично я думаю, что знание SQL — это обязательный навык для прикладного программиста, но так думают не все, и я не собираюсь вступать в полемику. В конце концов, знание инструкций x86 ассемблера в наши дни тоже необязательно. Давайте лучше подумаем о том, как облегчить жизнь программистам.
JPA EntityGraph
А давайте сделаем шаг назад и подумаем, что нам вообще нужно? Похоже, что нам просто надо указывать, какие точно атрибуты нам нужны в каждом конкретном случае. Ну и давайте это делать! В JPA 2.1 появился новый API — EntityGraph (граф сущностей). Идея — очень простая: используем аннотации для того, чтобы описать то, что будем выбирать из базы. Вот пример:
Для данной сущности описано два графа: user-only-entity-graph не выбирает атрибут Addresses (помеченный как lazy), в то время, как второй граф указывает ORM выбирать этот атрибут. Если мы пометим Addresses как eager, то граф будет проигнорирован и адреса будут выбраны в любом случае.
Итак, в JPA 2.1 можно делать выборку данных вот так:
Этот подход сильно упрощает работу, не нужно отдельно думать про lazy атрибуты, и длину транзакций. Дополнительный бонус — граф применяется на уровне SQL запроса, таким образом “лишние” данные не выбираются в Java приложение. Но есть одна небольшая проблема: нельзя сказать, какие атрибуты были выбраны, а какие — нет. Для проверки есть API, это делается при помощи класса PersistenceUtil :
Но это довольно-таки уныло и не все готовы делать такие проверки. А можно ещё что-нибудь упростить и просто не показывать атрибуты, которые не были выбраны?
Проекции Spring
В Spring Framework есть отличная штука, которая называется “Проекции” (и это не то же самое, что проекции в Hibernate). Если нужно выбрать только некоторые атрибуты сущности, то создается интерфейс с нужными атрибутами, и Spring выбирает “экземпляры” этого интерфейса из БД. В качестве примера, рассмотрим следующий интерфейс:
Теперь можно определить Spring JPA репозиторий для выборки сущностей User следующим образом:
В этом случае, после вызова метода findByName, в полученном списке мы получим сущности, у которых доступ открыт только к атрибутам, которые определены в интерфейсе! По такому же принципу можно выбирать и зависимые сущности, т.е. выбираем сразу отношение “master-detail”. Более того, Spring генерирует “правильный” SQL в большинстве случаев, т.е. из БД выбираются только те атрибуты, которые описаны в проекции, это очень похоже на то, как работают графы сущностей.
Это очень мощный API, при определении интерфейсов можно использовать выражения SpEL, использовать классы с какой-то встроенной логикой вместо интерфейсов и ещё много чего, в документации все расписано очень подробно.
Единственная проблема с проекциями в том, что внутри они реализованы в виде пар “ключ — значение”, т.е. предназначены только для чтения. А это значит, что, даже если мы и определим setter метод для проекции, то изменения сохранить не сможем ни через CRUD репозитории, ни через EntityManager. Так что проекции — это такие DTO, которые можно преобразовать обратно в Entity и сохранять, только если написать свой собственный код для этого.
Как выбираются данные в CUBA
С самого начала разработки фреймворка CUBA мы старались оптимизировать часть кода, который работает с БД. В CUBA мы используем EclipseLink как основу для API доступа к данным. Что хорошо в EclipseLink — он с самого начала поддерживал частичную загрузку сущностей, и это стало решающим фактором в выборе между ним и Hibernate. В EclipseLink можно было указать атрибуты для загрузки задолго до того, как появился стандарт JPA 2.1. В CUBA существует собственный способ описания графа сущностей, называется CUBA Views (представления CUBA). Представления CUBA — довольно-таки развитый API, можно наследовать одни представления от других, комбинировать их, применяя как к master, так и к detail сущностям. Ещё одна мотивация для создания CUBA представлений — мы хотели использовать короткие транзакции, чтобы можно было работать с открепленными сущностями в пользовательском web-интерфейсе.
В CUBA представления описываются в XML файле, как в примере ниже:
Концепт — CUBA View Interfaces
А что, если все-таки попробовать совместить графы сущностей и проекции? Мы решили попробовать это сделать и разработали интерфейсы для представления сущностей (entity view interfaces), которые повторяют подход из проекций Spring. Эти интерфейсы транслируются в CUBA представления при старте приложения и могут быть использованы в DataManager. Идея проста: описываем интерфейс (или набор интерфейсов), который и представляет из себя граф сущностей.
Стоит отметить, что для каких-то конкретных случаев можно делать локальные интерфейсы, как в случае AddressStreetOnly из примера выше, чтобы не “загрязнять” публичный API своего приложения.
В процессе старта CUBA приложения (бОльшая часть которого — это инициализация контекста Spring), мы программно создаем CUBA представления и помещаем их во внутренний бин — репозиторий в контексте.
Теперь нужно немного изменить имплементацию класса DataManager, чтобы он принимал представления-интерфейсы, и можно делать выборку сущностей вот таким образом:
Под капотом генерируется прокси-объект, который реализует интерфейс и оборачивает экземпляр сущности, выбранный из БД (примерно так же, как это делается в Hibernate). И, когда разработчик обращается за значением атрибута, то прокси делегирует вызов метода “настоящему” экземпляру сущности.
Заметьте, что вычисляемые атрибуты можно вынести из модели классов сущностей и перенести в интерфейсы, применимые к конкретной бизнес логике.
Ещё одна интересная возможность — наследование интерфейсов. Можно сделать несколько представлений с разными наборами атрибутов, а затем их комбинировать. Например, можно создать интерфейс для сущности User с атрибутами name и email, и другой — с атрибутами name и addresses. Теперь, если нужно выбирать name, email и addresses, то не нужно копировать эти атрибуты в третий интерфейс, нужно просто унаследоваться от первых двух представлений. И да, экземпляры третьего интерфейса можно передавать в методы, которые принимают параметры с типом интерфейсов-родителей, правила ООП одинаковы для всех.
Также было реализовано преобразование между представлениями — в каждом интерфейсе есть метод reload(), в который можно передать класс представления в качестве параметра:
Представление UserFullView может содержать дополнительные атрибуты, так что сущность будет загружена заново из БД, если необходимо. И этот процесс — отложенный. Обращение к БД будет произведено только тогда, когда произойдет первое обращение к атрибутам сущности. Это немного замедлит первое обращение, но такой подход был выбран намеренно — если экземпляр сущности используется в модуле “web”, в котором находится UI и собственные REST контроллеры, то этот модуль может быть развернут на отдельном сервере. А это значит, что принудительная перегрузка сущности создаст дополнительный сетевой трафик — обращение к модулю core и затем к БД. Таким образом, откладывая перегрузку до того момента, когда это необходимо, мы экономим трафик и уменьшаем количество запросов к БД.
Концепт оформлен в виде модуля для CUBA, пример использования можно скачать с GitHub.
Заключение
Кажется, что в ближайшем будущем мы все ещё будем массово использовать ORM в энтерпрайз приложениях просто потому, что нам нужно что-то, что будет превращать реляционные данные в объекты. Конечно, для сложных, уникальных, сверхвысоконагруженных приложений будут разрабатываться какие-то специфичные решения, но, похоже, что ORM фреймворки будут жить столько же, сколько реляционные базы данных.
В CUBA мы стараемся упростить работу с ORM по максимуму, и в следующих версиях мы будем вводить новые возможности для работы с данными. Будут ли это интерфейсы-представления или что-то другое — сейчас сложно сказать, но я уверен в одном: мы будем продолжать упрощать работу с данными в следующих версиях фреймворка.
Orm что это
Такой записи не существует
Москва, ул. Большая Спасская 12
Курс «Вёрстка сайтов»
Курс «Анализ данных на Python»
Курс «Android-разработка на Kotlin»
Курс «Основы создания игр»
Курс «Java-разработчик PRO»
Курс «QA Инженер (Тестировщик)»
Научим кодить с самого нуля!
Записывайся уже сегодня
Тел.: +7 495 626-46-00
Тел.: +7 925 632-21-47
Эл. почта: moscow@inordic.ru
Время работы:
пн-пт: с 11:00 до 19:00
О сущностях, DTO, ORM и Lazy Load
Объектно-ориентированная парадигма — стандарт для прикладного ПО. Реляционные СУБД — стандарт хранения данных в прикладном ПО. Да, можно писать и на Haskell и хранить данные исключительно в ClickHouse. Но речь о мейнстриме.
ORM позволяет натянуть сову на глобус сделать вид, что RDBMS’а нет и данные хранятся в объектной модели, более подходящей для ООП. Остается «маленькая» такая проблемка — эта абстракция, как и многие другие, «течет». Там где в объектной модели ссылка на другой объект в базе данных foreign key и id. В момент материализации сущности мы встаем перед выбором:
В read-подсистеме всегда читать только DTO
Что делать если моя логика не транслируется в SQL?
Client Evaluation я рекомендую держать выключенным. Во первых, можно «помочь» и дописать поддержку необходимых функций прямо в субд. Не самый плохой вариант, если речь идет о простых вычислениях, а не бизнес-правилах. Вариант номер два: выделить интерфейс из сущности и реализовать его и в сущности и в DTO.
Например, в БД есть два поля: «цена без скидки» и «цена со скидкой». Если поле «цена со скидкой» заполнено, то используем его, если нет — то используем поле с обычной ценой. Добавим еще одно правило. При покупке 3 товаров вы платите только за 2 самых дорогих, при этом обычные скидки также учитываются.
Реализация может быть такой:
Во write-подсистеме Lazy Load не так страшен
Во write-подсистеме, наоборот, довольно часто только id для записи не достаточно. Всевозможные проверки не редко заставляют читать сущность целиком, потому что объектная парадигма предполагает совмещение данных и операций над ними в рамках объекта класса и его инварианта. Если в проекте используется DDD, то операции записи/изменения должны производиться через корень агрегации, а значит только над одним объектом и его зависимостями. Большое количество запросов может возникнуть только при работе со связанными коллекциями.
Связанные коллекции в агрегатах
Если в агрегате слишком много данных, это может свидетельствовать о проблемах с проектированием. Типичные корни агрегации — корзина, заказ, посылка. Люди обычно не работают с данными из тысяч строк, поэтому загрузка всей связанной коллекции может быть не самой производительной, но не смертельной операцией. А вот если в коллекции тысячи объектов, возможно, что такого корня агрегации на самом деле нет и его придумали разработчики, потому то было очень просто это сделать с помощью подручных инструментов.
Что если в агрегате все-таки тысячи записей
Передайте DbContext в конструктор и читайте из него только необходимые в контексте операции данные. Да, нарушаем DIP. Либо так, либо вообще не использовать агрегат в этом случае.
Массовые операции
Импорт файла на 10.000 строк отличная мишень для Lazy Load. Здесь ко всем проблемам read-подсистемы добавляются еще и тормоза ChangeTracker’а. Для массовой записи нужно использовать отдельные инструменты. Я отдаю предпочтения Batch Extensions, потому что опять можно обойтись без создания сущностей. Для особо тяжелых случаев существуют старые добрые хранимые процедуры и даже специальные средства СУБД.
Что такое ORM
Любой, кто имеет опыт разработки web приложений или использования какого-либо PHP фреймворка, безусловно, сталкивался с реляционными базами данных, такими как MySQL или PostgreSQL. Работа с SQL напрямую, может быть достаточно сложной, особенно при работе с данными сразу из нескольких таблиц и при применении различных фильтров. А это как раз та сфера, где на сцену выходит ORM.
Так, что же такое ORM?
ORM фреймворк может быть написан на каком-либо объектно-ориентированном языке ( PHP, Python, Ruby ) и представлять обертку над некой реляционной базой данных. Классы будут соответствовать таблицам в базе, а экземпляры этих классов – конкретным строкам таблицы.
Далее обсудим преимущества концепции ORM. Стоит также отметить, что не все библиотеки, реализующие данную концепцию, обладают всеми рассмотренными здесь преимуществами.
Независимость от вида базы данных
Это, пожалуй, главнейшая особенность и преимущество использования ORM в приложении. Так как нет необходимости писать специфический код под конкретный вид базы данных. Поэтому, вы можете начать проект с использования SQLite, затем можете поменять ее на MySQL или PostgreSQL. И все это делается редактированием пары строчек кода в настройках адаптера базы данных.
Моделирование предметной области
При использовании ORM для построения приложения, бизнес-логика приложения работает с объектами языка, а не с самой структурой базы данных. Это возможно благодаря соответствию между бизнес-моделью и самой базой данных.
Меньше кода и больше эффективности
ORM добавляет дополнительный слой абстракции, который позволяет разработчикам сконцентрироваться на их бизнес-логике, не отвлекаясь на создание сложных запросов к базе данных. Это приводит к сокращению количества необходимого для написания кода и увеличивает продуктивность разработчика.
Развитый интерфейс запросов к базе
В ORM предусмотрен богатый интерфейс, освобождающий разработчика от сложной семантики SQL.
ORM предоставляет свободное управление зависимостями в базе данных. Связанные объекты загружаются автоматически, когда вызов методов преобразуется в соответствующий SQL запрос.
Параллелизм, кэширование и транзакции
ORM поддерживает возможность параллельной работы, позволяя нескольким пользователям одновременно изменять один и тот же объект.
Другая особенность – объекты могут быть сохранены в кэше, сокращая нагрузку на базу и вцелом увеличивая скорость работы приложения.
Изменения, вносимые в объект могут быть ограничены в рамках данной транзакции, которая может быть сохранена или возвращена обратно в первоначальное состояние. В каждый момент времени могут быть активными множество транзакций, но все эти транзакции изолированы друг от друга.
ORM фреймворк добавляет слой абстракции, ускоряющий процесс разработки и снижающий сложность создания конечного продукта. Однако, ничто не проходит даром – приложение начинает потреблять больше памяти и нагрузка на процессор также увеличивается.
Применение ORM в PHP приложении предполагает, что у разработчика есть опыт работы с каким либо PHP фреймворком. И поэтому здесь без дополнительных знаний будет обойтись нелегко. Хотя вы можете значительно сократить время изучения ORM в PHP, если воспользуетесь моим курсом Фреймворк Yii 2.0 с нуля. Пример создания сайта. Там, в уроке номер 3 “Создание моделей”, я как раз рассказываю о создании объектов базы данных с помощью шаблона проектирования ActiveRecord.
Некоторые операции, такие как массовая вставка, обновление, удаление и т.д., медленнее, когда выполняются посредством ORM. Поэтому, в таких случаях лучше использовать чистый SQL.
Поверхностное знание SQL
Несмотря на то, что ORM облегчает жизнь, это часто приводит к тому, что разработчики не очень стремятся учить SQL или разбираются в нем слабо.
На сегодня все. Всего доброго!
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 0 ):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2022 Русаков Михаил Юрьевич. Все права защищены.
SERM, ORM или SMRM. Что выбрать?
SERM и ORM – давно знакомые слова для любого маркетолога. Но новички и клиенты могут путаться, не понимая, какая услуга нужна именно для их компании.
Для начала пройдемся по терминам:
ORM (online reputation management) – управление репутацией во всем интернете, включая поисковые и рекомендательные системы, форумы, социальные сети и СМИ.
SERM (search engine reputation management) – репутация в выдаче поисковых систем.
SMRM (social media reputation management) напрямую связано с социальными сетями.
Иногда отрицательный отзыв может повлечь за собой негативные отклики других клиентов, создав эффект карточного домика, который разрушит репутацию компании.
Помните историю 4-летней давности с жуками в кальянной?
Проблема ухудшилась еще и неадекватной реакцией со стороны владельцев бизнеса. Это яркий пример провала компании в репутационной сфере.
Разберем же главных «игроков» управления репутацией.
ORM – комплекс услуг, который необходим:
Крупным компаниям. Им важны не только отзывы о продукте/бренде, а также тональность (характер) упоминаний о них в интернете (пример – Альфа-Банк, Burger King).
Властям. ORM работает и здесь – но скорее в плане мониторинга упоминаний, чтобы (в идеале) улучшить свою работу и понять настроение граждан.
Количество площадок, на которых могут быть комментарии о компании, стремится к бесконечности. Online Reputation Management – наиболее правильный подход к управлению репутацией, который поможет с помощью комплексной стратегии выстроить положительный образ в сети.
Как вполне самостоятельной частью ORM выступает SERM – управление репутацией в поисковых системах.
Цель SERM – контроль сайтов с упоминаниями о компании на первых страницах выдачи поисковых систем. Как правило, в SERM работают с площадками, находящимся в ТОП-10 – больше всего трафика по брендовому запросу+отзыв поступает именно на них.
Управление репутацией в поисковых системах отличает охват контролируемых площадок. Мониторинг может вестись не только по названию компании, но и по «стоматологии в уфе». Такой подход позволяет контролировать не только карты и справочники, но и репутационное поле сферы.
Например, вы как обычный пользователь решили ввести как раз «стоматологии в уфе отзывы» и читаете примерно следующий отзыв о клинике №1:
«Лечился в Клинике №1, все отлично, залечили зуб после варварского удаления в Клинике №2…»
И все. Во вторую клинику вы не то что не пойдете – даже своим друзьям расскажете о таком опыте клиента. И неважно, заказной ли это был отзыв или настоящий.
Поэтому важно следить за репутацией не только своей компании, но и периодически проводить мониторинг упоминаний у конкурентов.
SERM идеально подходит для новых услуг или компаний, у которых еще нет активности в социальных сетях. Естественный переход после работы над репутацией в поиске – комплекс услуг ORM.
Сделали небольшую сравнительную таблицу для закрепления знаний.
SMRM идеально подойдет для малого бизнеса, осуществляющих продажи ВК/Instagram/Facebook. Такое управление репутацией поможет:
Главным минусом SMRM является его малая распространенность. Например, если недовольный клиент создаст пост на Отзовике «Компания Метеоритное золото обмануло меня на 150 тысяч», вы рискуете его пропустить и не отработать негатив.
А когда негатив на площадке обнаружится, может быть уже поздно и бессмысленно отвечать на отзыв.
Фраза, что «все работает в комплексе» верна и для управления репутацией в сети. Безразличие к репутационному профилю может отобразиться на бизнесе в любой момент, и нужно уметь вникать в проблемы клиентов и отрабатывать негатив.
SERM и ORM похожи, прекрасно взаимодействуют вместе, но отличаются сферами контроля:
ORM – контроль репутации во всей Сети без акцента на какую-либо площадку;
SERM – только в выдаче поисковых систем.
Национальная библиотека им. Н. Э. Баумана
Bauman National Library
Персональные инструменты
ORM (Object-Relational Mapping)
ORM (Object-Relational Mapping) – технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования, создавая «виртуальную объектную базу данных». Существуют как проприетарные, так и свободные реализации этой технологии.
Библиотеки ORM существуют для самых разных языков программирования. В общих чертах, технология ORM позволяет проектировать работу с данными в терминах классов, а не таблиц данных. Она позволяет преобразовывать классы в данные, пригодные для хранения в базе данных, причем схему преобразования определяет сам разработчик. Кроме того, ORM предоставляет простой API- интерфейс для CRUD-операций над данными. Благодаря технологии ORM нет необходимости писать SQL-код для взаимодействия с локальной базой данных. [Источник 1]
Содержание
Достоинства
Среди достоинств ORM выделяют:
Недостатки
Среди недостатков ORM выделяются:
Если говорить о главном минусе ORM, снижении производительности, то причина этого состоит в том, что большинство из ORM нацелены на обработку значительного большего количества различных сценариев использования данных, чем в случае отдельного приложения. В случае небольших проектов, которые не сталкиваются с высокой нагрузкой, применение ORM очевидно, особенно, если учесть такой важный критерий разработки, как время. «То, что с легкостью пишется с использованием ORM за неделю, можно реализовывать ни один месяц собственными усилиями». [Источник 2]
Альтернативы
Касательно альтернатив технологии ORM, то среди них выделяются:
В случае CoRM отсутствует ограничение на возможность хранить состояние разных объектов одного класса в разных коллекциях и ограничение на одновременное хранение в коллекции объектов, которые принадлежат разным классам.
От обычного ORM-подхода реляционное отображение коллекций отличает то, что коллекция напрямую не привязана к классу и, в теории, может включать в себя любой объект, в случае соблюдения некоторых минимальных требований к данному объекту, например, требование наличия способности к сериализации). Однако к этим требованиям не относятся ограничения на структуру объекта либо использование особых типов данных.
ORM — это инструмент решения проблемы семантического провала между реляционной и объектной моделями данных. Имеющий, однако, определенные проблемы, которых должны быть лишены его альтернативы, позволяющие вывести объектную сущность приложения из ограничений, накладываемых реляционным хранилищем. [Источник 3]
Пример с использованием FlexORM
Вам нужно хранить экземпляры классов во встроенной базе данных с возможностью читать их из нее.
Используйте библиотеку FlexORM. Это проект с открытым кодом, предоставляющий технологию ORM (Object Relational Mapping, реляционное отображение объектов) разработчикам AIR-приложений.
Определение отображения объектов
Библиотека FlexORM позволяет вам использовать метаданные в модельных классах для определения отображения ваших классов на таблицы базы данных. Одно из преимуществ такого подхода над другими решениями состоит в том, что вам не приходится расширять классы платформы. Ваша модель может оставаться неизменённой, если не считать метаданные, которые игнорируются компилятором, если вы их не используете.
В следующем примере имеется один класс, определяющий закладку браузера. Он имеет свойства id, name, url и notes:
Использование класса EntityManager
Первое, что вы должны сделать, — это корректно настроить класс Entity- Manager. Прежде чем он сможет выполнять какие-либо операции, вы должны будете передать ему экземпляр класса SQLConnection:
В этом коде класс EntityManager конфигурируется на использование файла базы данных bookmarks.db, размещенного в том же каталоге, что и приложение. После установки свойства sqlConnection вы можете выполнять над данными операции CRUD. [Источник 4]
Класс EntityManager позволяет без труда читать элементы указанного типа. Достаточно передать класс, который вы хотите прочитать, методу findAll() класса EntityManager:
Сохранить экземпляр класса с помощью класса EntityManager столь же просто:
Процедура удаления экземпляра выполняется аналогичным образом, но требует от вас указания класса, а также свойства id удаляемого экземпляра:
Создание законченного приложения
Объединив приведенные ранее фрагменты кода, вы можете создать законченное приложение, выполняющее операции CRUD исключительно с использованием класса EntityManager. В следующем примере браузер сохраняет закладки (как бы- ло показано выше). В дополнение к приведенному здесь MXML-файлу вам потре- буется SWC-файл библиотеки FlexORM (поместите его в каталог построения) и класс Bookmark, определенный ранее в этом рецепте (разместите его в пакете vo): [Источник 5]
ORM — отвратительный анти-паттерн
От автора перевода: Написанный далее текст может не совпадать с мнением автора перевода. Все высказывания идут от лица оригинального автора, просьба воздержаться от неоправданных минусов. Оригинальная статья выпущена в 2014 году, поэтому некоторые фрагменты кода могут быть устаревшими или «нежелаемыми».
Как работают ORM
Что не так с ORM
Как насчет производительности?
Что касается транзакций
Вступление
Как работают ORM
Во-первых, рассмотрим на примере как работает ORM. Давайте использовать Java, PostgreSQL и Hibernate. Допустим, у нас есть единственная таблица в базе данных, называемая post:
Теперь мы хотим манипулировать этой таблицей CRUD-методами из нашего Java-приложения (CRUD расшифровывается как create, read, update и delete). Для начала мы должны создать класс Post (извините, что он такой длинный, но это лучшее, что я могу сделать):
Перед любой операцией с Hibernate мы должны создать SessionFactory:
Эта фабрика будет выдавать нам “сеансы” каждый раз, когда мы захотим работать с объектами Post. Каждая манипуляция с сеансом должна быть заключена в этот блок кода:
Когда сеанс будет готов, вот так мы получаем список всех записей из этой таблицы:
Когда мы хотим выполнить обратную операцию и отправить объект в базу данных, мы делаем все то же самое, но в обратном порядке. Мы создаем экземпляр класса Post, заполняем его данными и просим Hibernate сохранить его:
Так работает почти каждая ORM. Основной принцип всегда один и тот же — объекты ORM представляют собой немощные (прямой перевод слова anemic) оболочки с данными. Мы разговариваем с ORM фреймворком, а фреймворк разговаривает с базой данных. Объекты только помогают нам отправлять запросы в ORM framework и понимать его ответ. Кроме геттеров и сеттеров, у объектов нет других методов. Они даже не знают, из какой базы данных они пришли.
Вот как работает object-relational mapping.
Что в этом плохого, спросите вы? Все!
Что не так с ORM?
Серьезно, что не так? Hibernate уже более 10 лет является одной из самых популярных библиотек Java. Почти каждое приложение в мире с интенсивным использованием SQL использует его. В каждом руководстве по Java будет упоминаться Hibernate (или, возможно, какой-либо другой ORM, такой как TopLink или OpenJPA) для приложения, подключенного к базе данных. Это стандарт де-факто, и все же я говорю, что это неправильно? Да.
Я утверждаю, что вся идея, лежащая в основе ORM, неверна. Его изобретение было, возможно, второй большой ошибкой в ООП после NULL reference.
ORM, вместо того чтобы инкапсулировать взаимодействие с базой данных внутри объекта, извлекает его, буквально разрывая на части прочный и сплоченный живой организм.
На самом деле, я не единственный, кто говорит что-то подобное, и определенно не первый. Многое на эту тему уже опубликовано очень уважаемыми авторами, в том числе OrmHate автора Martin Fawler (не против ORM, но в любом случае стоит упомянуть), Object-Relational Mapping is the Vietnam of Computer Science от Jeff Atwood, The Vietnam of Computer Science автора Ted Neward, ORM Is an Anti-Pattern от Laurie Voss и многие другие.
Однако мои аргументы отличаются от того, что они говорят. Несмотря на то, что их доводы практичны и обоснованны, например, “ORM работает медленно” или “обновление базы данных затруднено”, они упускают главное. Вы можете увидеть очень хороший, практический ответ на эти практические аргументы, от Bozhidar Bozhanov в его блоге ORM Haters Don’t Get It.
Суть в том, что ORM вместо того, чтобы инкапсулировать взаимодействие с базой данных внутри объекта, извлекает его, буквально разрывая на части прочный и сплоченный живой организм. Одна часть объекта хранит данные, в то время как другая, реализованная внутри механизма ORM ( sessionFactory ), знает, как обращаться с этими данными, и передает их в реляционную базу данных. Посмотрите на эту картинку; она иллюстрирует, что делает ORM.
Я, будучи читателем сообщений, должен иметь дело с двумя компонентами: 1) ORM и 2) возвращенный мне объект “ob-truncated”. Предполагается, что поведение, с которым я взаимодействую, должно предоставляться через единую точку входа, которая является объектом в ООП. В случае ORM я получаю такое поведение через две точки входа — механизм ORM и “предмет”, который мы даже не можем назвать объектом.
Из-за этого ужасного и оскорбительного нарушения объектно-ориентированной парадигмы у нас есть много практических проблем, уже упомянутых в уважаемых публикациях. Я могу добавить еще только несколько.
SQL-speaking объекты
Как я также упоминал в этой статье, каждый объект должен работать по контракту и реализовывать интерфейс. Давайте начнем наш дизайн с двух интерфейсов. Конечно, наши объекты будут неизменяемыми. Вот как будут выглядеть Posts :
Вот как будет выглядеть один Post :
Вот так мы будем перечислять все записи в таблице базы данных:
Вот так создаётся новый Post :
Я собираюсь использовать jcabi-jdbc в качестве оболочки JDBC, но вы можете использовать что-то другое, например jOOQ, или просто JDBC, если хотите. На самом деле это не имеет значения. Важно то, что ваши взаимодействия с базой данных скрыты внутри объектов. Давайте начнем с Posts и реализуем его в классе PgPosts (“pg” означает PostgreSQL):
Далее давайте реализуем интерфейс Post в классе PgPost :
Вот как будет выглядеть сценарий полного взаимодействия с базой данных с использованием только что созданных нами классов:
Как насчет производительности?
Обратите внимание: этот декоратор ничего не знает о PostgreSQL или JDBC. Он просто декорирует объект типа Post и предварительно кэширует дату и заголовок. Как обычно, этот декоратор также неизменяем.
Теперь все записи, возвращаемые iterate() этого нового класса, предварительно снабжены датами и заголовками, полученными за один круговой переход к базе данных.
Используя декораторы и несколько реализаций одного и того же интерфейса, вы можете создать любую функциональность, которую пожелаете. Что наиболее важно, так это то, что, хотя функциональность расширяется, сложность дизайна не возрастает, потому что классы не увеличиваются в размерах. Вместо этого мы вводим новые классы, которые остаются сплоченными и прочными, потому что они маленькие.
Что касается транзакций
Затем, когда вы хотите обернуть несколько манипуляций с объектами в одну транзакцию, сделайте это следующим образом:
Этот код создаст новую запись и опубликует комментарий к ней. Если один из вызовов завершится неудачей, вся транзакция будет откатана.
Мне этот подход кажется объектно-ориентированным. Я называю это “объектами, говорящими на SQL”, потому что они знают, как разговаривать на SQL с сервером базы данных. Это их мастерство, идеально заключенное в их границах.
Для чего нужна ORM?
Нет, я не пойму зачем заменять SQL язык своим?
Зачем надо делать класс, методы которого принимают имя таблицы, принимают условие для фраз WHERE, GROUP BY, HAVING.
По сути язык SQL заменили своим языком. Да к тому же этот язык ограничен методами, которая предоставляет ORM.
Ни тебе иерархические запросы пописать, ни тебе сделать внутренний селект.
Так в чём профит?
Кроме того ORM, как правило не исключает обращение к БД на уровне произвольных SQL запросов, оно лишь преобразуют результаты этих запросов в объекты модели предметной области (и наоборот), которые ничего не знают (в идеале) о таблицах, WHERE, HAVING и т. п.
ORM это не только инструмент архитектурного разделения областей ответственности объектов и классов приложения, а также инструмент облегчения разделения труда разработчиков: кто хорошо шарит в SQL вообще и особенностях конкретного движка в частности — работает по «ту сторону» ORM, оптимизирует его как хочет, может нормализовывать и денормализовывать, например; кто хорошо разбирается в дебетах и кредитах — работает с plain old objects в терминах предметной области и может вообще ничего не зная об SQL, ему лишь нужно знать, что он всегда может получить объект или их коллекцию обратившись к методам вроде findById() или findAll() и сохранить результат работы методом save() или flush().
это даже не dbal, а паттерн builder, в данном контексте query builder, он не болько помогает обстагироваться от типа стораджа, но и собирать запрос по частям, например, с учётом if-оф и переданных параметров.
кстати. типичная ошибка — применения билдеров в контроллерах, а не в отдельном-классе модели.
2 pihel
это будет ORM, если ты сможешь динамически доставать ти изменять связанные данные, например, категория товаров.
Сам по себе ORM, именно как maaping, в крупных проектах нужен как раз очень сильно. Опишу здесь свой опыт. Если понравится кому, может и статью потом.
Итак.
Представьте себе — у меня есть очень крупная система, и есть в ней таблица orders, в ней скажем, 50 колонок (на самом деле у нас 150, ну да ладно. Нормализаторы, молчать! Про нормальные формы я тоже знаю). И вот надо значит вам выбрать один ордер и показать его на экране. Допустим, вы пишете селект, неважно. Дальше что делать, в промежуточном слое? Вы не же вызываете хранимую процедуру (запрос) напрямую с, скажем, JSP страницы (я надеюсь), вам все равно надо получить данные и передать их как-то.
Так что, передавать их в виде массива, ArrayList-a, ассоциативного массива имя колонки/значения? Ну так дико громоздно, неудобно, и очень легко ошибиться. А если вам надо несколько ордеров, тогда что, создавать вложенные коллекции для конвертации результатов? Неудобно же.
Потому, очевидно, нам нужен объект Order, имеющий все нужные property, и нужен код, который умеет конвертировать результаты скл запрос в эти объекты (или коллекцию этих объектов).
Далее, очевидно, что писать руками _все_ запросы трудно и нудно, легко ошибиться, т.к. в Java они будут представляться в коде в виде строк (а значит, никакой статической типизации и compile-time проверок и прочее и прочее), и их надо держать либо в Java коде (если они мелкие), либо, если побольше, выносить в отдельные XML файлы.
В общем, ORM в больших проектах нужен для упрощения рутинной части. Без него — никуда 🙂
Безусловно, обойтись ТОЛЬКО ORM не получится. Есть у нас масса мест, где сложная логика написана в хранимых процедурах в 500-1000 строк на PL/SQL, написанная через ORM /Java она бы занимала в 10 раз больше и работала в 2 раза медленнее (при этом, она была бы еще и менее понятная, т.к. есть такая логика, которые в терминах реляционной алгебры описывается куда проще, чем в терминах ООП :), следовательно ложится на ORM со скрипом). Сколько нибудь сложные запросы с подзапросами, юнионами, хитрыми джойнами тоже писать через чистый ORM громоздко. Оптимизировать запросы, работающими в таблицах где, хотя бы, несколько сотен миллионов записей, без доступа к планам SQL оптимизатора и статистики/средствам мониторинга уровня СУБД тоже крайне сложно. Так что без SQL тоже — никуда 🙂