Статьи

Сохранение устаревшего кода: несовместимость языков и эволюция технологий

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

Есть несколько слоев к этому.

  • Несовместимость платформы . Это означает, что вспомогательные библиотеки для языка несовместимы между версиями. Это относительно редко; Языковые библиотеки почти всегда обратно совместимы. Когда это не так, проблему часто можно замаскировать с помощью «шим» или небольшого программного обеспечения, чтобы «обернуть» новые библиотеки, чтобы они работали как старые библиотеки. Добавление прокладки — вообще — ужасная идея. Зачем сохранять странные функции и причуды старой версии? Зачем добавлять сложность (и ошибки и причуды) прокладки?
  • Поддержка или Framework Несовместимость . Распространенной несовместимостью «поддержки» является база данных; Есть много других примеров. SQL, например, имеет стандартизированное ядро, но не всегда реализовано, и расширения поставщиков распространены. Любой большой фреймворк будет иметь проблемы совместимости между версиями и платформами.
  • Несовместимость ОС . Большинство POSIX-совместимых ОС (Linux, Mac OS X и т. Д.) Достаточно совместимы. Windows бросает гаечный ключ в работу. В некоторых случаях язык предлагает библиотеку, чтобы сделать программы на этом языке независимыми от ОС. Уникальная для ОС особенность приложения — тревожная вещь для конвертации. Является ли уникальная особенность ОС  существенной  особенностью приложения? В некоторых случаях уникальная функция ОС связана со специализированными драйверами для поддержки мультимедиа (звук, изображения, видео и т. Д.). Эта проблема совместимости мультимедиа приводит к сложной поддержке, независимой от ОС, или к использованию сторонних библиотек, независимых от ОС. ,
  • Несовместимость языка . Обычно это абсолютный блок для автоматического преобразования. Языки  не  совместимы на концептуальном или семантическом уровне. Автоматический перевод с одного языка программирования на другой затруднен, а в некоторых случаях по существу невозможен без каких-либо чрезвычайно сложных усилий в области искусственного интеллекта. Если бы языки были совместимы на концептуальном уровне, у нас был бы универсальный перевод среди языков программирования.

Когда мы смотрим на наши тематические исследования, мы видим следующее:

  • В чем дело?  Конвертация ОС; язык оставался более или менее прежним.
  • Есть ли причуды?  ОС и преобразование языка: Фортран в PL / 1.
  • Сколько стоит?  Преобразование языка: JOVIAL в Фортран.
  • Мощение Cowpaths . Постоянное преобразование инфраструктуры: плоские файлы в СУБД
  • Хранилище данных и устаревшие операции . Это часто включает в себя ОС, язык и постоянство преобразования.
  • Ошибки — это особенности . Это была умственная проблема, а не техническая.
  • Зачем сохранять мерзость?  ОС, язык и преобразование постоянства: Базовый в Java
  • Как мы справляемся с этим?  ОС, язык и постоянное преобразование: COBOL в Java.
  • Зачем сохранять DSL?  Язык и постоянство преобразования: C на Java.

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

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

Автоматический перевод языка

Идея автоматического преобразования языка — «привлекательная неприятность». (
http://en.wikipedia.org/wiki/Attractive_nuisance_doctrine ). Это не только вообще невозможно, но и снижает или исключает ценность полученных знаний.

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

Мы хотим «автоматически» создать новую программу P_2 на языке L_2. Поскольку в этих двух языках используются разные концепции, разные структуры данных, разные парадигмы программирования, преобразование не происходит на «высоком уровне». Это не вопрос смены оператора печати на функцию print (). Это вопрос «понимания» программы, P_1, а затем создания новой программы, P_2. который выполняет «те же» функции с точки зрения пользователя.

Выбор № 1 — создать техническую «спецификацию» очень высокого уровня, которая не зависит от языка. Затем переводчик компилирует эту высокоуровневую спецификацию на новый язык. По сути, мы «декомпилировали» из P_1 в P_S, а затем скомпилировали P_S в P_2, используя язык промежуточной спецификации, L_S. Язык спецификации высокого уровня L_S должен содержать оба языка, L_1 и L_2, в качестве функций.

Есть примеры элементов этого. C ++ компилируется в C. Eiffel часто компилируется в C. Мы можем думать о C ++ как о языке спецификации, который переводится в C.

Кроме того, мы знаем, что «структура управления» (IF-THEN-ELSE, WHILE, GOTO) может быть сопоставлена ​​друг с другом. Существует элегантное теоретико-графическое доказательство того, что программа, представляющая собой болото GOTO, может быть преобразована в циклы IF-THEN-ELSE и WHILE. Понятно, что обратное возможно.

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

Давайте посмотрим на Эйфелеву. Мы можем пойти от Эйфелевой до C. Мы можем пойти от C до Эйфелевой? На самом деле, нет. Eiffel не хватает GOTO, который поддерживает C. Кроме того, C имеет неограниченное приведение указателей (или приведение), которого нет у Eiffel. Чтобы «декомпилировать» C в Eiffel, нам нужно «понять» программирование на C и по существу переписать его в нейтральную версию на Eiffel, которая затем может быть переведена на другой язык реализации.

Ситуация усугубляется тем, что у С есть мутная семантика для некоторых конструкций. a [i ++] = i; например, плохо определен и может делать самые разные вещи.

Семантическая потеря

Выбор № 1 — создать техническую «спецификацию» очень высокого уровня — не может быть выполнен автоматически.

Выбор № 2 — создать очень низкоуровневую реализацию программы P_1, скомпилировав ее в машинные инструкции (или инструкции JVM, или байтовые коды Python, или слова Forth). Этот язык низкого уровня — L_M. Учитывая программу на L_M, мы хотим реструктурировать эти машинные инструкции в новую программу, P_2, на новом языке, L_2.

Важно отметить, что перевод из P_1 в машинный код L_M может повлечь некоторую потерю семантической информации. Инструкция «И» на машинном языке может быть частью логической операции «и» P_1 или частью операции битовой маски P_1. Контекст и смысловой фон теряется.

Без семантической информации P_2 может не отражать исходные знания, захваченные в P_1.

Обратите внимание, что эта трудность аналогична выбору № 1 — созданию спецификации более высокого уровня.

Мы не можем легко «декомпилировать» код в резюме, понимание или описание. Действительно, для некоторых языков мы уверены, что не хотим пытаться автоматически декомпилировать их. Некоторый унаследованный C-код настолько неясен и полон потенциальной путаницы, что, вероятно, его следует переписать, а не декомпилировать.

Вот конкретный пример от HamCalc.

700 A=2:B=1:T=P:X=0
730 FOR N=A TO T STEP B
750 IF T/N=INT(T/N)THEN X=X+1:PN(X)=N:T=T/N:GOTO 730
760 A=3:B=2
770 NEXT N

Дело в том, чтобы найти простые множители P, построив массив PN с X-факторами.

Обратите внимание, что строка 750 выполняет GOTO обратно в оператор FOR. Что именно это означает? И как можно автоматически декомпилировать в спецификацию, подходящую для компиляции на другой язык?

Это, оказывается, также является примером места, где HamCalc не является хранилищем глубоко полезного программирования. Смотрите 
http://en.wikipedia.org/wiki/Integer_factorization  для более сложных алгоритмов.

Захват знаний

Похоже, что захват знаний требует мышления.

Не существует автоматического перевода между языками программирования, структурами данных или парадигмами программирования.

Единственный приемлемый метод перевода — это ручное преобразование:

  1. Понять исходную программу.
  2. Создание юнит-тестов.
  3. Разработайте новую программу, которая проходит модульные тесты.