Данная статья — с одной стороны — изначально задуманное продолжение моей первой статьи "«Миграция приложений — мифы и реальность», а с другой стороны — ответ на часть комментариев, которые задавали в статье Хабравчане vladsharikov, lair и berez.

Конвертация кода с Delphi на C#


Для начала, приведу пример конвертации кода на Delphi в код на C#:
Код на Delphi
unit Unit3;

interface

type
  TMyClass = class
    _str: string;
    constructor Create;
    procedure setStr(s2: string);
  public
    class var
      FClassField: integer;
  end;
  TMyClassD = class of TMyClass;

procedure DoSomeThing;

implementation

procedure DoSomeThing;
begin

end;
{ TMyClass }

constructor TMyClass.Create;
var
  c: char;
  i: byte;
  cod: integer;
  s: string;
  cls: TMyClassD;
begin
  cls := TMyClass;
  inherited;
  DoSomeThing;
  Val('5', i, cod);
  c := '1';
  s := c;
end;

var
  cls: TMyClass;
  s: string;

procedure TMyClass.setStr(s2: string);
begin
  s2[4] := 'a';
end;

initialization
  cls := TMyClass.Create;
  s := '123456';
  cls._str := s;
  s[3] := '0';
  cls.setStr(s);
end.


После трансляции, код превращается в такой:
Код C#
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.IO;
using System.Text;
using FastCode.Delphi.Core._System;

namespace Project3 {
    public static partial class Unit3_Module {

        public static void Unit3_Initialization_() {
            cls = TMyClass.Create();
            s = "123456";
            cls._str = s;
            //s[3] = '0';
            s = s.Substring(0, 2) + '0' + s.Substring(3);
            cls.setStr(s);
        }


        public static void DoSomeThing() {
        }


        internal static TMyClass cls;

        internal static string s;
    }
    public partial class TMyClass : TObject {

        public override void __Create__() {
            Char c;
            byte i;
            int cod;
            string s;
            Class_of_TMyClass cls;
            cls = Class_of_TMyClass.Instance;
            base.__Create__();
            Unit3_Module.DoSomeThing();
            System_Module.Val('5'.ToString(), out i, out cod);
            c = '1';
            s = c.ToString();
        }


        public void setStr(string s2) {
            //s2[4] = 'a';
            s2 = s2.Substring(0, 3) + 'a' + s2.Substring(4);
        }


        public static TMyClass Create() {
            TMyClass _instance = new TMyClass();
            _instance.__Create__();
            return _instance;
        }


        public string _str;

        public static int FClassField;
    }
    public partial class Class_of_TMyClass {

        protected Class_of_TMyClass() {
        }


        public TMyClass Create() {
            return TMyClass.Create();
        }


        public static Class_of_TMyClass Instance = new Class_of_TMyClass();

        public int FClassField { get { return TMyClass.FClassField; } set { TMyClass.FClassField = value; } }
    }
}



И да, код на C# работает после подключения миграционной библиотеки и компиляции.
Есть более сложные и интересные места — например, реализация свойств с индексами (если кто знает Delphi — поймут), к которым есть доступ по имени, то есть в форме Obj.Items[index], но прямо сейчас под рукой этого кода нет.

Внешний вид в FoxPro


Накидал, по-быстрому, небольшое приложение на FoxPro, получилось вот такое:

Внешний вид в C# + WPF ниже.
Извините — полные варианты тем, с заменяемыми кнопками на заголовке окна и сменными же стилями заголовков, искать не стал


Здесь три дополнительных темы

Glass

Steel Blue gradient

Metro Light

