Как портят софт ради обратной совместимости

в 9:00, , рубрики: Assessment and Deployment Kit, Compatibility Administrator, linux, ruvds_статьи, SimCity, software lifecycle, Windows 95, Windows ADK, Блог компании RUVDS.com, легаси, обратная совместимость, преждевременная оптимизация, Программирование, Проектирование и рефакторинг, рефакторинг, Софт, технический долг

Как портят софт ради обратной совместимости - 1


«Ожирение софта» — известная беда современной разработки. Повышение производительности железа зачастую воспринимается менеджерами как возможность игнорировать рефакторинг, всё равно никто не заметит тормозов. Проще докупить железа, чем тратить время на оптимизацию.

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

▍ Баги ради совместимости

Известен случай, как в Windows 95 специально внесли баг ради совместимости с популярной игрой SimCity. Об этом рассказывал Джоэл Спольски, сооснователь Stack Overflow. Он хвалит Microsoft за то, как много усилий она вложила в поддержку обратной совместимости, и приводит слова Джона Росса, автора оригинальной версии SimCity для Windows 3.x:

Отличный новый 32-битный API прекрасно работал со старыми 16-битными программами. Microsoft была одержима этим, потратив кучу денег на тестирование под Windows 95 всех старых программ, какие только могла найти. Джон Росс случайно оставил в SimCity баг с чтением только что освобождённой памяти. Мда… Игра прекрасно работала на Windows 3.x, потому что там освобождённую память никто не занимал, однако в бета-версии Windows 95 она, естественно, падала. И вот тут самое интересное. Microsoft отследила баг и добавила в Windows 95 специальный код, который ищет SimCity. Если находит, то запускает аллокатор памяти в специальном режиме, который не сразу освобождает память. Именно такая одержимость обратной совместимостью заставляла людей охотно переходить на Windows 95.

Получается, в Windows 95 внедрили искусственную «утечку памяти», лишь бы старенькая SimCity не падала.

Это, конечно, уникальный случай. Но он демонстрирует некую тенденцию, когда перед разработчиками ставят главный приоритет — любой ценой обеспечить обратную совместимость, чтобы у старых клиентов ничего не падало после обновления, а у новых клиентов работали абсолютно все прежние программы. Из-за этого приходится идти на жертвы. И первым делом жертвуют качеством кода.

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

Вообще, Windows 95 — легендарная система. Вместе с MacOS она сыграла историческую роль в переходе человечества с текстовых (Unix, DOS) на графические интерфейсы с использованием мыши. В 1995 году важность Windows 95 была настолько исключительной, что её рекламировали из каждого утюга.

Как портят софт ради обратной совместимости - 2
Счастливый покупатель урвал сразу две копии Windows 95 в день начала продаж 24 августа 1995 года, Сидней (Австралия), источник

Руководство MS понимало, что приоритетная задача для принятия публикой новой ОС — это совместимость приложений. Один из разработчиков Microsoft в те годы Раймонд Чен вспоминает забавный факт: чтобы обеспечить максимально широкий охват для тестирования приложений на совместимость, менеджер по разработке Windows 95 сел в свой пикап, поехал в местный магазин Egghead Software (специальные магазины, где продавался коробочный софт) и купил по одной копии всех программ в магазине:

Затем он вернулся в Microsoft, выгрузил все коробки на столы в кафетерии и предложил каждому члену команды разработчиков Windows95 прийти и взять по две программы. Основные правила заключались в том, что вы должны установить программу, использовать её как обычный юзер — и составить отчёт на каждый найденный баг, даже самый мелкий… В обмен сотрудник получал право оставить эти программы себе бесплатно после выхода Windows 95 [нужно сказать, это очень ценное предложение, учитывая дороговизну коробочного софта в то время — прим. пер.]. Если вы справились с двумя программами, можно взять со стола ещё.

Кафетерий заполнили разработчики из команды Windows 95, они рассматривали коробки с программами, словно искатели сокровищ на блошином рынке, которые потом хвастаются добычей друг перед другом.

Я взял только одну программу — автоматический переводчик с английского на немецкий. Он работал нормально, только плохо переводил (понятно, что тут Windows ни при чём).

В общем, Microsoft была одержима обратной совместимостью. И это сохранилось в последующие годы. Каждая следующая версия Windows была обязана запускать все программы, которые запускались на предыдущей версии, дополнительно к нововведённым стандартам.

Инструмент Compatibility Administrator из комплекта Assessment and Deployment Kit (ADK) для каждой установленной программы под Windows показывает «исправления» (то есть трюки), сделанные в ОС для совместимости, то есть ради нормального запуска этой программы. Например, для игры Final Fantasy VII в Windows NT был реализован хак под названием Win95VersionLie, который пытался убедить игру в том, что рабочее окружение соответствует Win 95 и содержит необходимые файлы (на самом деле они отсутствуют):

