Pull to refresh
4
0
Send message
Спасибо за комментарий!
  1. Этот код далеко не везде нужен именно в таком виде, благо ссылками на классы пользуются не слишком часто;
  2. Код на Delphi, из которого родился этот код, как-то тоже не очень поддерживаем;
  3. Вышеприведённый код — код сразу «с пылу-с жару» из-под конвертера, более того — конвертер, на текущий момент, еще дорабатывается — многие вещи ещё поменяются (к примру, на текущий момент активно решаем как именно реализовывать изменение символов в строке — в Delphi это делается через индексер, а вот в C# строка так не умеет);
  4. Что именно показалось неподдерживаемым?
    • Необходимость эмуляции конструкторов также, как в Delphi (с возможностью вызова базового конструктора в любом месте конструктора наследника)?
    • Или необходимость эмуляции типов class of?
    • Или всё-таки страшная конструкция s.Substring() + 'a' + s.Substring()?



В любом случае, сейчас ведётся работа по «перестройке» кода так, чтобы он выглядел лучше. Многие «сервисные» вещи будут спрятаны за #region...#endregion
Хранимые процедуры на уровне базы данных делают все это без особого труда, да и все возможных nosql хранилищ с легким api тоже полно

Вопрос в том, что программисты FoxPro редко даже на их «комплексную БД» переходят, а уж про nosql и речи нет.
там огромное кол-во кода написано для работы с xml/json, экспорта в Excel, работы с архивами, работы с базами данными

Про конкретно тот проект, который мы переводили (да и тот, что я приводил в качестве примера в начале статьи) это совсем неверно. В проекте 2001 года действительно нужного кода было больше 60% — он эксплуатировался до тех пор, пока предприятие, для которого велась разработка, не решило себе купить SAP R3… Купили, потратили $20 млн ТОЛЬКО на настройку… а оно не заработало. А вот новый (сменившийся за 4 месяца до решения о переходе на R3) начальник отдела автоматизации купил себе квартиру в центре Москвы и, вроде как еще какую-то недвижимость в Европе. Неплохо для новоиспечённого начальника отдела автоматизации компании, расположенной за 6 000 км от Москвы, да?
Про экспорт в Excel — Visual FoxPro сам умеет таблицы в Excel «выкидывать»… или отчёты — точно не помню, помню только, что умеет и мы это в миграционной библиотеке реализовали.
Проект на Visual, опять-таки был, видимо, изначально очень неплохо спроектирован — там используется ровно одно место для общения с MS SQL (функция, которая, с помощью макросов, исполняет SQL запрос и возвращает результат, а в случае ошибки — реализует отображение нормального окошка с текстом ошибки). Так что спагетти кода там было не так много.
Отличный пост, приму на заметку.
Небольшой комментарий не въедливости ради, а для того, чтобы у тех, кто будет использовать этот код, не произошёл «нежданчик»:
Скрытый текст
Эта строка:
Dispatcher.CurrentDispatcher.Invoke(() => UIBlocked());

и вторая для UIReleased — нет ни проверки на null, ни первичного переноса значения делегата в отдельную переменную (что настоятельно рекомендуется, тем более, что в этом месте гарантирована многопоточность).

Это FoxPro и люди, которые на нем писали либо со времен DOS'а, либо со времён Windows 95.
Там очень часто для «быстрой» выдачи отчётов используют генерацию гигантских таблиц со сводными данными.
Единственное светлое место в том приложении заключалось в том, что достаточно большой пласт таких «сводных» обновлений они вынесли в SP, а на той стороне был достаточно шустрый сервер, который всё съедал быстро.
P.S. Из смешного, если бы не хотелось плакать. Когда мы первый раз подняли эту базу у себя (на виртуальной машине) — нам «немного» поплохело при первом же запуске и попытке работать. В результате собрали для первичного тестирования машинку с 32 Гб памяти и зеркалом на SATA-3 — тогда хоть немного быстрее зашуршало чтение данных, ну и гигабитная сеть здесь решала, как выяснилось — перекачка данных в 500-600 МБ для обработки на клиент — вполне себе регулярная задача была (я в одном из комментариев уже описывал).
Я вот только не могу понять — это много или мало?
основные данные на запись — это всяческие промежуточные данные для отчётов, сводные прайсы, сводные отчёты и подобное.
Больше половины объёма БД занимают справочники, проводки и приходно/расходные операции. Именно этим обусловлен высокий процент покрытия БД на чтение и относительно невысокий на запись.
Результаты примерные — так докладывал наш тестер (для сравнения использовался, если ничего не путаю, dbCompare). Для мониторинга чтения — что-то настраивали в SQL Profiler.
Как я уже ответил ниже — ошибка в вычислениях где-то произошла — на самом деле 1 300 человеко лет.
Сейчас исправлю в статье.
Упс, спасибо за комментарий — пересчитал — где-то ошибся при подсчётах.
там 1 300, однако… Сейчас поправлю всю арифметику, но цифры всё равно очень большие выходят.
На самом деле — те программисты писали больше — это были реально ОЧЕНЬ хорошие работники и пахали они «за совесть» — порядка 12/14 часов в сутки стабильно, суммарно, по прикидкам, они написали 15-16 млн. строк кода, просто часть кода писалась «поверх» другого — исправления в связи с изменениями законодательства и требований заказчика — всё это время система активно эксплуатировалась.
Еще раз спасибо за исправление — сейчас допишу в статье.
Да, реальные use cases проходились вручную — затраты на написание инструмента или покупку готового + его настройку были бы выше, чем зарплата того человека, который их выполнял.

Про данные — судя по изменениям, use cases охватывали около 85% данных на чтение и 100% данных за месяц/квартал (в зависимости от конкретного use case) на запись.

В целом, на запись охватывалось около 25-30% данных всей БД (база за два года — заказчики «устаревшие» данные убирали в архив средствами MS SQL).
Как раз для FoxPro у нас, пожалуй, самый продвиеутый инструмент. Формы 1-в-1, алгоритмы — тоже.
Самое забавное — даже раскраски в ячейках таблиц пашут адекватно.
P.S. забыл написать. FoxPro мы перетаскиваем в C# + WPF + MVVM. Получается интересно. Ну и скинов для контролов мы в какой-то момент делали 3 или 4, с подменой «на лету», а также — поддержку Zoom'а (чем и хорош WPF)
Для такой уверенности у нас было 3 основания:
1. конвертация делалась 1-в-1, порядлк выполнения операций было видно глазами, более того, в исходниках на новой платформе мы в комментариях оставляли копию изначального кода старого приложения — можно было сравнить визуально.
2. для различных частных мест (сложная выборка из БД, сложный расчет и т.п.) мы писали тесты, которые создавали клон данных, прогоняли тест и далше сравнивали результирующие данные с эталоном.
3. все очень сложные алгоритмы прохдили через «пошаговое» тестирование, то есть: выполняем шаг в старой системе — берем данные, выполняем шаг в новой системе — сравниваем. особо «интересные» места вытаскивались в тесты прошлого раздела. Такое пошаговое тестирование — это, конечно, долго, но пройдя сложные use case таким макаром по паре/тройке раз мы получади очень качественный охват кода тестами.
P.S. в конце проекта у нас был второй тестовый проект (не просто unit test'ы, которые можно регулярно запускать, а длинные тесты, суммарно часа на полтора-два), так в нём было порядка 350 тестов. Всё это давало гарантию одинаковости алгоритмов.
прохождение сценариев делается, обычно, вручную.
А с нуля написать не так просто — из реального опыта: 60 сценариев суммарно занимали около 50 часов на прохождение. там весьма сложные алгоритмы, описаний которых нет, а суммарно в сценариях, по примерным прикидкам, использовалось порядка 70% когда приложения. Часть сценариев в процессе прохождения требовали больше 100 пользовательских действий типа «выбрать строку, нажать кнопку, выбрать элемент комбо бокса, и т.д.» и требовали работы в более, чем 10 формах. Это был ад — у нас специально выделеный человек все время проекта (полгода) спера собирал use cases, а потом их тестировал.
К тому же, иногда бывает еще один фактор сложности — человее, который единственный знает старую систему может просто отказаться помогать ее переписывать, так как перестанет быть незаменимым.
Про охват данных — мы тестировали тот проект на копии боевой базы. Объем бэкапа — 500 Гб, развернутая база — около 750 Гб.
Какой именно пример?
Если нужен пример куска кода — могу кинуть, если скриншоты GUI — это чуть подольше — пара дней нужна (надо добраться до тех мест, где это всё есть).
На самом деле, я могу «родить» пример переноса кода прямо сейчас — тут же подход такой — при разработке конвертера мы определяем, как именно какие конструкции в какие будут переводиться, дополнительно решаем, какие типы из старой платформы будут подменяться на типы в новой (даже для custom типов, зачастую) Соответственно строится и mapping методов/полей/свойств.
С одной стороны — всё просто, с другой — сложно.
P.S. Утром постараюсь выложить примеры кода прямо в статью через UPD.
P.P.S. Про сложность переноса — согласен, порой получается очень, так скажем,
нетривиально
Интереса для, если не сталкивались, попробуйте прочитать про области видимости переменных в FoxPro. Конкретно — области видимости для переменных, созданных через конструкции Public, Private и Local. И попробуйте себе представить, как это должно выглядеть в C#. Мы данную проблему решили — у нас получилось, в своё время, разработать 100% автоматический переводчик из Visual FoxPro 9 в C#. Именно 100% автоматики (а причина простая — у FoxPro есть развёртывание макросов + есть функция Eval().
.

Вы абсолютно правы!
Цель миграции не только в том, чтобы перенести код на другую платформу (хотя и это — тоже цель).
Цель в том, чтобы:
  1. перенести приложение «прозрачно для тётушек со склада» (обычно — 4-8 классов образования — увы), то есть сохранить внешний вид и функционал,
  2. перенести код, оставив его хоть в какой-то мере похожим на тот, что был раньше (облегчить сотрудникам IT отдела переход с проекта на проект),
  3. оставить ВСЕ фичи (ну и баги, конечно) старой версии, все алгоритмы, которые годами нарабатывались (ниже есть пример одного из мест, где алгоритм нужно, конечно, менять, но подобные задачи тоже можно, порой, обработать автоматом или же, по крайней мере, отметить подобные места — слишком «типичный» вид)
  4. по возможности подготовить приложение к рефакторингу в процессе переноса.

Так что «писать абы как» тут не подойдёт.
P.S. Ну и как, опять-таки, я объяснял в другом комментарии — речь идет о миллионах (минимум — сотни тысяч, где первая цифра больше пятёрки) строк — там невозможно сохранить высокую скорость написания кода. Даже если писать код по ТЗ с нуля.
Ответ чуть другой.
Тестов, обычно, нет.
Сдается по простому алгоритму: а процессе миграции некоторое количество особенно продвинутых пользователей описывает набор use-cases, которые постоянно используются в системе (на систему в 1 000 000 строк на FoxPro их оказалось около 70).
После миграции проверяется, что все use-cases отрабатывают на одинаковых данных одинаково.
К сожалению, на предприятиях действительно много систем, которые не имеют документации, автор которых давно ушёл (а порой — и умер), тестов нет, есть только огромный объем исходных текстов и огромные же объемы действительно ценных данных.
Если переписывать что-то с небольшим общим объемом — да, можно лопатить и 1000+ строк в сутки.
Но здесь мы вернёмся к описанию задачи:
  1. в проектах, обычно, миллионы строк кода.
  2. В расчетах в сроки переписывания не включены отдельно, как можно заметить, ни отладка, ни тестирование, ни все остальное — это тоже очень большие расходы времени, которые стоят денег

30 строк в день — это средняя скорость. сюда включается и тестирование, и отлов багов, и корректировка отличий в работе плавающих вычислений (например иногда в Delphi и C# немного по-разному происходит окургление), иногда — надо переделывать работу с данными.
Про данные приведу отдельный пример:
в FoxPro при обработке больших (действительно больших) объемов данных принято делать так:
  1. выдергиваем данные из SQL Server'а через хранимую процедуру (которую лучше не трогать — упадет) в локальную таблицу DBF (например — 250-300 тысяч строк, я лично встречал и пару миллионов).
  2. Обрабатываем таблицу (проходя по каждой записи и выполняя над ней какие-либо действия),
  3. Группируем локальную таблицу, сохраняя сгруппированный результат в другой локальной таблице.
  4. Создаем relation типа master->detail, где главная таблица — таблица с группировками
  5. открываем форму, в которой отображаются все эти данные.

без реализации РЕАЛЬНО быстрой работы с каким-либо локальным хранилищем таблиц, поспорить в скорости выполнения данной задачи с FoxPro почти не реально — надо думать над переписыванием алгоритма, либо искать способ быстрой работы с локальными данными.
Кстати, про скорость локальных хранилищ
Работа с DBF файлами FoxPro — самый быстрый способ работать с таблицами, имеющими строгую структуру, возможность иметь до 231 записей, поддержку индексов, мемо полей и многого другого.
За скорость мы платим отсутствием транзакций, но FoxPo' шникам не привыкать

В общем, есть множество дополнительных задач, которые приходится так или иначе решать. Отсюда средняя скорость 30 строк в сутки… которая более-менее реалистична для действительно хороших разработчиков. Для тех, кто обычно сидит в IT отделах старых компаний, имеющих подобный софт — это очень высокая скорость.
P.S. А расчет с 300 строк/сутки тоже не убеждает?
Начну как еврей с вопроса-на-вопрос: «а много Вы видели систем, разработанных лет этак 20 назад на FoxPro / Delphi, в которых бы реально были тесты?!»
А если серьёзно — речь идёт о монстрах, миллионы строк кода, написанных по принципу «ген. директор в 17:45 захотел новый отчёт — к 10:00 должно работать» — обычно тут не до тестов.
Кроме того, в те годы особо и не было тестовых движков, да и про Test Driven Development и Unit Testing никто особо и не слышал…

Information

Rating
Does not participate
Location
Новосибирск, Новосибирская обл., Россия
Registered
Activity