Автор принял для себя решение

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

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

Но это если вкратце, давайте разберем по подробнее.

Размазанность бизнес логики

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

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

Возможное обращение к отцам основателям хранимых процедур

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

Сложность в тестировании

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

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

Умные мысли не покидали его...

Бывает, что при неработающем стенде от аналитиков и заказчиков поступают предложения протестировать на продакшене, потому что нужно как можно скорее исправить проблему. Они аргументируют это тем, что на продакшене всё равно уже не работает, но вся полнота ответственности за это ложиться на вас за это действие.

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

Но неработающий тестовый стенд — это ещё не самая худшая ситуация. Гораздо хуже, когда просто непонятно, как протестировать. Например, если хранимая процедура принимает входным параметром XML с динамическим количеством свойств, и вам нужно собрать нужную комбинацию этих свойств, чтобы добраться до вашего участка кода. Очевидно, что никто не осведомлён о необходимой комбинации. Сложность сбора этой комбинации свойств сродни сбору флеш-рояля в покере, когда вы играете на свой последний доллар.

Примерно так ощущаешь себя во время попытки протестировать

Автоматическое тестирование или unit-тесты

Сколько работал с хранимыми процедурами, ни разу за свою жизнь не встречал адекватных автотестов в CI, которые могли бы что-то проверять. Видел лишь попытки создания параллельных проектов, которые через некоторое время переставали поддерживать. А без тестов не будет качества, ведь вся разработка будет производиться наугад.

Хотелось бы, чтобы при закрытии бага можно было просто написать на него тест, который запустится в CI и сообщит нам, что всё отработало корректно и ваши изменения ничего не сломали. Но работа с хранимыми процедурами исключает данный подход.

Ответ дан после тестирования хранимок.

Отсутствие современных фишечек и фреймворков и соединение жизненного пути с БД.

Например, от бизнес-партнеров поступило требование собирать метрики по определённым участкам бизнес-процесса для их оценки. И как мы будем это делать? Правильно, реализовывать ещё больше костылей, потому что SQL — это язык для агрегации данных, а не язык для описания бизнес-логики приложения. В любом современном языке программирования достаточно подключить какую-либо библиотеку и настроить URL /metrics для сбора необходимых метрик и отправляться снова смотреть видосики на Youtube VK video.

Также, описывая бизнес-логику нашего приложения с помощью SQL, мы перекладываем все вычисления на сервер базы данных, что лишает нас возможности легко горизонтально масштабировать приложение с помощью увеличения числа инстансов в Kubernetes.

И вообще современных приложениях стараются отвязаться от конкретного источника данных, ведь кроме конкретной SQL БД существуют и другие. При использовании хранимых процедур наша БД становится конечной остановкой. Нужен более гибкий и быстрый поиск, где можно было бы использовать Elasticsearch? Требуется быстрая NoSQL для какой-либо части нашего приложения, например Redis? Извините, но у нас так не принято.

Хранимка извиняется и выносит предупреждение

А работая на .NET часто бизнес-логика выноситься в домен и покрываться сразу Unit-тестами не опираясь на используемую базу данных, ведь есть такие прекрасные вещи, как ORM (Entity Framework), которая позволяет выбрать любую базу данных в моменте и наслаждаться жизнью. То-есть мы уже вольны использовать, что нам нужно.

Также стоит упомянуть про логирование, которое работает из коробки в большинстве приложений и отправляется в ELK, чего SQL не может предложить.

Проблемы с переездом на другую БД

Раньше этот пункт казался чем-то невозможным: если понадобится, выделим пару десятков лет на переезд. Но после известных событий и наложенных санкций компании столкнулись с требованием перейти с MS SQL на другие СУБД. И тут начались проблемы: Postgresql имеет другой синтаксис и не обладает теми же функциональными возможностями. Поэтому в кратчайшие сроки нужно всё переписывать и переносить бизнес-логику обратно в приложение.

Из-за разницы в функциональности это даже сложно назвать переносом — нужно всё разбирать и переписывать с нуля. Но как переписать всё с нуля, если половина людей не понимает, как это работает, а у второй половины разная степень экспертизы в SQL? Для backend-разработчика глубокие знания всех версий и вариаций SQL не являются обязательными, ведь у них есть свой основной язык программирования.

Пример разного уровня экспертизы...

Заключение

В заключение хочу подвести итоги и перечислить все минусы, которые я обозначил в статье и к которым пришёл.

  • Сложность в поддержке и тестировании.

  • Проблемы при параллельной разработке

  • Ограничение функциональности, функциональностью БД

  • Отсутствие горизонтального масштабирования

  • Отсутствие гибкости в выборе необходимого хранилища данных

  • Проблемы с переносимостью бизнес-логики

  • Backend разработчики должны обладать знаниями DBA

  • Сложность порождает низкое качество и большое количество ошибок.

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