Копия для печати
Быстрая разработка
Свои представления
вместо чужих, путь первый: схема
экрана есть схема данных
Сегодня организации не
принимают решения в пользу
собственной разработки ПО, т.к.
чиновник зачастую хочет чуда
сегодня, он не готов ждать, а
приобретение продукта сторонних
фирм практически всегда
оборачивается уже известными
проблемами: стоимость настройки ПО
превышает стоимость собственной
разработки, часть бизнес-процессов
не автоматизируется
предоставленным ПО или стоимость
автоматизации слишком велика и
проще использовать старые
разрозненные программы
предыдущего поколения. Выходом из
сложившейся ситуации могла бы
стать технология быстрого
написания, излагаемая ниже.
Сложность схемы базы данных и
запутанность настроек программы,
созданной для этой базы, примерно
одинаковы. Однако всегда сложнее
понять чужие мысли, чем изложить
свои собственные самому себе.
Поэтому вы создадите схему
базы-для-себя быстрее, чем
представите карту взаимосвязей
чужих настроек. И если бы на весах
лежали только схема и карта,
понятно, что бы вы предпочли.
Что же заставляет нас выбирать
плохое решение да ещё и платить за
него? Какую третью гирю мы должны
сбросить с первой чаши, чтобы
обрести сразу двойную выгоду? Мы
должны сбросить программирование -
или редуцировать его в
максимальной степени.
Это возможно, если обратить
внимание на одну тонкость - поля
вывода связаны отношениями IDEF1.
Экран программы имеет схему, и эта
схема полностью повторяет схему
базы данных!
Например, если мы выводим
сотрудников какого-либо
департамента (рис. 1), то
получившаяся иерархия является
калькой с отношений базы данных
(рис. 2).
 |
| Рис. 1 |
| |
 |
| Рис. 2 |
Здесь есть вторая тонкость -
синтаксис, выражающий иерархию,
например, "Departments.Persons" напрочь
отсутствует в SQL. В соединениях
таблиц (декартовых произведениях)
клиент не может разделить, какие
поля относятся к одной таблице,
какие - к другой. Получается, что,
извлекая информацию из базы данных,
мы теряем какую-то её часть!
Вместо того чтобы вставить
теряемую информацию машиной, мы
пытаемся сделать это вручную,
заставляя человека трассировать
работу компьютера. На это уходит до
50% рабочего времени. Трассировка
записывается в нотации LOOP/FETCH. Мы
извлекаем по одной записи для того,
чтобы найти связанные с нею. И эта
проблема до сих пор не
отрефлексирована индустрией.
Сильное решение есть. Это
выражения вида "SELECT * FROM
Departments.Persons" для извлечения
записей, уже связанных внешним
ключом. Департаменты и персоны
могут быть даже связаны не
напрямую, а через
таблицу-посредник, например,
таблицу "Sections" - тогда
упомянутый запрос будет выглядеть
так:
select Departments.Persons from Departments.Sections.Persons
where Departments/@name="E-banking";
Если обе таблицы ссылаются друг
на друга или одна ссылается на
другую несколькими внешними
ключами, то эта неоднозначность
разрешается в запросе дерева:
после, собственно, имени таблицы,
содержащей нужный внешний ключ,
ставится знак '#' и имя нужного
ссылающегося поля (не имя constraint-а,
т.е. внешнего ключа). Выглядит как
новое имя таблицы с символом '#' в
середине имени. Такое указание
имени ссылающегося поля будем
называть термином 'рафинирование'.
Например, если "последующая"
таблица ссылается на
"предыдущую" (рис. 3), то запрос
выглядит следующим образом:
select * from a.b#ref1.c#lnk1;
 |
| Рис. 3 |
и возвращает (для того, чтобы
представить иерархические данные,
мы должны использовать хоть
какой-то формат. Для удобства
визуального представления будем
применять XML. Внешние ключи,
использованные при построении
ответа, не должны выводиться1)
<a id=1 data=12.3>
<b#ref1 id=10 ref2=2 data=34.5>
<c#lnk1 id=100 lnk2=20 data=78.9/>
<c#lnk1 id=101 lnk2=20 data=89.1/>
</b>
<b#ref1 id=30 ref2=2 data=56.7>
<c#lnk1 id=200 lnk2=40 data=91.2/>
<c#lnk1 id=201 lnk2=40 data=88.8/>
</b>
</a>
Другой вариант ссылки одной
таблицы на другую несколькими
внешними ключами состоит в том, что
"предыдущая" таблица
ссылается на "последующую"
(рис. 4) и требует запроса вида
select * from a#ref1.b#lnk1.c;
 |
| Рис. 4 |
и возвращает
<a#ref1 id=1 ref2=20 data=12.3>
<b#lnk1 id=10 lnk2=101 data=23.4>
<c id=100 data=45.6/>
</b>
</a>
Аналогично, если таблица содержит
список и ссылается на саму себя
несколькими внешними ключами, то
эта неоднозначность также
разрешается в запросе дерева:
после, собственно, имени таблицы
ставится знак '$' и имя нужного
ссылающегося поля (не имя constraint-а,
т.е. внешнего ключа). Это также
выглядит как новое имя таблицы с
символом '$' в середине имени (рис. 5).
 |
| Рис. 5 |
Такое указание имени
ссылающегося поля также будем
называть термином 'рафинирование'.
Запрос для дерева выглядит так2:
select * from a.b$ref1.c$ref3;
и возвращает
<a id=88 data=77.7>
<b$ref1 id=1 ref2=20 data=12.3>
<c$ref3 id=3 ref4=70 data=3.1/>
<c$ref3 id=30 ref4=700 data=3.2/>
<c$ref3 id=300 data=3.3/>
</b>
<b$ref1 id=10 ref2=200 data=23.4>
<c$ref3 id=4 ref4=80 data=4.1/>
<c$ref3 id=40 ref4=800 data=4.2/>
<c$ref3 id=400 data=4.3/>
</b>
</a>
В тот момент, когда мы сможем
отразить схему базы данных на схему
экрана, минуя ручную трассировку,
мы сможем писать личное ПО.
Развитие этой идеи представлено в
разделе "Hierarchical data output"
отдельной презентации3. Автор
заинтересован во мнениях,
комментариях и возможной
реализации этих предложений. Все
предложения являются общественным
достоянием.
(Окончание следует)
Дмитрий ТЮРИН,
главный специалист департамента
ЦАБС "АСБ Беларусбанк",
член группы внедрения SAP R/3
1 Как вы заметили,
возвращаемые данные в имени
открывающего xml-тега содержат
дополнительную информацию,
необходимую для того, чтобы без
всякого программирования вставить
эти данные в базу данных. Эта
дополнительная информация
выглядит как новое имя
открывающего тега с символом '#' в
середине имени. Указание имени
ссылающегося поля в теге будем
называть термином
"детерминация".
2 В двух разных видах
рафинирования использованы разные
знаки - '#' и '$' - чтобы оба вида
рафинирования можно было
использовать одновременно:
'table#field1$field2'.
3 Слайды # 3-62 презентации sql50.euro.ru/sql5.17.0.pdf
Обсуждение статьи (записей: 0)