Рекомендуемая стратегия миграции проекта C++ в Visual Studio 6

Для крупного приложения, записанного в C++ с помощью Visual Studio 6, что лучший способ состоит в том, чтобы переместить в современную эру?

Я хотел бы проявить поэтапный подход, куда мы медленно перемещаем части кода и пишем новые возможности в C#, например, и компиляцию, что в библиотеку или dll, на который можно сослаться из унаследованного приложения.

Действительно ли это возможно и что лучший способ состоит в том, чтобы сделать это?

Править: В этой точке мы ограничены выпусками Экспресса, которым я верю, не позволяют использование библиотек MFC, которыми в большой степени пользуются в нашем текущем приложении. Это - также настоящее крупное приложение с большим количеством аппаратных зависимостей, таким образом, я не думаю, что оптовая миграция находится в картах.

Edit2: мы изучили запись COM-перенесенных компонентов в C#, но наличие никакого COM испытывает, это страшно и сложно. Действительно ли возможно генерировать C# dll с прямым-C интерфейсом со всем управляемым совершенством, скрытым внутри? Или действительно ли COM является необходимым злом?

10
задан jacobsee 2 June 2010 в 14:52
поделиться

10 ответов

Столкнувшись с той же задачей, моя стратегия была бы примерно такой:

  1. Определить, что мы надеемся получить, переходя к разработке 2010 года - это могло бы быть

    • улучшенное обеспечение качества: модульное тестирование , mocking являются частью современных средств разработки
    • приятный пользовательский интерфейс: WPF обеспечивает современный внешний вид.
    • продуктивность: в некоторых областях разработка .NET более продуктивна, чем поддержка разработки C ++
    • : новые инструменты поддерживаются с улучшениями и исправлениями.
  2. Определите, какие части системы не выиграют от переноса на C #:

    • доступ к оборудованию, низкоуровневый алгоритмический код
    • в значительной степени самый индивидуальный рабочий код, не связанный с пользовательским интерфейсом - нет смысла выбрасывать его, если он уже works
  3. Определите, какие части системы необходимо перенести на C #. Для этих частей убедитесь, что текущая реализация на C ++ разделена и модульна, чтобы эти части можно было заменить. Если приложение является монолитом, потребуется значительная работа по его рефакторингу, чтобы его можно было разбить и выбрать части, повторно реализованные на C #. (Можно ничего не реорганизовать, вместо этого просто сосредоточьтесь на реализации новых функций приложения на C #.)

  4. Теперь, когда вы определили, какие части останутся в C ++, а какие будут реализованы в C # (или просто оговорите, что новые функции есть в C #), фокус переходит на то, как интегрировать C # и C ++ в единое решение.

    • используйте COM-оболочки - если ваш существующий проект C ++ хорошо использует объектно-ориентированный подход, это часто не так сложно, как может показаться. В MSVC 6 вы можете использовать классы ATL, чтобы предоставлять свои классы как компоненты COM.
    • Прямая интеграция собственного кода и кода C #. Для интеграции "устаревшего" скомпилированного кода требуется промежуточная DLL - подробности см. здесь .

Смешивание пользовательского интерфейса MFC и пользовательского интерфейса C #, вероятно, невозможно и не рекомендуется, так как это приведет к смешению пользовательского интерфейса двух разных стилей (серый цвет 1990-х годов и атмосфера 2010 года). Проще сосредоточиться на достижении инкрементной миграции, такой как реализация нового кода приложения на C # и вызов его из собственного кода C ++. Благодаря этому объем переносимого кода C # с самого начала остается небольшим. По мере того, как вы углубляетесь в разработку 2010, вы можете брать более крупные фрагменты, которые нельзя переносить постепенно, например пользовательский интерфейс.

6
ответ дан 3 December 2019 в 14:10
поделиться

Если вы перейдете сразу с 6 на 2010, вы можете оказаться с перепутанными настройками проекта. Если это не очень большой проект, и он один из немногих, которые вам нужно преобразовать, то все должно быть в порядке. Просто откройте его в 2010 и следуйте указаниям мастера преобразования. Не забудьте сначала сделать резервную копию проекта и проверить настройки проекта после завершения работы.

На мой взгляд, лучший способ - это конвертировать проект шаг за шагом через каждую итерацию Visual Studio. Мне нужно было модернизировать 1400 проектов с 2003 до 2010, и лучшим способом, который я нашел, было преобразовать все в 2005, затем в 2008 и, наконец, в 2010. Это вызвало у меня наименьшее количество проблем.

