В и без того непростом процессе разработки программных продуктов время от времени появляются совсем уж неприятные вопросы. Один из них — что же делать со структурой БД, как хранить информацию о версиях, как обновлять копии БД на серверах да и как организовывать совместную работу.
База данных — это неотъемлемая часть вашего приложения. Если развернуть версию 2.0 этого самого приложения на базе данных версии 1.0, то, в общем случае, в итоге получится неработоспособная программа. Именно поэтому БД должна находится в системе контроля версий непосредственно рядом с исходниками программы.
Вся соль проблемы заключается в том, что условие «непосредственно рядом» в случае с БД довольно непросто выполнить. Встает вопрос о том, что именно хранить в системе контроля версий. Всю БД? Совершенно бессмысленное занятие. Всю заскриптованную схему БД? Как тогда делать инкрементальные изменения существующих структур? Скрипты с инкрементальными изменениями? Очевидно, это и будет самым правильным решением, однако же как удостовериться в том, что скрипты применяются в правильной последовательности, ровно столько раз, сколько требуется, и ровно на тех базах данных, на которых это необходимо?
Вот в этот момент на сцену выходят специальные средства.
Одно из них (начинается бессовестный пиар, ради которого все и затевалось) — octalforty Wizardby. Этот инструмент позволяет автоматизировать доведение схемы БД «до кондиции», сводя все необходимые манипуляции к двум вещам: написанию миграций и работе с консольным приложением, обрабатывающим упомянутые миграции.
По сути, «миграция» — это инструкция, говорящая о том, как из схемы БД версии N сделать схему версии N + 1. Другими (совсем другими) словами:
и далее:
то в итоге:
А вот если потом:
то Wizardby все равно все сделает самостоятельно:
Страница проекта (лицензированного под MIT License) находится здесь. Исходный код доступен либо в виде ZIP-архива, либо в SVN репозитории. Кроме того, есть ZIP-архив с уже скомпилированной версией. Документация же (на английском) — тут. А здесь можно посмотреть, как Wizardby используется в «реальной жизни».
Проблема
База данных — это неотъемлемая часть вашего приложения. Если развернуть версию 2.0 этого самого приложения на базе данных версии 1.0, то, в общем случае, в итоге получится неработоспособная программа. Именно поэтому БД должна находится в системе контроля версий непосредственно рядом с исходниками программы.
Вся соль проблемы заключается в том, что условие «непосредственно рядом» в случае с БД довольно непросто выполнить. Встает вопрос о том, что именно хранить в системе контроля версий. Всю БД? Совершенно бессмысленное занятие. Всю заскриптованную схему БД? Как тогда делать инкрементальные изменения существующих структур? Скрипты с инкрементальными изменениями? Очевидно, это и будет самым правильным решением, однако же как удостовериться в том, что скрипты применяются в правильной последовательности, ровно столько раз, сколько требуется, и ровно на тех базах данных, на которых это необходимо?
Решение
Вот в этот момент на сцену выходят специальные средства.
Одно из них (начинается бессовестный пиар, ради которого все и затевалось) — octalforty Wizardby. Этот инструмент позволяет автоматизировать доведение схемы БД «до кондиции», сводя все необходимые манипуляции к двум вещам: написанию миграций и работе с консольным приложением, обрабатывающим упомянутые миграции.
По сути, «миграция» — это инструкция, говорящая о том, как из схемы БД версии N сделать схему версии N + 1. Другими (совсем другими) словами:
migration "Oxite" revision => 1: <br> version 20090323103239:<br> add table oxite_Language:<br> add column LanguageID type => Guid, nullable => false, primary-key => true<br> add column LanguageName type => AnsiString, length => 8, nullable => false<br> add column LanguageDisplayName type => String, length => 50, nullable => false<br><br>* This source code was highlighted with Source Code Highlighter.
и далее:
то в итоге:
А вот если потом:
version 20090330170528:<br> oxite_User:<br> UserID type => PK, primary-key => true<br> Username type => LongName, unique => true<br> DisplayName type => LongName<br> Email type => LongName<br> HashedEmail type => ShortName<br> Password type => MediumName<br> PasswordSalt type => MediumName<br> DefaultLanguageID references => oxite_Language<br> Status type => Byte, nullable => false<br> <br> oxite_UserLanguage:<br> UserID references => oxite_User<br> LanguageID references => oxite_Language<br><br> index "" columns => [UserID, LanguageID], unique => true, clustered => true<br><br>* This source code was highlighted with Source Code Highlighter.
то Wizardby все равно все сделает самостоятельно:
Проект
Страница проекта (лицензированного под MIT License) находится здесь. Исходный код доступен либо в виде ZIP-архива, либо в SVN репозитории. Кроме того, есть ZIP-архив с уже скомпилированной версией. Документация же (на английском) — тут. А здесь можно посмотреть, как Wizardby используется в «реальной жизни».