Мы все еще используем UML. Как другие здесь, я нахожу, что они значительно помогают в коммуникации. Для людей намного легче связаться, когда у них есть визуальные средства (введите популярность PowerPoint). Это особенно верно в начальных фазах проекта, где сценарии как объясненный firebird84 происходят много. Кропотливая сторона к UML является содержанием схем однажды разработчики на кодировании запуска проекта.
Мы не генерируем код прочь их, хотя и я должен все же лично говорить с кем-то, который использовал UML до той степени.
У меня есть запись в блоге о том, как управление версиями базы данных dbisam и сервер sql .
Важные части:
Поскольку dbisam не поддерживает представления, номер версии сохраняется (вместе с кучей другой информации) в ini файл в каталоге базы данных.
У меня есть модуль данных, TdmodCheckDatabase. Это имеет Компонент TdbisamTable для каждой таблицы в базе данных. Компонент таблицы содержит все поля в таблице и обновляется всякий раз, когда таблица изменено.
Чтобы внести изменения в базу данных, был использован следующий процесс:
- Увеличить номер версии в приложении
- Внести и протестировать изменения в БД.
- Обновить затронутые таблицы в TdmodCheckDatabase
- При необходимости (редко) добавить дополнительные запросы на обновление в TdmodCheckDatabase. Например, чтобы установить значения новых полей, или добавить новые строки данных.
- Создайте единичный скрипт CreateDatabase, используя предоставленную базу данных. tools.
- Обновить модульные тесты для соответствия новой базе данных
Когда приложение запущено, оно с помощью следующего процесса
- . Если база данных не найдена, запустите модуль CreateDatabase, а затем выполните шаг 3
- Получить текущий номер версии из ini-файла базы данных
- Если он меньше ожидаемого номера версии, тогда Запустите CreateDatabase (для создания любых новых таблиц) Проверьте каждый компонент таблицы в TdmodCheckDatabase Применить любые изменения таблицы запускать любые сценарии обновления вручную
- Обновить номер версии в ini-файле базы данных
Пример кода:
class procedure TdmodCheckDatabase.UpgradeDatabase(databasePath: string; currentVersion, newVersion: integer);
var
module: TdmodCheckDatabase;
f: integer;
begin
module:= TdmodCheckDatabase.create(nil);
try
module.OpenDatabase( databasePath );
for f:= 0 to module.ComponentCount -1 do
begin
if module.Components[f] is TDBISAMTable then
begin
try
// if we need to upgrade table to dbisam 4
if currentVersion <= DB_VERSION_FOR_DBISAM4 then
TDBISAMTable(module.Components[f]).UpgradeTable;
module.UpgradeTable(TDBISAMTable(module.Components[f]));
except
// logging and error stuff removed
end;
end;
end;
for f:= currentVersion + 1 to newVersion do
module.RunUpgradeScripts(f);
module.sqlMakeIndexes.ExecSQL; // have to create additional indexes manually
finally
module.DBISAMDatabase1.Close;
module.free;
end;
end;
procedure TdmodCheckDatabase.UpgradeTable(table: TDBISAMTable);
var
fieldIndex: integer;
needsRestructure: boolean;
canonical: TField;
begin
needsRestructure:= false;
table.FieldDefs.Update;
// add any new fields to the FieldDefs
if table.FieldDefs.Count < table.FieldCount then
begin
for fieldIndex := table.FieldDefs.Count to table.Fields.Count -1 do
begin
table.FieldDefs.Add(fieldIndex + 1, table.Fields[fieldIndex].FieldName, table.Fields[fieldIndex].DataType, table.Fields[fieldIndex].Size, table.Fields[fieldIndex].Required);
end;
needsRestructure:= true;
end;
// make sure we have correct size for string fields
for fieldIndex := 0 to table.FieldDefs.Count -1 do
begin
if (table.FieldDefs[fieldIndex].DataType = ftString) then
begin
canonical:= table.FindField(table.FieldDefs[fieldIndex].Name);
if assigned(canonical) and (table.FieldDefs[fieldIndex].Size <> canonical.Size) then
begin
// field size has changed
needsRestructure:= true;
table.FieldDefs[fieldIndex].Size:= canonical.Size;
end;
end;
end;
if needsRestructure then
table.AlterTable(); // upgrades table using the new FieldDef values
end;
procedure TdmodCheckDatabase.RunUpgradeScripts(newVersion: integer);
begin
case newVersion of
3: sqlVersion3.ExecSQL;
9: sqlVersion9.ExecSQL;
11: begin // change to DBISAM 4
sqlVersion11a.ExecSQL;
sqlVersion11b.ExecSQL;
sqlVersion11c.ExecSQL;
sqlVersion11d.ExecSQL;
sqlVersion11e.ExecSQL;
end;
19: sqlVersion19.ExecSQL;
20: sqlVersion20.ExecSQL;
end;
end;
Здесь похожая история. Мы храним номер версии БД в «системной» таблице и проверяем его при запуске. (Если таблица / поле / значение не существует, значит, мы знаем, что это версия 0, в которой мы забыли добавить этот бит!)
Во время разработки, когда и когда нам нужно обновить базу данных, мы пишем сценарий DDL для выполнения работать, и когда он доволен, что он работает нормально, он добавляется в качестве текстового ресурса в приложение.
Когда приложение определяет, что ему необходимо обновить, оно загружает соответствующий ресурс (-ы) и запускает его / их. Если необходимо обновить несколько версий, он должен запустить каждый сценарий по порядку. Оказывается, это всего лишь несколько строк кода.
Суть в том, что вместо использования инструментов на основе графического интерфейса пользователя для изменения таблиц специальным или «случайным» образом мы фактически сразу пишем DDL. Это значительно упрощает, когда придет время, для создания полного сценария обновления. И структурное различие не требуется.
What I do is store a version number in the database, and a version number in the application. Every time I need to change the database structure, I create some code update the structure of the database, and increase the version number in the application. When the application starts, it compares, numbers, and if need be runs some code to update the database structure AND update the database's version number. Thus the database is now up to date with the application. My code is something like
if DBVersion < AppVersion then
begin
for i := DBVersion+1 to AppVersion do
UpdateStructure(i);
end
else
if DBVersion > AppVersion then
raise EWrongVersion.Create('Wrong application for this database');
UpdateStructure just runs the necessary code something like :
procedure UpdateStructure(const aVersion : Integer);
begin
case aVersion of
1 : //some db code
2 : //some more db code
...
...
end;
UpdateDatabaseVersion(aVersion);
end;
You can actually use the same code to create the database from scratch
CreateDatabase;
for i := 1 to AppVersion do
UpdateStructure(i);
Я использую ADO для своих баз данных. Я также использую схему номеров версий, но только для проверки работоспособности. У меня есть программа, которую я разработал, которая использует Connection.GetTableNames и Connection.GetFieldNames для выявления любых несоответствий с XML-документом, который описывает "главную" базу данных. Если есть несоответствие, я создаю соответствующий SQL для создания недостающих полей. Я никогда не отбрасываю дополнительные.
У меня есть таблица dbpatch, которая содержит список исправлений, идентифицированных по уникальному имени. Если отсутствуют определенные патчи, они применяются, и соответствующая запись добавляется в таблицу dbpatch. Чаще всего это новые сохраненные процедуры, изменение размера полей или индексы
. Я также поддерживаю min-db-версию, которая также проверяется, поскольку я разрешаю пользователям использовать старую версию клиента,