Если у вас есть только 6 и самая новая Visual Studio, вы можете просто попытаться перейти на новую версию с помощью мастера. Ожидайте некоторой ручной очистки, прежде чем все снова соберется правильно.

Кроме того, еще раз повторю, сначала создайте резервную копию! :)

.
3
ответ дан 3 December 2019 в 14:10
поделиться

Для начала я бы постарался сохранить как можно больше код, насколько это возможно, чтобы избежать перезаписи. Я бы также удалил весь неиспользуемый код перед началом преобразования.

Начиная с версии VC ++ 6.0 Microsoft изменила библиотеки MFC и стандартную библиотеку C ++.

Я рекомендую начать сборку ваших DLL без зависимостей, затем просматривать ваши сторонние библиотеки, а затем перестраивать одну зависимую DLL / EXE за раз.

Вводите модульные тесты, чтобы убедиться, что поведение кода не меняется.

Если у вас смешанная сборка, использующая разные версии VC ++, вам необходимо принять меры против передачи ресурсов (дескрипторов файлов) между библиотеками DLL, которые используют разные версии среды выполнения VC.

2
ответ дан 3 December 2019 в 14:10
поделиться

Высокоуровневый код C++, вызывающий низкоуровневый код C#, не выглядит хорошей идеей. Области, в которых языки .NET лучше, это пользовательский интерфейс, доступ к базе данных, работа в сети, работа с XML файлами. Низкоуровневые вещи, такие как вычисления, доступ к оборудованию и т.д., лучше оставить в виде родного кода на C++.

Переходя на .NET, в большинстве случаев лучше полностью переписать пользовательский интерфейс, используя технологии WPF или Windows Forms. Низкоуровневые вещи остаются родными, а для связи C# и родного кода используются различные технологии взаимодействия: PInvoke, обертки C++/CLI или COM-взаимодействие. Через некоторое время вы можете решить переписать низкоуровневые нативные компоненты на C#, только если это действительно необходимо.

По поводу компиляции нативного C++ кода в VS2010 - я не вижу никаких проблем. Просто исправьте все ошибки компиляции - новые компиляторы имеют более строгую проверку типов и синтаксические ограничения, и отлавливают гораздо больше ошибок во время компиляции.

3
ответ дан 3 December 2019 в 14:10
поделиться

Visual Studio 6 славится своей ошибкой и медлительностью. Переход в современную эру лучше всего осуществить с помощью нового компилятора. Что, вероятно, проще всего сделать, это написать устаревшее приложение в DLL, а затем записать исполняемый файл на C # и использовать P / Invoke. Тогда вам больше не придется трогать старый код - вы можете просто писать все больше и больше на C # и все меньше и меньше использовать старую DLL.

Если в вашем старом коде очень много объектно-ориентированного программирования, вы можете использовать C ++ / CLI для написания классов-оболочек, которые позволяют .NET вызывать методы для объектов C ++, а также собирать их, если вы используете интеллектуальный указатель с подсчетом ссылок.

1
ответ дан 3 December 2019 в 14:10
поделиться

Вы можете использовать C# для написания новых компонентов с оберткой COM или COM+ (System.EnterpriseServices), которые будут вызываться из существующего кода C++.

0
ответ дан 3 December 2019 в 14:10
поделиться

Во-первых, ваше определение современной эпохи спорно. Нет никаких оснований считать, что C# в каком-то смысле лучше, чем C++. Много говорилось о том, помогает ли C# лучше избегать ошибок управления памятью, но это вряд ли так с современными средствами в C++, и, очень легко сделать беспорядок в C# в плане времени получения ресурсов, что может зависеть от того, что делают другие программы.

4
ответ дан 3 December 2019 в 14:10
поделиться

Если это вообще возможно с финансовой точки зрения, я бы настоятельно рекомендовал просто заплатить деньги за ту версию Visual Studio, которая вам нужна, потому что вы вполне можете потерять больше денег на потраченном времени. Я не знаю достаточно об экспресс-версиях, чтобы дать хороший ответ по ним, но при интеграции кода от субподрядчика, который был написан на C++, я использовал C++ / CLI. Вы, вероятно, сможете повторно использовать большую часть своей кодовой базы и будете знакомы с языком, но у вас также будет доступ к управляемому коду и библиотекам. Кроме того, если вы захотите начать писать новый код на C#, вы сможете это сделать. Самая большая проблема, с которой я столкнулся, заключается в том, что в VS 2010 отсутствует intellisense в C++ / CLI.

