Это только слегка переделанный перепост с другого форума. Прошу прощения, что отсылаю пост «как есть» с другого Российского форума. Очень долго переделывать, подстраиваясь под «настроение» обитателей здешнего форума.
Это насчёт того, зачем всё это надо.
*** МОТИВАЦИЯ ***
В моём учреждении разрабатывается техническое задание (ТЗ) на создание информационной системы (ИС). В ТЗ мы формулируем «что нам надо, и как нам надо». Проектировать и реализовывать эту систему будут сторонние разработчики, поскольку
мы – не программисты.
ИС – могутная и дорогостоящая. Разработка предполагается поэтапной (1-2 года). На каждом этапе, возможно, будут трудиться параллельно несколько фирм-разработчиков, реализующие отдельные составляющие ИС.
Одна из составляющей ИС – реляционные базы данных (БД) и соответствующие клиентские приложения. Мы намерены включить в ТЗ специальные требования к методам доступа к данным для разработчиков (для чего см. ниже). Предполагается, что программисты фирм-подрядчиков должны будут следовать требованиям ТЗ.
Предполагается, что на разных этапах разработки для разных БД разные подрядчики могут использовать любые языки программирования приложений (одни конторы будут писать на VB, другие Delphi или BCB++, третьи – MSVC++).
Сложность в том, что на стадии разработки ТЗ мы не можем сделать предположений относительно СУБД, которые могут изменяться при модернизации нашей ИС. Как впрочем, и относительно версий окошек рабочек и серверов и сетевой инфраструктуры. Т.е. сегодня у нас MS SQL Server, а «завтра», возможно мы переедем на оракл или db/2. Вопросы переноса данных с одной СУБД на другую СУБД при модернизации ИС не рассматриваются. Это наша забота.
К сторонним программистам предъявляется только одно требование – их клиентское ПО должно «жить» с новыми источниками данных без перекомпиляции. Это требование для нас важно.
Можно, конечно, в договоре с подрядчиком просто оговорить, что их клиентское ПО должно «жить независимо от СУБД»? Мои сомнения относительно «просто строчки в договоре» в том, что:
- это может остаться только декларацией (невыполнимой даже на 50 %).
- подрядчик может согласиться на эту «строчку», но фактически не станет реализовывать в своих проектах СУБД-независимые архитектурные решения.
**** ОБЪЕКТЫ ДОСТУПА К ДАННЫМ ****
Я попытался проанализировать несколько «сценариев», которые могут иметь место в зависимости от того, как подрядчик будет программировать.
BDE
Здесь, на мой взгляд, больше иллюзия «независимости приложения от СУБД», чем её реализация на сегодняшний день. Когда-то - это было кул, но не сегодня. Уже начиная с версии Delphi 5.0 в отличие от 3.0 (тоже, разумеется, касается и BCB++) я к удивлению обнаружил, что native SQL Links драйвера MSACCESS уже не работают, по тому, что мелкософт чего-то не поделил с Борландом. Поддержка компонентами Борланда ODBC-сокетов вообще дубовая (по сравнению с тем, если это делать в VC++ хотя бы с использованием MFC). Не факт, что у Борланда найдутся «работающие», а не просто продекларированные native драйвера SQL Links для некой новой версии Oracle, на которую возможно мы переедем в будущем.
Таким образом, приложение, написанное для нашего предприятия на BCB++ с использованием BDE может уже через год не работать, так как для нашей новой СУБД (установленной при модернизации ИС) нет подходящего native драйвера Борланда.
ODBC
Это более привлекательно по сравнению с BDE. Ясно, что никто не должен Борланду, но все должны мелкософту. Если уж вышла новая версия некого SQL сервера, то уж естественно его разработчики постарались с драйверами ODBC (иначе, как ЭТО будет юзастья под окошками старыми клиентами с доступом к данным по ODBC). Мой опыт показывает, что приложения работают устойчиво, если ЭТО программировать средствами VC++ а не использовать сокеты компонент Борланда. Опасения в части ODBC только такие, что производители серверного софта могут решить, что хватит постоянно реанимировать архаичные технологии доступа к данным, и что, для того чтобы их SQL сервер был самым SQL сервером в мире, следует использовать только ихние сверхпроизводительные OLE DB компоненты. Доля шутки в этой шутке в том, что мелкософт, как мне кажется, давно рассматривает ODBC как устаревший способ доступа к данным, хотя и тянет это API от операционки к операционке для продления жизни старого клиентского софта.
ADO
Наверное, это наименьшее зло из того, что выше. Сомнения только в том, что, не смотря на все заверения мелкософта, настоящим стандартом, на мой взгляд, ЭТО так и не стало (здесь я могу сильно ошибаться). Достаточно посмотреть, что теперь уже ADO не модно. Теперь правильное программирование - только с использованием ADO.NET. Мелкософт заверяет, что, мол, не волнуйтесь, будет, будет поддерживаться ADO вместе с ADO.NET в будущем. Но что-то сильно напоминает соотношение ODBC-ADO.
Кроме того, здесь тоже присутствует некая доля иллюзии «стандартности». Ясно, что в ASCII коде программы разработчик будет использовать действительно стандартный интерфейс к методам компонент ADO. Это радует. Но то, что его скомпилированная программа будет использовать вполне конкретную версию компонент MDAC – это может, на мой взгляд, в будущем принести огорчения. Впрочем, у меня есть практический опыт таких огорчений, когда мы так и не смогли под W98 полноценно прикрутить MDAC для комплекса «АКСИОК» (это могутный комплекс для госконтор. Не помню кто разработчик). Возможно, это было из моей криворукости, вернее криворукости моих сотрудников. Но факт- под W2k и XP работает на ура, а под W98 – через пень-колоду. Динамичность, с которой мелкософт развивает OLE DB просто пугающая. Поэтому и сомнительно, как это будет работать, когда мы переедем на новые версии окошек, где старая версия ADO поддерживается не в полной мере, или для новой версии SQL сервера старый провайдер («зашитый» в коде клиентского ПО) уже не поддерживается. Думаю, без перекомпиляции клиентской проги в этом случае не обойтись. Этого как раз и хочется избежать для нашей ИС. Повторяю, что я считаю ADO лучшим в части построения «живучих» программ. Выше я только о своих сомнениях, которые, возможно, из-за моей малограмотности.
**** МЕТОДЫ ДОСТУПА К ДАННЫМ ****
Положим, что в результате обсуждения на этом форуме мне объяснили мою дремучесть и невежество и рассеяли все сомнения относительно вышесказанного. Подсказали, что, мол, «забивай» в ТЗ требование – использовать только ADO. Спорно – хорошо ли. Боюсь, наше учреждение в этом случае может потерять в качестве потенциальных разработчиков тех программеров, которые не знакомы с ADO, или по какой-то причине его ненавидят.
Однако есть другой ряд причин, по которым даже использование ADO может не обеспечить требуемой «живучести» приложений нашей ИС, имхо. Программер использует вполне определённый синтаксис SQL. Разработчики всех промышленных СУБД декларируют, что поддерживают стандарт ANSI SQL. Мой опыт показывает, что не факт. Диалекты SQL, например, T-SQL для MSSQL Server, JET-SQL для MSAccess, SQL для SQL Links – различаются как в части синтаксиса DDL, так и DML (например, в определении скалярных функций преобразования типов данных). Конечно, можно в ТЗ ограничить программистов обязательством использовать только, действительно стандартные лексемы и, например, не использовать скалярные функции SQL вообще. Не факт, что программер будет придерживаться этого правила. Да это может быть и не удобным (почти всегда). Например, программер «зашивает» в код функцию cast в предложении select, тогда как после модернизации мы переехали на СУБД, драйверы которой понимают ключевое слово convert вместо cast. Программер «зашивает» в коде строчку ucase, тогда как после модернизации мы переедем на источник данных, драйверам которого надо будет говорить upper вместо ucase. С DDL – ещё хуже (хотя это обычно не критично для клиентской проги).
Поскольку с этими проблемами непереносимости диалектов SQL я сталкивался не раз при решении задач адаптации клиентской проги для работы с различными СУБД, то есть понимание, что ЭТО нельзя оставлять «на самотёк» в ТЗ. Я проблему решал в своё время, как мне казалось, просто. Все SQL запросы вначале отправлялись на претрансляцию. Там в зависимости от драйверов конкретного источника данных выполнялась «корректировка» лексем. Только после этого строка SQL отправлялась драйверу в том виде, в котором он эту строку понимает. Модули претрасляции выполняли «корректировку», пользуясь мапингом в «настроечных» ASCII-файлах (так я делаю сейчас), или в подключаемых dll (так я делал раньше).
*** ВЫВОД ***
Было найдено такое решение – разработать ведомственный, корпоративный стандарт, оговаривающий методы доступа к данным (для ведомственных контор). Этот стандарт предусматривает, по меньшей мере, три способа написания и использования в клиентских приложениях API доступа к данным:
1) API – построенное на COM
2) хэндл-ориентированное «обычное» API
3) COM-подобное API – для программистов С++ (удобнее, чем COM).
В техзадание оказалось возможным забить обязательство программистов (подрядчиков) использовать только это API. В коде клиентского ПО – ни каких вызовов мелкософтовского API или борландовских компонент. Используем только своё, самостийное API. Ясно, что такое API инкапсулирует объекты мелкософта или борланда (или и то и другое). Т.е. это API классов-обёрток.
В чём преимущество? Что это даёт? То, что такое API можно перекомпилировать при необходимости по десять раз в день, не нарушая работу клиенской проги нашей ИС. Придёт время в процессе модернизации ИС переписать это API для некого нового источника данных – это сможет сделать программер сравнительно невысокой квалификации. Даже я. Перекомпиляция клиентов не нужна вовсе. Три варианта написания и использования API включены в ТЗ, что бы как можно меньше связывать руки прикладным программистам.
*** МОДЕЛЬ****
Поскольку, как известно, легче пукнуть, чем понюхать, то, что бы в наш адрес не поступали такого рода рекламации от подрядчиков (Российские программеры очень капризны в последнее время) – была разработана «действующая модель» такого API. Дескать, всё реализуемо. Дескать, не надо, уважаемые господа программисты, волноваться и бояться. В кавычках я поставил «модель», поскольку использую её несколько лет. Когда я программирую в Борланде, у меня нет в проекте ни одного ихнего компонента доступа к данным. Т.е., ни в статике, ни в динамике не создаются и не используются компоненты типа TQuery и им подобные. Все только через API. Там есть и Query и не только.
Когда я программирую в MSVC, то в С++ коде нигде нет объявлений CDatabase, нет использования низкоуровневого API ODBC, нигде нет даже упоминания об ADO. Всё работает, как и в случае Борланда только через API.
Подрядчикам мы ПЕРЕДАЁМ исходники нашего API в качестве примера. Подрядчики вольны выбирать – или разработать своё собственное API (но обязательно с соблюдением наших требований на разработку API), или использовать наше, уже разработанное API.
Когда программист фирмы-подрядчика будет использовать хэндл-ориентированное API, он будет делать вызовы, аналогичные тем, что ниже (это фрагмент работающего кода):
Код: Выделить всё
Dim hr As Long ' код результата запроса
Dm I As Integer
hr = QueryOpen(hQuery, "select id from tbl1") ' выполняем запрос
If (hr <> S_OK) Then
MsgBox ("Can't open query")
Exit Sub
End If
QueryFirst (hQuery) ' указатель на первую запись
While (QueryEof(hQuery) = False)
I = vbQueryIntegerField(hQuery, "id") ' получаем данные текущей записи
…
…
QueryNext (hQuery) ' указатель на следующую запись
Wend
QueryFreeConnections (hQuery) ' удаляем временные объекты
QueryClose (hQuery) ' закрываем активный набор данных
Здесь нет вызовов методов объектов мелкософта или Борланда. Здесь используется один из вариантов API, о котором я писал. Если господа прикладные программисты любят COM, то они будут писать нечто вроде (это тоже фрагмент работающего кода)
Код: Выделить всё
hr = IQuery.Open("select id from tbl1") ' выполняем запрос
If (hr <> S_OK) Then
MsgBox ("Can't open query" & Chr(13) & IQuery.ErrorMessage)
Exit Sub
End If
IQuery.First ' указатель не первую запись
While (IQuery.IsEof = False)
Id = IQuery.IntegerField("id")
…
…
IQuery.Next ' указатель на следующую запись
Wend
IQuery.FreeConnections ' удаляем временные объекты соединения с базой данных
IQuery.Close ' закрываем активные наборы данных
В последнем случае клиент-«супертонкий». Реализация объектов доступа к данным лежит на мидлаврном сервере. Там и BDE, и ODBC вместе с OLE дебюми в одном флаконе (вернее там, то, что нужно мидлварному серверу компонент доступа к данным в зависимости от его текущей конфигурации).