Как портят софт ради обратной совместимости - 3

В базе «исправлений» Windows ADK много игр. Разработчики понимали, что это главные приложения, которые должны работать оптимально и без глюков, чтобы привлечь максимальное количество пользователей. В результате вносились изменения в саму ОС — отключались некоторые горячие клавиши в определённых ситуациях, создавались фиктивные файлы, эмуляции CD-ROM и виртуальные машины, только чтобы обмануть запущенную игру.

▍ Старый балласт

Всё это хорошо для любителей игр. Но погоня за обратной совместимостью распространяется не только на игры, но и на другие стандарты и протоколы. В итоге — сейчас за Windows тянется целый шлейф архаичных технологий, от которых компания не хочет (или не может) отказаться по требованию клиентов. Среди них:

  • запуск древних 16-битных бинарников от Windows 1.0 (на 32-битной ОС) и почти всех приложений Win32 на Win64;
  • поддержка старых форматов файлов, включая пакетные файлы;
  • древний интерпретатор cmd.exe (от него не могут избавиться, потому что тысячи клиентов за десятилетия внедрили в продакшн миллионы пакетных файлов);
  • старый формат реестра.

Поскольку новые функции добавляют, а старые не убирают, это естественным образом раздувает код. К 2017 году репозиторий Windows 10 вырос до 3,5 миллиона файлов и 300 ГБ кода. В команде Windows около 4000 разработчиков, а инженерная система ежедневно выдаёт 1760 лабораторных билдов» в 440 ветках в дополнение к тысячам билдов для проверки пул-реквестов.

В ядре Linux тоже есть проблемы с раздуванием кода, но гораздо в меньшей степени. Там Линус Торвальдс всё-таки понимает важность оптимизации и проводит строгую чистку кодовой базы. Например, 21 октября 2022 года он предложил удалить из ядра поддержку процессорной архитектуры 80486 (80386 удалили в 2012-м). Такая оптимизация сократит потребление памяти и увеличит производительность ядра, поскольку в ядро непрерывно приходится вносить разные костыли (workarounds) для поддержки старых CPU.

По причине постоянных чисток ядро Linux всегда было гораздо эффективнее, безопаснее и производительнее, чем Windows. Сравните две картинки ещё с 2006 года. На первой — стек системных вызовов в процессе работы веб-сервера Apache под Linux.

Как портят софт ради обратной совместимости - 4

На второй — стек системных вызовов для веб-сервера Microsoft IIS под Windows.

Как портят софт ради обратной совместимости - 5

Хотя в стремлении к рефакторингу главное — не переусердствовать. Есть примеры преждевременной, излишней оптимизации. Например, несколько дней назад из кодовой базы движка Blink (браузер Chromium) полностью удалили код для рендеринга JPEG XL (раньше это была экспериментальная функция за флажком, отключённая по умолчанию). Такое решение разработчиков и вызвало бурные споры, потому что JPEG XL превосходит WebP и AVIF по уровню сжатия без потерь, а в тестах на сжатие с потерями результаты противоречивые.

Близкий к нам пример — намерение разработчиков Хабра полностью удалить старый редактор в пользу нового, чтобы сократить расходы на поддержку двух несовместимых редакторов.

Как портят софт ради обратной совместимости - 6

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

В общем, удаление старого кода (и функций) из приложений является скорее исключением в современной разработке, чем правилом. Но тут главное — не переборщить.

▍ Любой код — временный

Теоретически — решением проблемы легаси может быть введение более чёткой концепции жизненного цикла программного обеспечения (software lifecycle). В частности, изначально при написании любого кода устанавливать чёткий срок его поддержки, после которого он признаётся «устаревшим» и изымается из использования. Грубо говоря, у каждой новой строчки кода должен быть метатег со сроком её жизни.

Многие думают, что существующая концепция жизненного цикла разработки (SDLC) будто не предусматривает вывод из строя ПО по окончании поддержки. Обычно распространяют такую схему жизненного цикла:

Как портят софт ради обратной совместимости - 7

Однако в полной версии SDLC по истечении жизненного срока программный код подлежит замене. В оригинальном документе NIST после фазы «Поддержка» следует фаза «Вывод из строя» (Sunset) и «Замена» (Disposal), см. диаграмму на третьей странице PDF:

Как портят софт ради обратной совместимости - 8

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

Отлично помогают в этой реформе новые, более продвинутые языки программирования, такие как Rust. Самим фактом своего появления он как бы намекает на возможность переписать всё с нуля, в лучшем виде.

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

Telegram-канал с полезностями и уютный чат

Автор: Анатолий Ализар

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js