Рекомендуемая стратегия миграции для проекта C ++ в Visual Studio 6 - PullRequest
10 голосов
/ 02 июня 2010

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

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

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

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

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

Ответы [ 10 ]

12 голосов
/ 15 июня 2010

Я бы хотел взять пошаговое подход, где мы медленно перемещаем порции кода

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

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

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

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

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

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

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

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

Сколько человек вовлечено в проект?

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

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

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

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

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

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

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

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

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

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

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

  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) без (почти) проблем.

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

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

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

6 голосов
/ 15 июня 2010

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

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

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

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

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

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

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

4 голосов
/ 11 июня 2010

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

3 голосов
/ 17 июня 2010

Не уверен, почему так много людей выступают за 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. Если вы продали свое программное обеспечение как минимум 3 клиентам, которые все еще разговаривают с вами, и можете пройти самопроверку логотипа Windows 7 (через день или два я прошел через приложения VB 6), то вы можете получить 5-10 копий. всего (Windows, Office, VS) примерно за 1900 долларов в год, в зависимости от того, где вы живете.

3 голосов
/ 02 июня 2010

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

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

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

3 голосов
/ 02 июня 2010

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

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

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

Кроме того, еще раз, ВЕРНУТЬ ЕГО ПЕРВЫЙ! :)

2 голосов
/ 17 июня 2010

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

2 голосов
/ 02 июня 2010

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

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

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

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

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

1 голос
/ 02 июня 2010

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

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

0 голосов
/ 02 июня 2010

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

...