2
ответ дан 3 December 2019 в 14:10
поделиться

Я хочу использовать инкрементную подход, где мы медленно перемещаем порции кода

Это единственный реальный способ сделать это.

Во-первых, какой контроль версий вы используете? (Если вы используете управление версиями ветвления, которое позволяет вам проводить эксперименты и видеть, что работает, сводя к минимуму риск компрометации вашего кода; другие тоже в порядке, но вам нужно быть очень осторожным в зависимости от того, что вы используете).

Правка : Я только что видел, что вы используете SVN. Возможно, стоит перейти на mercurial или git, если у вас есть на это право (изменение обеспечивает качественный скачок в том, что вы можете делать с базой кода).

и напишите новые функции на C # для пример и скомпилируйте его в библиотека или dll, на которые можно ссылаться из устаревшего приложения.

Это ... не обязательно хорошая идея. Код C # может предоставлять COM-интерфейсы, доступные в C ++. Написание клиентского кода на C ++ для модулей, написанных на C #, может быть забавным, но может оказаться утомительным (с точки зрения соотношения усилий и выгод); Он также медленный и подвержен ошибкам (по сравнению с написанием клиентского кода C # для модулей, написанных на C ++).

Лучше подумать о создании инфраструктуры приложения на C # и использовании модулей (уже написанных на C ++) для основных функций.

Возможно ли это и что лучше как это сделать?

Да, это возможно.

Сколько людей задействовано в проекте?

Если их много, лучшим способом было бы, чтобы несколько (два? Четыре?) Работали над новой структурой приложения, а остальные продолжали работать в обычном режиме.

Если их мало, вы можете подумать о том, чтобы за это отвечал либо человек, либо больше людей, работающих неполный рабочий день.

Процент людей / усилий, назначенных для каждого (обслуживание старого кода и разработка нового кода), должен зависеть от размера команды и ваших приоритетов (Является ли переход проблемой низкого приоритета? date?)

Лучший способ сделать это - начать адаптировать модули кода, чтобы их можно было использовать в нескольких сценариях (как со старым, так и с новым кодом), и продолжить разработку параллельно (опять же, это было бы очень упрощается за счет использования разветвленной распределенной системы контроля версий).