Если есть ещё вопросы по примерам конвертации — прошу в комментарии.
P.S. Перевод с Delphi на C# — один из проектов-тестов, которые использовались в процессе отладки конвертера.
P.P.S. Форма на FoxPro сделана «наспех», специально для демонстрации.

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


  1. lair
    10.06.2015 22:12
    +2

    Ох. Вы искренне считаете этот код на C# поддерживаемым?


    1. HackerDelphi Автор
      10.06.2015 22:22

      Спасибо за комментарий!

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



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


      1. lair
        10.06.2015 22:47
        +1

        Да все вместе. Это код, с которым я бы никогда не хотел иметь дела.

        Что, собственно, возвращает нас к началу разговора и вопросу: а зачем вообще «переписывать» код с одного языка на другой? Вот я заказчик, у меня есть работающее приложение на, скажем Java + DB2 — зачем мне его переписывать?


        1. HackerDelphi Автор
          10.06.2015 23:29
          +1

          основных причин для миграции, как правило, 3:

          1. Найти квалифицированных разработчиков на многие старые языки (такие как FoxPro, а сейчас — и Delphi) с каждым годом всё сложнее, а старые разработчики — кто уходит, кто даже умирает.
          2. В свете п.1, иногда ведущий разработчик начинает чувствовать себя незаменимым (и являться им, пока система на старой платформе), что ведёт к самым различным вещам, вплоть до грубого посылания (в матерной форме) генерального директора фирмы, когда незаменимый — с похмелья. Заменить его, зачастую, некем.
          3. Платформа устаревает. Тот же Visual FoxPro с 2009, если не ошибаюсь, года не обновляется и снят с поддержки 13 января 2015 года пруф. Есть и более старые платформы — там проблем еще больше.

          Конкретно в вашем случае — не вижу глобальных причин для миграции. Java разработчики вроде как на рынке есть, DB2, конечно не так популярен, как Oracle или MS SQL, но тоже вполне себе можно изучить или найти готового разработчика.
          Единственной для вас причиной может оказаться желание, к примеру, перенести весь код на платформу .Net, чтобы дальше перенести основную часть, опять-таки к примеру, на ASP.Net и подключить туда клиент Windows Phone / Windows Store / Windows Desktop. Но подозреваю, что конкретно в вашем случае будет решение использовать либо Linux либо Android в качестве клиентского места. В принципе, можно и OSX и Windows — тут простор велик.
          Надеюсь — ответил на Ваш вопрос?
          P.S. я Попробую чуть позже найти код без такой экзотики, такой как конструкции «class of» и прочее.


          1. lair
            10.06.2015 23:31

            Нет, не ответили. Какая разница, есть ли квалифицированные разработчики/устарела ли платформа, если система работает?


            1. HackerDelphi Автор
              10.06.2015 23:37
              +1

              Бизнес системы почти всегда требуют доработки. Системы, которые начаты в 1985 году (к примеру) требуют доработки всегда.
              Менеджмент постоянно хочет новые формочки.
              Доработки нужны постоянно.


              1. lair
                10.06.2015 23:40
                +1

                То есть на самом деле, заказчик хочет развивать систему, но не может этого делать, потому что стоимость внесения изменений в существующую реализацию слишком велика, так?


                1. HackerDelphi Автор
                  10.06.2015 23:44

                  Либо слишком велика, либо вообще невозможна.


                  1. lair
                    10.06.2015 23:49
                    +2

                    (Невозможного не бывает, бывает слишком дорогое)

                    Это все означает, что то, что получается после переписывания, должно быть дешевле в поддержке и развитии, чем то, из чего оно выросло, а не просто «работать так же, как». Что, в свою очередь, означает требования по качеству и структуре кода.

                    Я это все к тому, что (по моему опыту), следующий шаг за автоматической конвертаций — ручной рефакторинг со всеми необходимыми этапами, и стоимость этого рефакторинга тоже надо считать в стоимости «переписывания». Иначе результаты несравнимы.


                    1. HackerDelphi Автор
                      11.06.2015 00:00

                      Не совсем верно.
                      В данном случае не применялось никаких инструментов автоматического рефакторинга, который в нашем конвертере очень даже присутствует (в окончательной версии).
                      Текущая версия — рабочая, но как раз инструменты рефакторинга «по анализу» не встроены — только что перешли на совсем новую модель внутреннего представления данных.
                      Эти примеры — примеры того, что можно получить «автоматом и дёшево» — многие согласны на такую услугу — лишь бы меньше платить.
                      А насчёт ручного рефакторинга.
                      По опыту пары прошлых проектов, конвертированный код использовали «как есть», а вот в процессе развития/отладки (оригинальный код содержал ошибки — как же без них) переписывались достаточно большие участки кода.
                      Более того, обычно мы предлагаем, кроме чисто конвертации и запуска приложения, услугу по чистке кода и рефакторингу (вовсе не вручную и намного дешевле, чем вручную).
                      Кроме того, можем, зачастую, предложить и услуги по оптимизации.


                      1. lair
                        11.06.2015 00:10

                        Я, очевидно, сужу по коду, который вы показываете, никакого другого для сравнения у меня нет. И этот конкретный код, на мой вкус, к поддержке и развитию непригоден. Соответственно, озвученную выше задачу — получить код более дешевый в поддержке, чем оригинальный — он не решает. Если для того, чтобы код был дешевле в поддержке, нужно применить дополнительные усилия — не важно, ручные или автоматические — их стоимость тоже нужно учитывать в сравнении «автомат vs ручное переписывание».


                        1. HackerDelphi Автор
                          11.06.2015 00:13

                          Заметим, я пока что вообще не приводил цен на «автомат».
                          Более того, даже с учётом доведения кода до «хорошего» с точки зрения целевой платформы (например — уборка «красивых» статик методов «Create» и замена их на нормальные конструкторы, выкидывание Class_of конструкций и подобного) цена наших услуг в разы ниже, чем «ручной перевод».
                          P.S. Кстати, гарантии, что ручной перевод будет лучше, чем показанный код нет — чаще всего найти действительно толковых программистов и заинтересовать их на 2-3 года подобным проектом крайне тяжело.


                          1. lair
                            11.06.2015 00:22

                            Заметим, я пока что вообще не приводил цен на «автомат».

                            Вы утверждали, что это выгоднее по ресурсам, чем ручное переписывание. Нет, я ошибся?

                            Более того, даже с учётом доведения кода до «хорошего» с точки зрения целевой платформы

                            Это зависит от критериев «хорошести», согласитесь?

                            чаще всего найти действительно толковых программистов и заинтересовать их на 2-3 года подобным проектом крайне тяжело

                            Зависит от целей проекта и предлагаемых условий. Нам подобное вполне удалось.


                            1. HackerDelphi Автор
                              11.06.2015 13:01

                              Это зависит от критериев «хорошести», согласитесь?

                              Там же написано — «С точки зрения целевой платформы» — для большинства платформ есть более-менее вменяемые описания «хорошего» кода.
                              Зависит от целей проекта и предлагаемых условий. Нам подобное вполне удалось.

                              По-хорошему завидую — искали, очень тщательно, людей, которые способны руками переводить код с FoxPro — нереально, даже если брать не слишком высокий уровень. Перевести код с того же Delphi на C# уже проще, но при условии использования Win Forms, а вот перенос Delphi => WPF уже всё намного грустнее — слишком большая разница в «нутре» библиотек — многие неспособны одновременно и то и то хорошо понимать.


                              1. lair
                                11.06.2015 13:03

                                Там же написано — «С точки зрения целевой платформы» — для большинства платформ есть более-менее вменяемые описания «хорошего» кода.

                                Нет. Есть гайдлайны, но соответствие им не гарантирует хорошего кода.

                                По-хорошему завидую — искали, очень тщательно, людей, которые способны руками переводить код с FoxPro — нереально, даже если брать не слишком высокий уровень. Перевести код с того же Delphi на C# уже проще, но при условии использования Win Forms, а вот перенос Delphi => WPF уже всё намного грустнее — слишком большая разница в «нутре» библиотек — многие неспособны одновременно и то и то хорошо понимать.

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


            1. BlessMaster
              15.06.2015 22:04

              Попробую ответить за вашего визави. Реальный случай из жизни, причём, совсем не «за новые формочки», а хоть бы как-то заставить работать.

              Купили на СТО железку для общения с тем, что в автомобилях 90-х называется «компьютером». К нему прилагается софт, по внешнему виду писанный ещё во времена, когда в моде были контролы Win3.x-style. Всё это добро ещё работает на WinXP, но уже в момент, когда его купили WinXP не продавался, а все ноуты шли с Вистой.

              Конечно, было два пути решения — искать б/у ноут или пиратить винду, но это ведь тоже решения тянущие в дремучее прошлое — ноуты ломаются, нелицензионка на предприятии — к добру не ведёт.

              При этом производитель железа на тот момент явно испытывал сильную зубную боль от самой идеи переписывания ПО (ассортимент железок большой, рынок — не так уж и велик, кризис, опять же).

              Так что, ниша, из-за устаревания систем и прекращения поддержки, наверно, всё-таки есть.


              1. lair
                15.06.2015 22:09

                А кто в вашем примере будет пользоваться услугами по автоматической миграции? Те, кто купил софт? А откуда у них исходники, и как они потом будут проверять правильность конверсии? Или производитель? Так у него, вроде бы, зубная боль и так.

                (с точки зрения лицензирования такие вещи, афаик, делаются через XP Mode в той же семерке, но это оффтопик)