Именование объектов в Oracle. Взгляд "со стороны"Источник: habrahabr Artem_7
"Старая песня о главном""Стандарты именование объектов БД" и "правила оформления кода" темы не новые. Так или иначе, к вопросу выработки или заимствования таких стандартов и правил приходят все команды разработчиков. При желании в сети можно найти статьи и презентации по данной теме, а так же примеры и шаблоны различных соглашений. Многие из них безусловно полезны, некоторые - практически идеальны, если бы не одна маленькая оговорка: они написаны разработчиками и для разработчиков. К сожалению, в моей субъективной реальности разработчики являют собой лишь некую абстракцию. Эдакие фантомы по ту сторону телефонной трубки, от которых меня отделяют тысячи километров и 3 часовых пояса. Прямого доступа в их коллективный мозг у меня нет. Доступны только образы, порожденные данным мозгом,- в виде объектов эксплуатируемой системы. В принципе, пожелания по оформлению и именованию у "прикладника" (администратора приложения/технолога) и разработчика на 90 процентов совпадают. Но существуют все же некоторые отличия в восприятии "читателя" и "писателя", о которых я хотел бы поговорить.
Почему именно СУБД Oracle? Мне она ближе и родней. А попытки объять необъятное с претензиями на универсальность не по моим зубам и компетенциям. В данном топике я попытался обобщить материалы статей Билла Коулэма (Bill Coulam), Стивена Ферстайна (Steven Feuerstein) и Тома Кайта (Tom Kyte) по данной теме и свой скромный опыт проектирования, разработки и эксплуатации различных информационных систем. Те, кому лень читать про разные подходы к именованию и продираться через доводы в защиту того или иного подхода, могут просто прокрутить статью до конца, где я привел ссылку на собственный "Oracle NC"-плакат. Там же вы сможете найти другие полезные ссылки по теме топика. Вы еще здесь? Смогли сдержаться и не начали скроллить? Поздравляю, вам достается специальный бонус: вы можете скачать "Oracle NC"-плакат прямо здесь, не сходя с этого места. Дело в том, что я уже читал свою статью (да-да) и заранее предупреждаю: она громоздка и изобилует малопонятными с первого взгляда врезками-шаблонами. Воспринимать ее будет гораздо проще, имея под рукой все правила и примеры на одном листе.
Все знают, что главное в танке, но не каждый может сдержаться…Казалось бы, идея выработки NC для проекта в сфере IT лежит на поверхности. Соблюдение требований NC при проектировании и разработке, тоже задача не бог весть. Однако ж, мой опыт работы с решениями от ведущих российских разработчиков на рынке биллинговых систем для телекоммуникационных компаний говорит о том, что культура именования объектов и оформления исходного кода на деле крайне низка. В принципе, все решения, которые по долгу службы были мной изучены, можно поделить на четыре группы:
Я не хочу углубляться в анализ причин п.п. 1-3, я просто констатирую факт. Все, что я хочу - помочь сделать шаг к "мечте" п. 4. Итак, начнем.
Общие рекомендацииНачнем с того, о чем следует помнить и чему следовать при разработке под СУБД Oracle:
Правила именования объектовТаблицыВ вопросе именования таблиц я почти полностью разделяю точку зрения Билла Коулэма. Разработанный им стандарт исчерпывающ и практически идеален, как для разработчика, так и для "эксплуататора". Я не буду приводить здесь полный перевод, остановлюсь только на основополагающих моментах. Итак, Коулэм предлагает следующую универсальную форму именования таблицы (фигурные скобки включают обязательные компоненты, а "прямые" скобки - опциональные): Группа используется для тех же целей: она позволяет группировать сущности, логически связанные между собой (обычно до 20 объектов в группе). Представляет собой так же сокращение в 2-4 символа. Использование системной и логических групп позволяет не только группировать сущности в дереве объектов, но и существенно упрощает разработку и сопровождение системы в целом. Действительно, исчезает необходимость запоминать наименования конкретных объектов, достаточно помнить аббревиатуры модуля и логической группы, а дальше подсказчик кода поможет легко найти необходимый вам объект. С Наименованием все понятно. Это и есть фактическое название сущности. Билл Коулэм рекомендует использовать единственное число, но лично мне ближе и привычнее множественное (Стивен Ферстайн, привет!). И Стивен и Билл советуют избегать сокращений в наименованиях сущностей. Исключения - слова длиннее 8 символов. Не всегда назначение таблицы удается выразить одним словом. В этом случае некоторые отечественные разработчики по привычке пользуются правилом, которое я про себя называю "Правилом товарного чека", когда порядок слов идет от общего к частному, от сущности к свойствам. Т.е. "Бумага туалетная", вместо "Туалетная бумага", "Огурцы маринованные", а "Паста томатная". К сожалению, в англоязычных наименованиях это чаще всего выглядит ужасно. Сравните YELLOW_SUBMARINE и SUBMARINE_YELLOW . В данном случае я не вижу смысла опираться на единый шаблон, а рекомендую использовать тот порядок, который более уместен в конкретном контексте. Роль - по сути назначение (тип назначения) таблицы в системе. Коулэм выделяет около двух десятков ролей, но на мой вкус некоторые из них избыточны. Приведу только те, которые использую я:
В отдельный класс Коулэм выделяет таблицы, посредством которых реализуется взаимосвязь "многие-ко-многим". Для таких таблиц он предлагает следующий шаблон именования:
Колонки (столбцы) таблицНачнем с ограничений общей длины наименования - старайтесь уложиться в 15 символов (лучше - меньше). Запас до верхнего ограничения вам понадобится для последующего именования ограничений, индексов и столбцов с внешним ключом. В своих проектах я использую следующий шаблон: [Код таблицы_]{Наименование столбца}[_Роль] Код таблицы представляет собой сокращенное наименование таблицы, которой принадлежит колонка (2-4 символа). Хоть я и обозначил данный префикс опциональным, я его использую почти для всех столбцов. Исключение - "служебные" столбцы, которые хранят значение неких свойств абстрактной записи любой таблицы, а не свойств конкретного объекта (например, UPDATE_DATE , UPDATE_BY и т.п.). Наименование столбца говорит само за себя. Отдельно хочется сказать только о правиле формирование наименования для внешнего ключа - оно состоит из кода дочерней таблицы плюс полное наименованием родительского первичного ключа. Роль - опциональный суффикс. Обращаю внимание, что это тип значения столбца, а не код типа данных этого столбца! Чаще всего я использую следующие роли (типы значений):
Многие считают шаблон (а, конкретно, префикс в виде кода таблицы) избыточным. Однако я, имея возможность сравнивать разные подходы, выбрал для себя именно его. Приведу свои доводы:
ОграниченияКоулэм рекомендует именовать ограничения, используя префикс в виде полного имени таблицы, на которую данное ограничение распространяется. Я считаю такое именование необоснованным расточительством, особенно с учетом общего лимита в 30 символов на длину наименования. Поэтому стараюсь, где возможно использовать Код таблицы вместо полного имени. Таким образом, для первичного ключа получаем: [Модуль_][Группа_]{Код таблицы}{_PK} Здесь и далее префиксы Модуль и Группа ограничения получают в "наследство" от таблицы, с которой они связаны. Это позволяет избежать нарушений уникальности при формировании имен в больших системах, а так же удобно группировать ограничения по модулям. Для уникального ключа, построенного на одном столбце: Для уникального ключа, построенного на нескольких столбцах: Внешний ключ на базе одного столбца: Внешний ключ, построенный на нескольких столбцах: ИндексыИндексы я обычно делю на три категории:
Индексы на базе ключей (первичного и уникального) именуются так же, как и соответствующие им ограничения: [Модуль_][Группа_]{Код таблицы}{_PK} [Модуль_][Группа_]{Шаблон столбца}{_UK} [Модуль_][Группа_]{Код таблицы_}{CОMP_UK}[_#] Индексы на базе одного столбца: [Модуль_][Группа_]{Шаблон столбца}[_Роль]{_IDX} Под Ролью в данном шаблоне понимается модификатор типа индекса. Коулэм рекомендует использовать следующие модификаторы:
Индексы на основе нескольких столбцов. Коулэм рекомендует следующую форму: [Модуль_][Группа_]{Код таблицы}{_COMP}[_Роль]{_IDX}[#] Я считаю шаблон Коулэма частным случаем и всегда стараюсь перечислить все столбцы (если при этом не нарушается ограничение по длине) в наименовании индекса: [Модуль_][Группа_]{Код таблицы_}{Список столбцов}[_Роль]{_IDX} Почему я ограничиваюсь модификатором COMP для ограничений, но стараюсь не использовать его для индексов? Все дело в том, что составные ограничения все-таки являются скорее исключением, чем правилом. Их обычно не очень много, да и сообщение с ошибкой об их нарушении встречаются не очень часто. Другое дело - составные индексы. Во-первых, их просто много. Во-вторых, их часто больше одного на таблицу. И, в третьих, разработчик и администратор приложения работает с ними постоянно, проверяя планы запросов.
ТриггерыВ данной статье я рассматриваю только триггеры DML, потому что считаю, что все остальные типы относятся больше к зоне ответственности DBA, а не разработчика. Триггеры я именую по следующим правилам: [Модуль_][Группа_]{Код таблицы}[_Цель/Роль]_{B/A/C (I/U/D)[S]}[_#] Где аббревиатуры B, А, С ( BEFORE , AFTER , COMPOUND ), определяют "момент" срабатывания триггера; I, U, D ( INSERT , UPDATE , DELETE ) - событие срабатывания; S ( STATEMENT ) - определяют "уровень" срабатывания. В своих проектах я выделяю две "типизированные" Цели (роли) триггеров:
ПредставленияПравила именования представлений ничем не отличаются от правил именования таблиц. Единственное пожелание - включать в наименование признак, что данный объект является именно представлением. Подходы тут могут быть разные. Я встречал данный признак в виде префикса имени. Например, V_ или даже V$, как у системных представлений Oracle. Лично я использую суффиксы:
Но вам не посоветую. Знак доллара в качестве разделителя - дело привычки. Это "якорь" для моих глаз, который позволяет отличить таблицу от представления. Объективно на данных подход я взглянуть не могу, поэтом ничего не имею против знака "нижнего подчеркивания", как у Ферстайна (суффиксы _V и _MW).
ПоследовательностиПоследовательности я выделяю среди других объектов суффиксом _SEQ и рекомендую именовать по следующему правилу: [Модуль_][Группа_]{Код таблицы / Полное наименование столбца / Цель}{_SEQ} Код таблицы (сокращенное наименование таблицы 2-4 символа) используется для последовательностей, служащих для генерации суррогатного первичного ключа таблицы. Наименование столбца (а у нас оно, напомню, включает код таблицы) используется для генерации значения колонки, не входящей в первичный ключ. На самом деле, это вырожденный случай, который я реально не использую. Если последовательность не используется для генерации значений первичного ключа - в наименовании я стараюсь отразить Цель данной последовательности. Для примера, последовательность для генерации первичного ключа таблицы INTERNET_LOGINS я назову ILG_SEQ , а последовательность для генерации логина конкретной учетной записи интернет - LOGIN_SEQ .
СинонимыСинонимы именуются так же, как и объекты, на которые они ссылаются
ТипыПо типам, у меня нет окончательно сформированного мнения. Я встречал разные подходы к именованию этих объектов, но так и не смог до конца определиться, какой подход мне ближе. Опишу здесь те, которые не вызывают во мне негативных реакций: [Модуль_][Группа_]{Наименование}[_Признак коллекции]T Данный шаблон рекомендует Коулэм. Признак коллекции типа обознается символом Т. Таким образом, тип одиночного объекта всегда имеет суффикс _T, тип коллекции - _TT. Например, UTL_PARAMETER_T , UTL_PARAMETER_TT . [Модуль_][Группа_]{Наименование}[S]_TYP Здесь S обозначает множественное число, а суффикс TYP квалифицирует объект БД как тип. Например, UTL_PARAMETER_TYP , UTL_PARAMETERS_TYP . Это подход мне нравится менее всего, потому что признак коллекции не выделен и глаз за него не цепляется. [Модуль_][Группа_]{Наименование}_{OBJ / TAB} В данной нотации, если наименование объекта БД заканчивается на OBJ или TAB, то объект является типом (TAB - коллекция, OBJ - одиночный объект). Например, UTL_PARAMETER_OBJ , UTL_PARAMETERS_TAB
Программные модулиПравила оформления кода программных модулей я хотел бы выделить отдельную статью. Здесь приведу шаблон, предлагаемый Коулэмом. Для пакетов процедур Билл использует следующее правило: [Модуль_][Группа_]{Цель/Назначение}[_Функцион. модификатор][_PKG] В терминах NC Коулэма Функциональный модификатор (для меня понятнее термин Подгруппа) используется при выделении каких-то функций в отдельный пакет при рефакторинге. Скажем так, это дополнительный уровень логической группы. Например, пакет UTIL содержал функции работы с числами и строками. Его разбили на два: UTIL_NUMBER и UTIL_STRING . При разработке в PL/SQL специалист постоянно оперирует функциями и процедурами других пакетов. Чтобы код не смотрелся громоздким, я стараюсь избегать ненужного удлинения в наименовании пакетов. Поэтому суффикс _PKG использую только в случаях, когда наименование пакета может совпадать с наименованием другого объекта схемы. Для отдельных процедур и функций Коулэм рекомендует следующий шаблон:
ЗаключениеКак и обещал, привожу ссылку на собственный "Oracle NC"-плакат. Я, ни в коем случае, не навязываю никому свои правила и стандарты и не настаиваю на их использовании. Я просто считаю наличие NC и соблюдение его требований в команде хорошим стилем - "вежливостью" разработчика к тому, кто будет работать впоследствии с системой. Удачи вам в ваших проектах. P.S. Внимательный читатель безусловно заметил мой маленький обман. Первая цель статьи так и не была достигнута: далеко не все типы объектов СУБД Oracle описаны в статье и присутствуют в NC-плакате. Что же, у вас есть шанс исправить этот недочет. Вы можете скачать "исходник" NC-плаката и отредактировать его под свои цели и задачи. В статье использованы следующие источник:
|