0,0
рейтинг
11 февраля в 16:04

Разработка → Избавляемся от Visual Basic из песочницы

image

Вот и настал тот переломный момент, когда мы решили перевести два проекта с VB на С#. Кому интересно — прошу под кат.

Введение


Данные проекты нам достались от подрядческой организации, которая писала их на протяжении лет 5-6. В общей сложности это около 1,5 млн. строк кода, если верить средству оценки метрик в Visual Studio, из которых около 30% на C#, а остальное на VB. Почему мы решили это сделать?! Скорее всего из-за нежелания работать с VB и отсутствия хороших vb-разработчиков.

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

Подготовка


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

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

Почему относительно?! Да потому, что после конвертации, в любом случае, имеется нотка неизвестного поведения программы. Это может всплыть сразу, если у вас код не покрыт 100% тестами. В нашем случае, я про тесты вообще промолчу, ибо нет их вовсе. Ну что ж – рассмотрим, что за шаги мы выделили:

1) Выбор инструмента для конвертации

Это очень важный этап на таком нелегком пути, ведь от того какую пилу выберешь, будет зависеть скорость и качество распила. После многочисленных вопросов гуглу и совещаний, мы остановились на двух продуктах: Instant CSharp и SharpDevelop версии 4.х (в версии 5.х конвертация не поддерживается), что очень странное, на мой взгляд, решение.

SharpDevelop бесплатен – это несомненно плюс, но и Instant CSharp имеет free версию, которая не отличается функциональностью от платной версии, лишь имеется ограничение на число строк в конвертируемом проекте. Плюсом Instant CSharp является то, что он лучше конвертирует WinForms. Есть у него и минус – это корректная конвертация только UTF файлов.

Решили использовать Instant CSharp для мелких проектов, а SharpDevelop для всего остального.

2) Составление списка VB проектов и формирование диаграммы зависимостей

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

image

На данной диаграмме также указано число зависимостей между проектами. Из диаграммы, да и по логике вещей, видно, что порядок преобразования проектов — от проектов с меньшим количеством зависимостей к проектам с большим количеством зависимостей.

3) Замена ReDim на Array.Resize()

Был написан небольшой класс Re, чтобы реализовать данную замену.

Public Class Re
    Public Shared Sub [Dim](Of T)(ByRef Source As T(), HighBound As Integer)
        //изменяем размер массива
        DimPreserve(Source, HighBound)
        //очищаем массив
        Array.Clear(Source, 0, HighBound + 1)
    End Sub

    Public Shared Sub DimPreserve(Of T)(ByRef Source As T(), HighBound As Integer)
        //изменяем размер массива
        Array.Resize(Source, HighBound + 1)
    End Sub
End Class


Далее все вызовы ReDim Preserve X(N) заменили на Re.DimPreserve(X,N), а ReDim X(N) заменили на Re.Dim(X,N).

4) Включение опции компиляции strict

По умолчанию .NET Visual Basic или компилятор Visual Basic не обеспечивает строгую типизацию. Чтобы изменить это поведение по умолчанию, необходимо в свойствах проекта на вкладке Compile установить Option strict в значение on. После этого исправить все возникшие ошибки.

Следующие пункты не требуют разъяснений, так как они просты и понятны. Мы просто берем в руки ReSharper и выполняем все, описанные ниже пункты, со скоростью звука (а то и еще быстрее).

5) Для value type переменных заменить Nothing на Default
6) Замена And на AndAlso и Or на OrElse
7) Удаление конструкций Imports, ссылающихся на классы
8) Замена вызова метода вида .Method на .Method()
9) Удаление конструкций Exit Try
10) Замена сравнения строковых переменных с Nothing или "" или со String.Empty на String.IsNullOrEmpty()
11) Замена ненужных директив ByRef на ByVal у параметров методов
12) Переименование методов, имеющих имя своего же класса
13) Исправление некорректных регистронезависимых вызовов в VB коде

Конвертация


И вот мы подошли к завершающему этапу – этапу конвертации. Инструмент выбран, проекты подготовлены и ждут своей участи.

