Большинство 4GL-языков SQL не предназначены для разработки приложений

Обоснование
Большая часть специфических процедурных языков, добавляемых к SQL разработчиками, ни в коей мере не предназначена для замены языков разработки приложений (обратите внимание на исключения). Это не более чем микроязыки для выполнения простых процедур внутри базы данных.
У классического микроязыка нет настоящего ввода-вывода; ваши возможности ограничены выдачей сообщений на стандартное устройство. Нет возможности управлять файлами, проводить сложные вычисления, отображать окна. Такие языки нужны для написания триггеров или простых процедур по обслуживанию БД. Всегда считалось и считается, что они не должны быть длиннее примерно 50 строк.
И это замечательно! Во многоуровневой архитектуре отображение и сложные расчеты выполняются хост-языком на представительском уровне. Но стоит заглянуть в группу новостей по SQL, и вы немедленно встретите там новичков, которые хотят управлять отображением данных средствами БД. Они хотят дописывать нули впереди числа в операторе SELECT, объединять в одну строку имена и фамилии, нумеровать строки на дисплее и еще много всего. SQL предназначен исключительно для извлечения данных и не имеет никакого отношения к представительскому уровню.

Исключения
Языки Informix 4GL, Progress, Oracle PL/SQL и некоторые другие действительно предназначены для разработки приложений. Иногда такой язык появлялся даже раньше самой СУБД. Программа на специализированном языке быстро выполняется, легко пишется и обладает другими замечательными свойствами. Оборотной стороной медали, естественно, является отсутствие переносимости.

Основы разработки программ

Просто поразительно, как мало программистов SQL знакомо с основами разработки программ. В группах новостей нередко встречаешь программиста, который просит написать ему определение связности (cohesion) или сцепления (coupling). Очевидно, основам профессии в свое время он не обучился, а теперь ему нужно сдавать какой-то тест. С некоторым смущением я приступлю теперь к изложению материала, который вам должны были преподавать на первом курсе.
Описанные ниже принципы справедливы для любого процедурного языка программирования, но в SQL у них появляются свои особенности, поскольку это язык непроцедурный, ориентированный на работу с наборами данных и отягощенный вопросами взаимосовместимости.

Связность

