Немецкий секс или перевод проекта с Delphi 1 на Delphi 3
Как-то подходит ко мне начальник и говорит:
- А вы проект с Delphi 1 на Delphi 3 перевести можете ?
- Как два байта переслать - говорю я. Но, вспомнив о ReportSmith и о перетаскивании отчетов с одной версии QuickReport на другую, я добавил: - ну если там будут отчеты, то это будет намного сложнее.
Прошло несколько недель. Меня вызывает директор фирмы и говорит:
- Есть заказ от немцев. Надо проект с Delphi 1 на Delphi 3 перевести. Ты руководишь проектом. Поставь их программу, глянь исходники, разберись и оцени трудоемкость. Для вас эта работа полезна. Посмотрите западный стиль программирования, поучитесь.
Дали мне задание, архивы с исходниками и инсталлятором. В задании было написано:
- перевести базу данных с Access -2 на Access -97;
- изменить исходные коды, так, что бы получить 32-bit EXE-файл на Delphi 3;
- оптимизировать исходные тексты, общие процедуры и функции повторяющиеся в разных модулях вынести в один;
- изменить подключение к базе данных – вместо ODBC использовать BDE native drivers.
Роюсь в старых компактах, нахожу Access-2 и Delphi 1 - ставлю. Затем распаковываю немецкий инсталлятор, а там несколько каталогов и куча всяких файлов, для их установки требуется какой-то WinINSTALL 5.1 (Network Application Installer for Windows (c) Copyright 1991-1997 by Seagate Software, Inc.). Спросил у людей – никто о нем и не слышал. Посмотрел, а файл описывающий действия инсталлятора в текстовом виде, да и поставил все это ручками по командам в этом файле: скопировал файлы, настроил пути в ini-файле, настроил ODBC и BDE.
После часов двух работы немецкое детище заработало. Оно представляло собой систему поверки оборудования и состояло из трех частей (программы для снятия показаний с оборудования нам переделывать не надо): из головной программы и двух программ по обработке данных полученных при тестировании оборудования. Отчетов не было. Головная программа копировала обработанные данные в базу на сети. Посмотрев задачу, на утро я дал заключение:
- Если не напрягаться, то на выполнение задания надо около месяца.
Посоветовавшись, немцам зарядили трудоемкость два месяца - денег больше и время на решение непредвиденных обстоятельств было бы.
2. Стиль программирования
Начав работу над кодом мы быстро ознакомились с их "стилем программирования":
1) Все формы находились в автокрейт (наверно для экономии ресурсов :-))
2) На нескольких формах проекта находились объекты TDatabase, которые дублировали друг друга (в них указаны одни и те же алиасы) и периодически открывались и закрывались
3) Сотни неиспользуемых переменных
4) В одной процедуре они несколько раз могли динамически создать один и тот же объект, провести с ним какие то операции, убить его... Например они частенько создавали TQuery и TTable
5) Для подсчета количества записей в таблице они динамически создавали объект TTable, открывали и получив RecordCount - высвобождали объект. Правда RecordCount они использовали редко, чаще можно было видеть:
nli := 0;
While not TempTable.EOF do
begin
nli := nli +1;
Next;
end;
Спрашивается, почему бы не выполнить запрос "SELECT COUNT(*)" ? Также они проверяли пуста ли таблица.
6) Метод Prepare у Query вызывался после каждого динамического задания текста запроса, даже когда запрос не имел параметров или вызывался один раз. Зачастую использовались такие конструкции:
For i:=0 to k do
begin
TempQuery.SQL.Clear;
TempQuery.SQL.Add('SELECT * FROM TABLE');
TempQuery.SQL.Add('WHERE Z=:Z');
TempQuery.Prepare;
TempQuery.Params[0].asInteger := i;
TempQuery.Open;
...
TempQuery.Close;
end;
7) Глаз резали конструкции:
if A.Count > 0 Then
btn_Delete.Enabled := True
else
btn_Delete.Enabled := False;
Почему их не заменить на более простую
btn_Delete.Enabled := A.Count > 0 ?
или
if (Row = 7) Or (Row = 6 )
Then CanSelect := True
else Canselect := False;
Почему их не заменить на более простую
CanSelect := (Row = 7) or (Row = 6 );
или похожая
if (bNumForm = True) Or (bTimeForm = True)
Then Result := True
else Result := False;
заменить на
Result := bNumForm Or bTimeForm;
8) Про оптимизацию процедур:
Var
nlCol : longint;
begin
nlCol := grd_stat_istwerte.Col;
if nlCol < 8 Then
grd_stat_istwerte.LeftCol := 1;
if nlCol >= 8 Then
grd_stat_istwerte.LeftCol := nlCol -6;
End;
Можно заменить
begin
if grd_stat_istwerte.Col < 8
Then grd_stat_istwerte.LeftCol := 1
else grd_stat_istwerte.LeftCol := grd_stat_istwerte.Col -6;
end;
9) Работа с таблицами была немного странной:
if ta_SS.Active = False Then
ta_SS.Open;
if not (ta_SS.State = dsEdit) Then
ta_SS.Edit;
try
ta_SS.Post;
except
end;
Почему бы сразу проверки состояние таблицы, если она редактировалась не вызвать метод Post ?
if ta_SS.State = dsEdit then
ta_SS.Post;
10) Если на различные события нужен был одинаковый обработчик, то его код повторялся (при необходимости много раз).
3. Что не взлюбил компилятор D3
Сразу при компиляции исходного текста полезли ошибки:
1. Переменные цикла изменялись внутри цикла:
For i:=1 to k do
begin
....
i := x-1;
end;
2. В операциях со строками использовалась хитрые операции:
- операция ++
messagetxt := 'Ihre '+IntToStr(i) ++ ' fertige';
- операция := +
messagetxt := + stText+'tot';
3. В связи с тем, что String теперь не 256 байт, а до двух гигабайт, то конструкции для определения длины строки Path[0] пришлось заменять на Length(Path) (Path - String)
4. Если функция была описана как
function zformat(Var Text : String) : Boolean;
то следующий код вызывал несовпадение типов:
Var
st : String[5];
Begin
...
if zformat(st) = True then
5. В конструкциях
With TempQuery do
begin
...
FindFirst(file_path, faAnyFile, SearchRec); // поиск файла
...
end;
компилятор ругался на неправильные параметры у FindFirst, т.к. воспринимал как метод у объекта (TempQuery.FindFirst), в таких местах пришлось править на SysUtils.FindFirst
4. Исправление ошибок
Ошибки лезли отовсюду. Вот несколько - самых распостраненных:
1. Зачастую переменные цикла использовались и после завершения цикла. Если в Delphi1 после выполнения цикла for i:=1 to k переменная i имела значение k, то в Delphi 3 переменная принимала значение k+1, что естественно приводило к неправильному функционированию программы в целом.
2. Если составной индекс в БД создан из трех полей, а в программе для поиска задавалось IndexFieldNames := 'id;vor' - два поля из индекса, то после вызова GotoKey ничего не находил. Пришлось создавать новые индексы.
5. Работа над ошибками
Завершив работу досрочно все упаковали и кинули немцам на тестирование. Через неделю пришел ответ: "Тестировать сейчас некогда, т.к. люди заняты в других проектах. Мы вам доверяем тестирование. Предлагаем вам снять копии экранов с 16-бит приложения и соответствующие им 32-битные картинки." Повозмущавшись, мы наснимали им чуть больше 50 мег картинок. Отослав их мы спокойно жили несколько недель. Затем пришел файл от немцев с описанием замечаний и ошибок. Ошибки были страшные:
- увеличить длину Label, т.к. надписи у них не помещаются;
- растянуть кнопки, чтобы надпись помещалась. Прикол был с кнопкой Cancel: задаем Kind равный bkCancel у нас надпись помещается, а у немцев под немецкой Delphi вместо "Cancel" выводится "Abrechen", которое не помещается на кнопке.
- зачастую для редактирования данных использовался StringGrid, положение и размер которого на диалоге рассчитываются в программе. Количество колонок, строк, их высота и длина тоже рассчитывались. После перехода на Delphi 3 гриды сдвинулись, текст перестал помещаться в ячейки, появились скролбары. Для каждого пришлось подбирать оптимальный размер на форме и коэффициенты для расчета высоты и длины ячеек.
- В шапке некоторых гридов был установлен стиль у шрифта fsBold, им это в 32-bit версии не понравилось - слишком жирный шрифт (в 16-bit было нормально).
- Для тог, чтобы немцы вводили четыре цифры года мы вставили ShortDateFormat:='dd.mm.yyyy'. Из-за этого кое где на диалогах появилась дата 0208.19.99 - результаты форматирования и старых шаблонов.
В результате один наш сотрудник на неделю ездил в Германию, для исправления ошибок. Как оказалось, ПО которое мы дорабатывали, писал самый толковый программист в их конторе.
Данная статья конечно не отражает уровень разработчиков ПО в неметчине, но заставляет задуматься. О подобных случаях частенько рассказывают знакомые, которые работают на западных заказчиков.
Copyright© 1999 Scrooge Специально для Delphi Plus
| 2011 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2010 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2009 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2008 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2007 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2006 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2005 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2004 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2003 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2002 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2001 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 2000 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 1999 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
Последние статьи
- Компания по разработке программного обеспечения
- Услуги аутсорсинга в области программирования
- Как продлить срок службы картриджей
- Мошенничество во Всемирной Паутине. Осторожно: фишинг!
- Web-студия
- Как легально поднять уровень индекса цитирования.
- Мы реально сможем помочь вам в управлении предприятием
- Создание сайтов – популяризация вашего замысла
- Свой сайт. Управление ресурсом
- Семантическое ядро сайта или правила подбора ключевых фраз
Литература
- Программирование в среде Delphi 8 for .NET
- Практикум по Delphi для решения прикладных задач
- Фундаментальные алгоритмы и структуры данных в Delphi
- Delphi 6. Программирование на Object Pascal
- Delphi и технология COM
- Delphi в шутку и всерьез: что умеют хакеры
- Программирование в Delphi глазами хакера
- Delphi 2005. Секреты программирования
- Искусство создания компонентов Delphi
- Приемы программирования в Delphi на основе VCL
- Программирование баз данных в Delphi 7
- Программирование баз данных в Delphi
- Программирование в среде Delphi
- Программирование в Delphi 7
- Язык SQL в Delphi 5