Что ж – начнем!

Процесс конвертации не сложнее программы «Hello World», только требует немного большего времени. Приведу небольшой tutorial, как это делается в SharpDevelop и Instant CSharp.

Конвертация с помощью SharpDevelop
1. Скопировать проект VB.NET в отдельную папку
2. Открыть проект в SharpDevelop (File->Open->Project/Solution)
3. Сконвертировать проект (Project->Convert->From VB.NET to C#)
4. Открыть в Visual Studio основной солюшен и удалить проект VB.NET
5. Удалить папку с проектом VB.NET
6. Переименовать папку и файл сконвертированного в C# проекта (убрать слово Converted)
7. Скопировать папку с новым проектом в каталог с основным солюшеном
8. Добавить в солюшен скопированный проект
9. Добавить ссылки на новый проект (C#) во все остальный проекты, в которых были ссылки на старый (VB.NET). Для этого можно воспользоваться средством системы управления версиями для просмотра изменений в файлах *.csproj и *.vbproj
10. Попробовать скомпилировать проект. Исправить возникающие ошибки

Конвертация с помощью Instant CSharp
Instant CSharp не дружит с ANSI, так что необходимо сначала преобразовать кодировку файлов исходников в UTF8.
Удобная утилитка UTFCast Express
1. Открыть UTFCast Express
2. В поле Source directory указать путь к каталогу проекта
3. В поле Target directory указать путь к каталогу в который будут перемещены файлы проекта в кодировке UTF8
4. Выстовить опцию Copy unconverted и запустить преобразование

И после этих танцев с бубном можно производить конвертацию проекта.

1. Открыть Instant CSharp
2. В поле VB project or solution: указать путь к файлу проекта *.vbproj
3. В поле C# target folder: указать каталог, в который будет сохранён сконвертированный в C# проект
4. Сконвертировать проект (Project->Convert->From VB.NET to C#)
5. Открыть в Visual Studio основной солюшен и удалить проект VB.NET
6. Удалить папку с проектом VB.NET
7. Скопировать папку с новым проектом в каталог с основным солюшеном
8. Добавить в солюшен скопированный проект
9. Добавить ссылки на новый проект (C#) во все остальный проекты, в которых были ссылки на старый (VB.NET). Для этого можно воспользоваться средством системы управления версиями для просмотра изменений в файлах *.csproj и *.vbproj
10. Попробовать скомпилировать проект. Исправить возникающие ошибки

Вывод


В итоге мы перевели оба наших проекта полностью на c#.Сейчас идет, полным ходом, рефакторинг кода, кстати, не в рекламу будет сказано, но ReSharper в этом деле не заменим. В процессе эксплуатации, иногда, всплывают ошибки, связанные с конвертацией, но это неизбежно, увы.

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

Ссылки


Instant CSharp
SharpDevelop
Максим @Hell31
карма
5,0
рейтинг 0,0
Developer
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (22)

  • +18
    «В процессе эксплуатации, иногда, всплывают ошибки, связанные с конвертацией, но это неизбежно, увы. » — самое интересное упустили.
  • 0
    Я правильно понимаю, что основную часть проектов удалось перенести автоматически? Не возникало проблем с отсутствием полноценного наследования в Visual Basic?
    • 0
      Удаление конструкций Imports, ссылающихся на классы
      — это вы про что?
      • 0
        @ Epsil0neR, как, возможно, вам известно — можно делать не только imports namespace, но и imports class.
        Так вот при конвертации программа, в частности SharpDevelop тупо перегоняет в using namespace. Что в итоге?! Наши методы весят без класса, но зато у нас есть новый namespace. И вы думаете это будет работать?
        • 0
          Если вы изначально знаете, что инструмент кривой — то зачем вообще такой инструмент использовать?

          Но вообще хотел у pec-orange спросить про «Не возникало проблем с отсутствием полноценного наследования в Visual Basic?» — откуда такие сведения?
          • –1
            Насколько я знаю, в VB есть какие-то ограничения на наследование. В частности, не реализовано множественное наследование классов, из-за чего приходиться искать обходные пути через наследование интерфейсов. Если я не прав — поправьте, с VB я знаком не очень хорошо.
            • 0
              В C# тоже нет множественного наследования.
              • 0
                Ну тогда вопрос снимается (хотя на него уже и ответили).
    • 0
      @ pec-orange, да, вы правы. Нет, проблем с отсутствием полноценного наследования в Visual Basic не встретили.
  • –16
    А не судьба была найти профессионального VB-программиста? Он бы с лёгкостью перевёл бы вам весь код, без ошибок. Или для вас Visual Basic — это нечто для лохов?
    Сразу заметно минимум 3 грубейшие ошибки:
    1. Удаление конструкций Exit Try
    2. Замена ненужных директив ByRef на ByVal у параметров методов
    3. Удаление конструкций Imports, ссылающихся на классы

    Далее разбирать даже не хочется. Честное слово: надоели постоянные нападки на VB со стороны кодеров, которые зачастую C# еле-еле знают, а спроси их: в чём реальное отличие VB от C# — толком ничего сказать не могут.
    Пункты 6 и 10 — тоже удачи вам…
    • +4
      Прямого аналога в C# для Exit Try нет.
      Может вам и покажется, что действия неоднозначные и ошибочные, но если бы программы умели правильно все переводить и было бы у всего свой эквивалент, то все было бы тихо, мирно и без пыли.
      На счет профессионального VB-программиста — как я писал — времени было мало, да и найдите быстро человека, который перегонит, как вы сказали — с легкостью" миллион строк. может это вы и мы все не так сделали.?!
      И еще — могу точно вам ответить, что в процессе эксплуатации, именно из-за 10 пункта было 3 ошибки из-за неправильного сравнения.
      Напоследок — никто не чмырил vb.Мы решили — мы перешли.
      • –9
        Прямых аналогов много для чего нет в C#, для этого и нужен программист, а не только инструмент (Exit Try => goto+label). Проекты такого размера переводятся за несколько дней (умеючи). Поэтому ваше нежелание потратить немного времени на поиски хорошего программиста непонятно. При том, какие грубые ошибки вы сделали (и 10 пункт уже всплыл, остальных ждём в самые «приятные» моменты) — времени на исправление того — сами не знаете чего, в вызовах туда — не будете знать куда, вам прийдется потратить в десятки раз больше. Но если вы решили — вы сделали, то дело ваше. Поделитесь хоть названием продукта, чтобы знать, откуда проблем ждать.
        Насчёт не чмырил — это обычно по началу. Не вы первый, не вы последний, кто кривой подход на язык сваливать будут.
        • +4
          Разве использование одного языка вместо двух в одном проекте — не прекрасно?
        • +1
          Exit Try => goto+label

          Использовать goto в шарпе? Вы это серьёзно?:)
  • +2
    А с каких пор Visual Basic и VB.NET стали одним и тем-же?
    • +1
      Как я понял, у автора статьи все таки обычный VB, иначе бы другой софт понадобился.
      А если у них был VB.NET, то они явно упустили самый простой способ перевода в C#)))
      • 0
        Судя по приведенным ссылкам на сайты инструментов, они работают с VB.NET, не с VB.
        • 0
          Instant C# умеет VB6. По крайней мере та версия, которую я ковырял последней лет пять назад)
          • 0
            Может быть. У них на сайте в одном месте написано
            Converting VB (.NET)

            и
            Converts VB6-style On Error GoTo statements from VB to C#

            В другом:
            «VB» refers to the .NET implementation of Visual Basic, previously known as «VB.NET» (not VB6).

            Хотя, это относится к Free версии.
  • 0
    Скажите а какая версия #Develop использовалась?
    • 0
      vba, 4.4
  • 0
    Ну вот, только я налил кофе и зашел прочитать кровавые подробности перевода с VB6 на C#, а тут всего-то миграция с VB.NET… :)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.