Связность описывает, насколько хорошо модуль приспособлен для решения одной и только одной задачи, насколько он логически связен. В идеале модуль должен обладать очень сильной связностью, чтобы ему можно было присвоить имя в формате <глагол><объект>, где <объект> — логическая единица модели данных.
Имеется несколько видов связности. Ниже я перечислил их от самого плохого к самому лучшему:
1. Конъюнктивная;
2. Логическая;
3. Временная;
4. Процедурная;
5. Коммуникационная;
6. Информационная;
7. Функциональная.
Один модуль может обладать несколькими видами связности.
— Конъюнктивная связность.Наихудший вид связности. Он означает, что в модуле под одной крышей собрано несколько не относящихся друг к другу задач. Так бывает при использовании динамического SQL или при передаче в качестве параметра имени таблицы.
Допустим, имя модуля InsertNewCustomer() ясно говорит о том, что вы намереваетесь работать с таблицей, содержащей данные о клиентах. А вот процедура InsertNewRecord, предназначенная для добавления строк в любую таблицу схемы, слишком обща, чтобы обладать хорошей связностью. Она будет использоваться и для волынок, и для свадеб, и для осьминогов, и для любой новой таблицы, которая будет добавлена в схему позже.
Программисты должны избегать динамического SQL, поскольку он лишен связности и попросту опасен. Пользователь, которому приходится задавать имя таблицы, волен также включить в него добавочные операторы SQL. Например, вместо того чтобы передать просто имя таблицы, он может передать в процедуру строку “Foobar; DELETE FROM Foobar; COMMIT” и нанести серьезный ущерб БД. Использование динамического SQL также говорит о том, что программист не считает себя достаточно компетентным для написания кода и передает эту обязанность случайному пользователю.
Такой подход к программированию обычно является результатом попытки выполнить операции с метаданными посредством информационных таблиц схемы. У реализаций SQL есть собственные средства для работы с метаданными, и их не нужно переписывать.
— Логическая связность.Модули способны решать набор взаимосвязанных задач, но вызывающий модуль выбирает из них только одну. Худший образчик такого подхода встретился мне в 2004 г. в группе новостей по SQL Server. Некоему программисту приказали разместить все процедуры в одном модуле. Затем в зависимости от параметра осуществлялся выбор, который из пятидесяти с лишним модулей нужно выполнять и какие параметры использовать.
Так любят поступать объектно-ориентированные программисты. Каждая таблица кажется им объектом особого рода, а процедура напоминает метод объекта. Это на самом деле не так.
— Временная связность.Модуль выполняет набор действий, которые должны выполняться в одно время. Классический пример — объединение в модуле задач, связанных с запуском или остановкой системы. Этот метод типичен для старых программистов на Коболе, которые привыкли работать на системах пакетной обработки.
— Процедурная связность.Модуль осуществляет последовательность шагов процесса, которые должны выполняться в определенном порядке.Этот стиль также типичен для программистов, привыкших к работе всистемах пакетной обработки. Они же, как правило, создают много временных таблиц для хранения промежуточных результатов.
— Коммуникационная связность.Все элементы оперируют одним и тем же входным набором данных или создают один и тот же выходной набор данных. Части обмениваются информацией с помощьюобщих данных в глобальной таблице.
— Информационная связность,или последовательная связность.Выходные данные одного элемента поступают на вход другого элемента, но в отличие от случая логической связности коды для всех действий совершенно независимы друг от друга.
— Функциональная связность.Модуль служит для решения одной и только одной задачи или для достижения единственной цели. Лучшим примером такой связности являются математические функции. Функциональная связность — наша главная цель. Именно благодаря ей SQL еще называют функциональным языком.
Процедурная, коммуникационная, информационная и функциональная связности в SQL более сложны, чем в языке 3GL, поскольку в SQL у нас есть транзакции. Логически транзакция представляет собой один шаг, хотя и состоит из отдельных выражений SQL/





Сцепление

Модули, которые должны выполняться в определенном порядке, обладают сильным сцеплением. Если их можно выполнять независимо друг от друга, они слабо сцеплены. Существует несколько видов сцепления, которые перечислены ниже — от худшего к лучшему:
1. По содержимому;
2. По общей области;
3. По управлению;
4. По образцу;
5. По данным.
Вот какими свойствами они обладают.
— Сцепление по содержимомуозначает, что один модуль непосредственно обращается к содержимому другого модуля. Например, модульх передает управление на локальную метку в модуле у или модифицирует выражение в модуле у. Такие модули неразрывно связаны друг сдругом. Сцепление по содержимому опасно, но в продуктах SQL 4GL оно поддерживается редко. Главное правило — не передавать в качестве параметра SQL 4GL процедуру.
— Сцепление по общей областиозначает, что несколько модулей имеют доступ к одним и тем же глобальным данным. В SGL-языках этому соответствуют глобальные переменные. В SQL сцепление по общей области происходит при использовании для передачи информацииобщих глобальных таблиц. Оно может быть опасным, если контрольвзаимосовместимости не налажен должным образом.
— Сцепление по управлениюозначает, что один модуль управляет логической структурой другого, например, если модуль х вызывает модуль y, и у затем определяет, какое действие должен выполнить модуль х. Сцепление по управлению происходит, скажем, когда в качестве аргумента передается управляющее выражение-переключатель. В SQL так бывает с подзапросами, которые обращаются к другим частям схемы впредикатах, управляющих выполнением кода.
— Сцепление по образцуозначает, что в вызываемый модуль передается таблица целиком, хотя в действительности используются лишь некоторые ее столбцы. Основной пример в SQL — использование оператора SELECT *.
— Сцепление по даннымдвух модулей означает, что все аргументы являются скалярными элементами данных. Такие модули проще обслуживать, поэтому нужно всегда стремиться именно к сцеплению по данным. При этом уменьшается вероятность того, что изменения в одном модуле или таблице распространятся на другие модули или таблицы.

Наши рекомендации