Вот как я бы это сделал (итеративная разработка с небольшими шагами и множеством проверок достоверности между ними):

  1. Выберите функциональный модуль (что-то, что не связано с графическим интерфейсом пользователя) в старой кодовой базе.

  2. Удалите ссылки на код MFC (и другие библиотеки, недоступные в VS2010 Express, например ATL) из модуля, выбранного на шаге 1.

    Не пытайтесь переписать функциональность MFC / ATL с помощью специального кода, за исключением небольших изменений (которые то есть невозможно решить создать свою собственную структуру графического интерфейса пользователя, но можно решить написать свою собственную оболочку указателя интерфейса COM, аналогичную CComPtr ATL).

    Если код сильно зависит от библиотеки, лучше разделить его как можно больше, а затем пометить его, чтобы в будущем его можно было переписать с использованием новых технологий. В любом случае, для библиотеки, сильно зависящей от MFC, лучше переписать код, используя что-нибудь еще (C #?).

  3. максимально уменьшите связь с выбранным модулем (убедитесь, что код находится в отдельной библиотеке, четко определите, какие функции модуль предоставляет клиентскому коду) и получите доступ к функциям с разделителями только через определенный открытый интерфейс (в старом код).

  4. Убедитесь, что старая кодовая база по-прежнему работает с модифицированным модулем ( тест - в конечном итоге автоматизируйте тестирование для этого модуля ) - это критично , если вам все еще нужно оставаться в market, пока вы не сможете отправить новую версию.

  5. Поддерживая текущее приложение, запустите новый проект (на основе C #?), Который реализует графический интерфейс и другие части, которые необходимо модернизировать (например, части, сильно зависящие от MFC). Это должно быть тонкоуровневое приложение, желательно независимое от бизнес-логики (которое должно оставаться в унаследованном коде, насколько это возможно).

    В зависимости от того, что делает старый код и определяемые вами интерфейсы, может иметь смысл использовать C ++ / CLI вместо C # для частей кода (он может работать с собственными указателями C ++ и управляемым кодом, что позволяет создавать простой переход при взаимодействии между управляемым кодом .NET и собственным кодом C ++).

  6. Заставить новое приложение использовать модуль, выбранный на шаге 1.

  7. Выберите новый модуль, вернитесь к шагу 2.

Преимущества:

  • будет выполнен рефакторинг (необходим для разделения модулей)

  • , в конце у вас должен быть набор тестов для ваших функциональных модулей (если вы еще этого не сделали).

  • вам еще есть что отправить.

Несколько примечаний:

  • Если вы не используете распределенную систему управления версиями ветвления, вам лучше работать над одним модулем за раз. Если вы используете ветвление / распределенное управление исходным кодом, вы можете распространять разные модули среди разных членов команды и централизовать изменения каждый раз, когда что-то новое было перенесено.

  • Очень важно, чтобы каждый шаг был четко разграничен (чтобы вы могли откатить свои изменения до последней стабильной версии, попробовать что-то новое и т. Д.). Это еще одна проблема, с которой сложно справиться с SVN и легко с Mercurial / Git.

  • Перед запуском измените имена всех файлов проекта на расширение .2005.vcproj и сделайте то же самое для файла решения. При создании нового файла проекта сделайте то же самое с .2010.vcxproj для файлов проекта и решения (вы все равно должны сделать это, если вы конвертируете решения / проекты). Идея состоит в том, что вы должны иметь оба параллельно и открывать, в зависимости от того, что вы хотите, в любой момент. Вам не нужно делать обновление исходного дерева для другой метки / тега / даты в системе управления версиями только для переключения IDE.

Edit2: Мы писали Компоненты с оболочкой COM в C #, но без опыта работы с COM это страшно и сложно.

Вы все еще можете сделать это, написав код оболочки (например, небольшой шаблонный класс интеллектуальных указателей для COM-интерфейсов не помешает - аналогично CComPtr в ATL). Если вы изолировали код COM за некоторыми оболочками, вы могли бы написать клиентский код (не зависящий от COM) без (почти) проблем.

Можно ли сгенерировать dll C # с прямым интерфейсом C со всеми управляемое добро, спрятанное внутри? Или COM - необходимое зло?

Не знаю. Я думаю, что COM станет неизбежным злом, если вы планируете использовать серверный код, написанный на C #, и клиентский код на C ++.

Возможно и наоборот.

12
ответ дан 3 December 2019 в 14:10
поделиться

Не знаю, почему так много людей выступают за COM. Если у вас еще нет большого количества COM, научиться делать это на стороне C ++ будет больно, и тогда вы будете использовать максимально медленное взаимодействие с управляемой стороны. Не мой первый выбор.

В идеале вы перестроили свой пользовательский интерфейс на основе бизнес-логики. Затем вы можете создать новый пользовательский интерфейс (WPF, WinForms, ASP.NET, веб-службы, которые поддерживают какой-либо другой клиент, что угодно) и вызвать свою бизнес-логику через P / Invoke или написав оболочку C ++ / CLI. @mdma дает вам хороший совет, предполагая, что рефакторинг возможен.

Однако , если бы вы платили мне за то, чтобы я пришел и помог вам, мой самый первый вопрос был бы: почему вы хотите это сделать? Некоторые клиенты говорят, что они больше не хотят платить разработчикам C ++, поэтому они хотят, чтобы весь код C ++ исчез. Это пугающая цель, потому что все мы ненавидим прикасаться к работающему коду. Некоторые клиенты хотят предоставить свою логику ASP.NET, службам Reporting Services или чему-то еще, поэтому мы сосредоточились на рефакторинге. Некоторые говорят: «Это похоже на 1999 год», и для них я показываю им, как сейчас выглядит MFC. Цвета, скиннинг / тематика, включая внешний вид офиса и win7, лента, плавающие / закрепляемые панели и окна, интеграция с панелью задач Windows 7 ... если вы просто хотите выглядеть по-другому, взгляните на MFC в VS 2010, и вам, возможно, не придется настраивать любой код вообще.

Наконец, чтобы сделать неэкспресс-версии VS 2010 доступными, ознакомьтесь с Партнерской программой Microsoft.Если вы продали свое программное обеспечение как минимум трем клиентам, которые все еще разговаривают с вами, и можете пройти самотестирование логотипа Windows 7 (у меня есть приложения VB 6 через день или два), то у вас может быть 5-10 копий. всего (Windows, Office, VS) примерно за 1900 долларов в год, в зависимости от того, где вы живете.

3
ответ дан 3 December 2019 в 14:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: