понедельник, 25 февраля 2019 г.

[prog.thoughts] Legacy for the masses?

В свете последних вестей с полей стандартизации C++ (TL;DR: С++ станет еще больше и сложнее, сильно больше и сильно сложнее) подумалось о том, что мы становимся свидетелями того, как с понятием legacy сталкивается все больше и больше разработчиков. Что достаточно необычно для массового софтостроения, как мне кажется.

Попробую пояснить свою мысль.

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

А потом начались 1980-е и 1990-е годы, в которых все понеслось просто с фантастической скоростью. При этом случилось два очень важных сдвига в разработке софта. Сперва это были персоналки и разработка для десктопа. Затем Интернет, WWW и разработка под Web. Ну и потом еще и разработка под мобильные устройства, хотя она вряд ли так сильно перетряхнула подходы к софтостроению.

Так вот, уже в 1980-е и в 1990-е legacy (как в смысле старых прикладных систем, так и в смысле старых языков программирования) уже вполне себе было. И было, что называется, в полный рост. COBOL, PL/1 и Fortran яркие тому подтверждения. Но это legacy не оказывало практически никакого влияния на то, что стремительно развивалось в это время.

Если мы посмотрим на то, что тогда появлялось, то мы обнаружим множество знаковых вещей, оказавших серьезное влияние на последующие события. Например, конец 1970-х и 1980-е: появление сперва SmallTalk, затем Objective-C, C++, ObjectPascal, Perl. Развитие операционных систем для Mac и Next. Появление и развитие Windows, работы над OS/2. Затем в 1990-х: победа Windows, появление Linux-а, новый MacOS после поглощения Next-а. Возникновение Python, Delphi, Java, JavaScript, Ruby.

Для тех, кто пришел в программирование в 1980-е или в 1990-е это все было новым, либо только-только появившимся, либо имеющим совсем недолгую историю развития.

Даже для людей, которые пришли в разработку в 2000-е годы все вышеперечисленное могло восприниматься как новое. Ну, например, в 2005-ом году: языку Java всего 10 лет и в Java только-только завозят генерики, JavaScript-у всего 10 лет и этот язык только-только начинает восприниматься как полноценный язык для чего-то серьезного, а не для добавления капельки динамики на статические веб-странички. Про Ruby западный мир только-только узнал, до этого Ruby был широко распространен разве что в Японии. C# и .NET совсем еще молодые технологии... Операционка Windows, которая вроде как существует давным-давно, только-только повсеместно стала 32-х битовой, хотя кто-то, наверное, еще сидел и на Windows-98.

Да тот же C++: в 2005-ом году языку, формально, 20 лет. Но с момента появления стандарта C++98 прошло всего семь лет. И всего два-три года как поддержка этого стандарта стала доступна широким массам. Так что даже C++98 в 2005-ом году был достаточно молодым языком.

Но вот прошло еще почти пятнадцать лет и можно обнаружить, что legacy практически повсюду вокруг нас.

Языкам C++ и Objective-C более 30 лет. Языкам Java, JavaScript и Ruby практически 25. Языку Python через несколько лет будет тридцатник. Даже разделение на Python 2 и Python 3 произошло уже более десяти лет назад (в 2008 году). Функциональные языки, которые хотя бы чуть-чуть перестали быть маргинальщиной (Erlang, Haskell, OCaml), насчитывают по несколько десятков лет истории каждый (Erlang лишь на несколько лет помоложе C++).

Да даже относительно молодой язык Go в этом году будет отмечать свое 10-летие появления на публике (впервые миру Go был явлен, если не ошибаюсь, осенью 2009-го года).

Причем всем этим старым инструментарием пользуется огромное количество народу. Что принципиально отличает нынешнюю ситуацию от того, что было с COBOL, PL/1 и Fortran в 1980-х и 1990-х.


К чему я все это рассказываю?

Вероятно к тому, чтобы подчеркнуть два важных момента.

Момент первый. Инструменты и технологии с многолетней историей развития -- это уже норма. Нужно привыкать к тому, что массовая разработка будет вестись на языках, которые стали объемными и сложными, вобравшими в себя множество новых фич за время своего развития. Просто так от этих языков не откажешься (попробуйте заменить Java, C#, C++ или даже чистый C). И даже новые языки, которые будут появляться, будут вынуждены довольно быстро обрастать разнообразными фичами. Что можно было видеть сперва на примере быстрой эволюции C#. А сейчас можно видеть на примере Go. Так что порог входа в мейнстримовые технологии нулевым не будет.

Момент второй. Старые инструменты, будучи востребованными, неизбежно будут развиваться. Очень хорошо это видно на примере C++. Хотя даже Java сейчас перешла на более короткие итерации. Что, мне кажется, должно сказаться на отношении владельцев старых кодовых баз к своему коду. По хорошему, старый код нужно модернизировать и адаптировать к современным версиям языков и технологий. Вариант, когда имеющийся и работающий продукт взяли и заморозили на пять-семь лет даже не пытаясь пересобирать его новыми компиляторами, остается, конечно же. Но его стоимость, имхо, повышается. Скажем, портировать какую-то старую кодовую базу с C++03 на C++17 сейчас будет сложнее, чем если бы ее в свое время портировали с C++03 на C++11, а затем на C++14.


Вот как-то так. Чем дальше, тем сложнее говорить, что в ИТ все меняется с фантастической скоростью. Что-то, конечно же, меняется. И даже слишком быстро. Но при этом все четче и четче прорисовываются "столпы", которые будут с нами еще много и много лет.

7 комментариев:

Dmitry Popov комментирует...

Про Windows 98 странная оговорка, разве она не была 32-битной?

eao197 комментирует...

У меня в памяти почему-то осталось то, что 95-я, 98-я и WinMe были версиями Windows, внутри которых еще работал 16-битовый код, доставшийся от Win 3.*. Хотя сами 95/98/Me поддерживали Win32 API и 32-х битовые приложения были там родными. Только начиная с Win2000 версии Windows стали базироваться только на ядре NT.

Grigory Demchenko комментирует...

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

Анонимный комментирует...

> Пока никто не думает в этом направлении, а зря.

Не только думают, но уже есть результаты. Kotlin очень даже позволяет писать новый код на Kotlin и использовать старый на Java (IMHO, они довольно шустро могут вытеснить Java на задворки, уже сейчас началась волна обучения студентов Kotlin'у и использования его крупными компаниями в разработке, так что через несколько лет процесс может принять лавинообразный вид, так что на Java останется только те части кода, которые еще не начали модифицировать/переписывать). Однако такой подход работает только при условии, что семантика нового языка не сильно отличается от предыдущего, т.е. Kotlin не получится совместить с С++ (даже в варианте Native) или каким-нибудь Haskell.

eao197 комментирует...

> Пока никто не думает в этом направлении, а зря.

Об этом думают и пытаются это делать все время, что я имею отношение к программированию. Трансляторы из одного языка в другой то и дело обсуждаются. В районе 2008-го года я сам на RSDN-е постил новость про транслятор из Java в D, с помощью которого пытались преобразовать Java-библиотеку SWT в библиотеку DWT (и вроде как это даже удалось, т.к. DWT все еще существует: https://github.com/d-widget-toolkit/dwt). В прошлом или позапрошлом году мне на глаза попалась статья, в которой обсуждались проблемы трансляторов из COBOL-а в Java.

Как уже верно заметил Unknown, для хорошего результата требуется совпадение семантики языков. Но есть и вторая очевидная проблема: потеря информации, которая содержалась в старом коде в виде комментариев. А эту информацию сложно сохранить, если не получается транслировать код из одного языка в другой 1-в-1. Например, если попытаться C-шный код перетранслировать в Pascal (поедут объявление и инициализация переменных, будут переписаны циклы, будут изменены операции над указателями и т.д.).

Думаю, что есть и еще одна проблема, которую можно проиллюстрировать на приведенном выше примере с Java и Kotlin: со временем новый код на Kotlin так же будет превращаться в legacy. И у разработчиков проекта будет старая кодовая база на двух языках. Если нужно как-то доработать Java-часть (пофиксить ошибку или чуть-чуть расширить функциональность), то выгоднее это делать на Java, чем переписывать старый кусок на Kotlin полностью. Поэтому не смотря на написание нового кода на Kotlin старый код на Java продолжит жить и эволюционировать. А потом окажется, что вместо Kotlin-а можно применить еще что-то. И опа! У нас уже и Java, и Kotlin, и еще что-то модное и молодежное.

Правда не знаю какой процент настолько больших и долгоживущих проектов, в которых успеет накопиться изрядно legacy-кода. Такое ощущение, что чуть ли не 80% разработки сейчас -- это что-то краткосрочное для Web-а на PHP, RoR или Node.js. Ну или на Go. Без претензий на то, что написанный код будет работать и развиваться в перспективе 5-10 лет хотя бы.

Grigory Demchenko комментирует...

> Не только думают, но уже есть результаты. Kotlin очень даже позволяет писать новый код на Kotlin и использовать старый на Java

Удивил. Еще можно привести в пример С++, который подтянул С и неплохо на этом поимел.

Речь шла про другое - не просто использовать библиотеки родительского языка, а всосать библиотеки неродственного.

Dmitry Popov комментирует...

>выгоднее это делать на Java, чем переписывать старый кусок на Kotlin

Кажися, джетбрейновская IDEA конвертирует джаву в котлин автоматически одной кнопкой.