Технологическая обманка
А случилось то же самое, что происходит во многих областях человеческой деятельности, где воцаряются монополии самых разных мастей: застой и загнивание. Какие же монополии захватили рынок вычислительной техники и программного обеспечения? Это монополии на мышление.
Что касается вычислительной техники, здесь всё в порядке. Её производительность постоянно повышалась всё это время. Если взять за единицу производительность среднего персонального компьютера 30 лет назад, то сегодня она увеличилась в 100 раз по тактовой частоте (с 40 мегагерц до 4 гигагерц), в четыре раза по ширине машинного слова (с 16 до 64 бит), и в 30-40 раз по продолжительности исполнения машинной инструкции (с 30-40 до меньше чем одного такта). Прирост производительности складывается в приблизительно 10-15 тысяч раз «в лоб», если не принимать во внимание появление новых, более совершенных машинных инструкций, увеличение объёма оперативной памяти и его кэшей, увеличение пропускной способности шин передачи данных в несколько тысяч раз, а также другие факторы. С учётом их всех производительность разных типов ПО должна была вырасти в десятки тысяч раз.
Когда я поступил в институт, имевшиеся там отечественные копии IBM PC XT работали так медленно, что если зажать какую-то клавишу, подержать секунду и отпустить, то потом ещё несколько секунд на экране печаталась строка из соответствующей буквы. Небольшой текстовый файл контрольной или курсовой работы сохранялся несколько секунд. Прошли всего несколько лет, и производительность ПК повысилась в десятки раз. К середине 90х гг. задержки при работе с ПО ушли в прошлое: операционные системы, текстовые редакторы, электронные таблицы и многое другое работало молниеносно. Некоторые думали, что так будет всегда, но прошли ещё 30 лет, многое переехало в «облака», и вот мы становимся свидетелями повсеместных «тормозов». Мы сидим и ждём, пока загрузится страница и прокрутятся эти модные колечки и проскачут точечки индикаторов прогресса загрузки, причём на ресурсах, у которых не так уж много посетителей. Где и что мы упустили? Как так вышло?
А вышло вот что: непобедимые общечеловеческие лень, жадность и страх заставили профессионалов в области информационных технологий, как любую бюрократию, не только выполнять свои обязанности добросовестно, но и искать способы сделать себя незаменимыми, увеличить свой доход и расширить свои полномочия. Это возможно только при условии наращивания сложности программного кода и увеличения его объёма, чтобы он требовал больше времени на изучение, модификацию и развитие. Какие Ваши доказательства? Да они у всех перед глазами! В последние 10 — 15 лет объём пакета установки практически любого распространённого продукта, от операционных систем, баз данных, офисных пакетов, и т.д. рос в степенной прогрессии или экспоненциально, что однако не сопровождалось эквивалентным увеличением набора функций. Этот рост некоторое время следовал за ростом объёма сменных носителей, но с массовым отказом от них в пользу прямого скачивания файлов из Интернет оторвался и рванул ввысь: десятки мегабайт, сотни мегабайт, гигабайты, десятки гигабайт...
Возможно, некоторые считают, что в этих немереных гигабайтах присутствуют какие-то важные и полезные функции. Смею вас уверить: их там нет, и вот почему. Любой разработчик знает, что у исполняемого файла, откомпилированного с какого-то языка программирования высокого уровня, есть минимальный объём, требующийся для запуска под выбранной операционной системой. Дальше каждая инструкция, добавленная в исходный код, привносит какой-то небольшой дополнительный объём исполняемого файла. Он невелик. Как правило проект выпускается потребителям, имея в своём составе необходимый набор функций. В следующих версиях к ним добавляются новые, и проект растёт на незначительную величину. Когда же объём файлов проекта удваивается, пользователю следует ожидать эквивалентное удвоение возможностей и функций, но этого не происходит уже давно. Так чем же индустрия набивает пакеты установки, если не ими?
Давайте разбираться. Во-первых, многое ПО помимо исполняемых файлов содержит данные. В зависимости от области применения это могут быть изображения и звуковые файлы, объём которых рос всё это время, следуя за аппаратными возможностями. Текстуры игр, иконки, картинки, музыка и звуковые эффекты выросли в объёме. Тогда как в середине 90х гг. прошлого века размер текстур игр измерялся десятками байт, сейчас они выросли до десятков и сотен мегабайт, то есть в миллионы раз. Рост оперативной памяти видео-адаптеров позволил этому произойти. Поставим галочку. Количество каналов звуковых эффектов и музыки выросло с одного для монофонического и двух для стереофонического воспроизведения до семи, а размер числа, выражающего уровень сигнала в каждый момент времени, вырос в несколько раз. Длительность звуковых файлов многократно возросла, чтобы они реже повторялись. Пусть в результате размер звуковых файлов тоже вырос в миллион раз. Ставим ещё одну галочку. Следовательно, игры можно снять с крючка: у них есть веская причина. Но что же с остальными продуктами?
Сколько графических и звуковых файлов присутствует, например, в пакете из редакторов текстов, электронных таблиц и презентаций? А сколько в пакете виртуализации? А в системе управления базами данных? От нуля до исчезающе малой величины, но и они разбухли в десятки, сотни и тысячи раз, а пользователь не замечает в них ничего нового, кроме ошибок. Так зачем всё это? Признаюсь сразу: я не лазил в их исходный код и не проверял, чего туда накачали. Я лишь сам сидел и писал код для разнообразного ПО, обслуживающего предпринимательскую деятельность в нескольких отраслях. И вот моё-то ПО росло с каждым выпуском на ничтожно малую величину: единичные проценты. Основной его объём составляли библиотеки, которые изредка приходилось добавлять, чтобы воспользоваться ещё какой-нибудь новой функцией. С чего бы мой и чужой код так различались в объёме? Ответ неутешительный: или в общедоступное ПО постоянно привносится всё больше функциональности, недоступной и ненужной пользователю, или качество его исполнения стремительно ухудшается. Иного не дано: или дудочка, или кувшинчик, или пение, или танцы.
Если обратить внимание на процессы, происходящие в отрасли информационных технологий, то возникает масса вопросов. Эта отрасль обожает красивую и при этом запутанную терминологию. С её помощью легко одурачить тех, кто не имеет специального образования и опыта, и продать им пустышку. Чего стоят все эти инверсия контроля; микро-сервисы; впрыскивание зависимостей; оркестрации; чистая разработка; структура сущностей; разработка, управляемая тестами; кэширование и океаны подобной же мути, спрыснутые названиями, вообще не несущими никакой смысловой нагрузки и требующими разъяснения! Они всегда произносятся напыщенно, безапелляционно, с чувством превосходства (я знаю, а ты нет!) и служат для самодостаточного объяснения и оправдания практически чего угодно. А потом пользователь сидит и ждёт, пока интернет-приложение соизволит прекратить крутить своим бубликом и загрузит страницу.
Стесняюсь спросить: скажите, а количество пользователей ресурсов в Интернет тоже выросло в десятки тысяч раз? Нет. Население Земли за это время почти удвоилось, количество самих ресурсов выросло в тысячи раз, и нагрузка на многие из них осталась на том же самом уровне. Количество процессорных ядер на кристалле увеличилось в десятки и сотни раз, и самих процессоров теперь несколько. Да, есть ресурсы, которые теперь обслуживают в миллион раз больше пользователей, но они-то почему-то как раз работают быстро. Что же скромно нагруженные ресурсы безбожно тормозят-то? А объяснение-то простое: их разработчики всех надули и или притворились профессионалами, не имея адекватных знаний и опыта, или имея, но намеренно создав посредственные решения.
Обмануть руководство, не имеющее специальных знаний в области информационных технологий, проще простого. Им достаточно соврать, и проверить за разработчиками они не смогут, даже если наймут независимого консультанта, потому что он ест из того же корыта и может не пожелать выдавать своих, которые нагромоздили мусорную кучу нелепых решений, скроенных из нелепых продуктов и технологий. Глядя на множество широко известных и повсеместно применяемых решений, обнаруживаешь именно это: бред сивой кобылы и мошенничество. Чего стоит, например, популярная система управления содержанием WordPress! Её структура и применённые в ней решения послужили причиной обсуждения на одном популярном ресурсе, где кто-то спросил, почему бытует ненависть к языку PHP, а ему ответили, что она проистекает от знакомства с WordPress, которая является его олицетворением. Да, этот продукт настолько ужасен, что ненависть к нему самому распространилась на язык программирования, на котором он написан. Но он не единственный такой: есть множество похожих примеров, и их число растёт.
Типичный проект в наши дни начинается с впрыскивания зависимостей. Задумка замечательная: каждый класс в объектно-ориентированном языке порождается от абстрактного класса и следует интерфейсу, являющемуся декларативным договором о правилах его вызовов. Это позволяет подменять фактическую реализацию интерфейсов классами основного проекта их проверочными вариантами в тестовом проекте, который используется, как критерий годности изменений к внесению в выпускаемый продукт. Но концепция впрыскивания зависимостей не бесплатная: она тянет за собой немалый объём библиотек, и вот минимальный проект, способный лишь печатать «Здравствуй, мир!», уже объёмом не несколько байт или килобайт, как в было в прошлом тысячелетии, а десятки мегабайт. За этим тянется т.н. структура сущностей, без которой нынешние, вечно ноющие разработчики не могут шагу ступить, и вот проект уже превышает сотню мегабайт. Завернём его в контейнер и добавим оркестрацию, потому что без масштабирования современный разработчик впадает в кому, депрессию или истерику. Так мы можем накидать объём, который не поместится на компакт-диске, а он ещё даже не начал выполнять заявленную функцию, зато сколько красивых слов было сказано!
Интерфейс — замечательная концепция, позволяющая вызывать методы классов, соответствующие ему, из любого кода, даже на другом языке программирования. Для библиотек, равно как и для автоматизированного тестирования, интерфейс — самое то. Но их подали, как догму, и на неё купились конформисты, которых среди разработчиков большинство. В результате их суют везде и всюду, даже туда, где они не нужны, а это тоже раздувает код. В исполняемых файлах одноцелевых проектов, каковыми являются большинство решений для предпринимательской деятельности и потребительские, коробочные решения вроде Офиса или графических пакетов, интерфейсы не обязательны, но кого это интересует, и кто вообще в курсе?
Однажды я работал над проектом, который вела команда недавних выпускников престижного ВУЗа. Меня попросили помочь им со срочной работой. Первое, что я обнаружил, был один единственный тест, которым они проверяли изменения на годность. Эта сложная система обслуживания финансовых операций проверялась единственной моделью клиента в идеальных условиях, сферическим конём в вакууме. Слышали бы вы их недовольство, жалобы и нытьё, когда я добавил полтора десятка прямых и обратных тестовых условий внутри, на границах и за пределами допустимых диапазонов значений, и внезапно проект перестал проходить проверки перед сдачей. Эти разработчики применили все красиво звучащие технологии, наворотили бесчисленные слои библиотек и файлов сценариев, с гордостью хвастались новомодными решениями, но оказалось, что они всю дорогу обманывали себя и руководство, что в итоге привело к провалу.
Ещё мне довелось работать над развитием проекта, который оказался мошенничеством от начала и до конца. Будучи циклически вызываемым исполняемым файлом, который делал выборки из базы данных, формировал из них файлы и отправлял их подрядчикам, проект представлял собой Вавилонскую башню, нагромождённую из самых новомодных решений, в которых не было никакой потребности. Тут следует сделать отступление и упомянуть главное из них: асинхронность. Это очень важная технология, которая получила распространение в последние 10-15 лет. Заключается она в том, что код, функции которого вызываются в случайные моменты времени и зачастую разными пользователями (как живыми людьми, так и сторонним ПО), не ждёт весь целиком, пока закончится обработка одного такого запроса, а отрабатывает и другие запросы и отвечает на них по мере их завершения. Замысел грандиозный, но его применение бывает совершенно неуместным, потому что асинхронность тоже не бесплатная, а сопровождается падением производительности. Тот самый однопользовательский и однопоточный проект был на 100% асинхронным, тогда как в этом не было никакой нужды, а вот в высокой производительности как раз была. Разработчики всех обманули, зато как красиво звучали их заявления!
Массовый психоз в среде разработчиков ПО по поводу асинхронности ничем не отличается от такового по поводу глобального потепления. Оба фактически являются культами со всей атрибутикой: проповедники, фанатики, последователи, ритуалы. О чём ни спроси, в ответ сразу зазвучит негодование, что не используется асинхронность, вплоть до оскорблений. Всё это явно носит характер информационной войны, ведущейся проплаченными сотрудниками. А если задуматься, то в ней далеко не везде имеется необходимость. Цена за применение асинхронности доходит до производительности в несколько раз ниже. Задумайтесь! Это не какие-нибудь 2-3%, а 200-300%, а то и больше. Машина состояний, которая программно поддерживает асинхронные вызовы, не бесплатная в плане процессорных тактов и имеет свои ограничения. Её продавливают, запугивая разработчиков многопоточностью, которая страшная, не прощает ошибок и вообще вчерашний день, хотя и не сопровождается сравнимым падением производительности. Почему? Причина проста: облака.
Одним из главных погонщиков асинхронности является, по странному совпадению, крупнейший поставщик облачных услуг. Ему невыгодно, чтобы клиенты использовали многопоточность, потому что на одно процессорное ядро их нужно набить как можно больше. Асинхронность не обязательно запускает новый поток на другом ядре. Повышается степень использования процессорного кэша. Вот и ответ, кому это выгодно. Что ПО клиента замедлится, поставщику безразлично или даже выгодно: деньги продолжают капать за каждый такт процессора.
Следующий повод для повального помешательства — это контейнеры, без которых никто не попадёт в микро-сервисный рай. Всеобщее сумасшествие дошло до того, что разработчики теперь обязаны иметь опыт работы с контейнерами и с их оркестрацией, хотя на самом деле это область деятельности системных администраторов. Подаётся это под соусом масштабируемости, которая заменила собой производительность. Задумываться о соотношении этих двух понятий не модно, и производительность теперь предпочитают не упоминать. Попробуйте, и на вас зашипят со всех сторон: не дай Бог ты оптимизируешь свой код, интересуешься производительностью альтернативных решений и/или тревожишься об их влиянии на производительность. Ты не должен! Тогда ты плохой. Применяй асинхронность, контейнеры и микро-сервисы, и твой код будет масштабируемым. Тогда ты хороший, и не важно, нужна ли масштабируемость кому-то сейчас, и понадобится ли она кому-то в будущем. Главное — это надеть шоры и нестись по прямой, не сворачивая, а то, что производительное, хотя и менее масштабируемое решение требует меньше ресурсов, работает быстрее и оказывается дешевле в эксплуатации и доработке, никто не должен знать.
Производительность — это когда ПО работает быстро с одним пользователем и чуть медленнее с несколькими. Масштабируемость — это когда оно работает одинаково медленно, что с одним, что с несколькими. Существуют ли эти множественные пользователи в природе, проповедники масштабируемости предпочитают умалчивать. Если вы зашли на ресурс, где картинки товаров медленно прорисовываются в случайной последовательности, и непонятно, обновились они все или нет, то это микро-сервисная архитектура, и благодарить за эту неразбериху нужно последователей её секты.
Мне довелось поработать на проекте, производительность которого оставляла желать лучшего, но причина была объективной: она ударилась в возможности устаревающих технологий, применённых в начале разработки. Им имелось простое и эффективное решение, которое я уже успешно применял в прошлом. Предложение применить его было встречено в штыки, потому что ведущий разработчик мечтал переписать проект с использованием контейнеризации и микро-сервисов, ради карьеры. Надо ли упоминать, что воз и ныне там, потому что финансировать масштабный проект по коренному переписыванию системы, которая удовлетворяет потребителей функциональностью и лишь подтормаживает, никто не станет? А ведь скорости можно было добавить, просто заменив несколько вызовов функций на другие.
Как я уже неоднократно писал, работники отрасли информационных технологий мечтают прославиться. Делают они это при помощи своих проектов, преимущественно с открытым кодом, выложенным в общий доступ. Некоторые этим довольствуются, но иные с пеной у рта рекламируют эти проекты, сами или с помощью спонсоров, чтобы о них узнали и начали их применять как можно более широкие круги разработчиков. Среди них есть шедевры мысли, равно как и откровенный мусор. Чтобы протолкнуть его, нужно много и красиво врать, причём то, что другие разработчики хотят услышать. Проще всего пообещать им, что в случае применения такого проекта они сэкономят нажатия на клавиши для написания исходного кода. От этой прикормки программист дуреет и охотно заглатывает крючок с такой наживкой, не задумываясь о последствиях.
Примером служит т.н. структура сущностей, Entity Framework. Её создатель обещал потребителям, что им больше не придётся писать запросы на языке SQL к базам данных. Чем всё закончилось? Тем, что выросло поколение юных и доверчивых разработчиков, выдающих на гора тормозной код с многочисленными проблемами доступа к данным. Появились и такие, кто о транзакционной целостности данных отродясь не слышал. За это время специалисты по базам данных и языку SQL стали вымирающим видом. И вот пользователь сидит и смотрит на не прорисованные элементы страниц Интернет-приложений и вертящийся бублик загрузки, а поддержка требует от него очистить файлы «куки». Зато применяются шаблоны дизайна и разработки!
Казалось бы, тут вырисовывается противоречие со стремлением разработчиков усложнять свой код, но нет, всё совпадает. Они используют возможность печатать меньше исходного кода, чтобы его можно было усложнить, ведь им теперь не приходится тратить время на обдумывание действительно необходимых функций, а значит, можно просто добавить воды.
Эти шаблоны набили оскомину. Сколько разработчиков, столько и шаблонов. У каждого он есть, и все пованивают. Помешательство по их поводу доводит до того, что достаточно стало упомянуть, что ты применяешь какой-либо шаблон, и все вопросы к структурированию кода и применяемым решениям отпадают: ведь это его величество Шаблон! А представляет ли он ценность или нет, мало кого теперь волнует. Видал я такие шаблоны... Почему-то самыми популярными являются те, которые разрывают возможность двигаться по иерархии вызовов методов классов при помощи сред разработки, используя т.н. технологию «подразумеваемых вызовов». Ещё бы! Ведь это позволяет разработчику, применившему шаблон, запутать код и других разработчиков, тем самым обезопасив своё рабочее место от сокращений или подсиживания. Для него, чем труднее разобраться, тем лучше и безопаснее. А ещё, чтобы такие вызовы работали, нужна дополнительная библиотека. И вот код распухает ещё больше.
Т.н. декорации или атрибуты классов, методов и их аргументов — это решение из той же оперы. Они подменяют явно отрабатывающий код неявным, скрытым в библиотеках. Конечный результат очевиден: вырастает поколение разработчиков, представления не имеющих, как на самом деле работает используемая ими технология. Зато они печатают меньше низкоуровневого кода. Лиши их этих библиотек, и они будут не в состоянии ничего создать. К какой же мысли я подвожу читателя?
А мысль эта проста и стара, как мир: ничто не бывает бесплатным. Точно так же, как владелец автомобиля, который не знает, что такое свеча зажигания, сцепление, коробка передач, тормозные колодки и антифриз, вынужден платить автомеханикам огромные суммы за простейшее обслуживание, которое он мог бы выполнить сам, потратив минут пятнадцать, так и разработчик, во всём слепо полагающийся на вызубренные шаблоны и разрекламированные библиотеки и решения, стоит человеческому обществу гораздо больше, чем разумно необходимо. Эта стоимость растёт, как снежный ком, если принять во внимание все аспекты полного цикла разработки и эксплуатации технологических решений. Индустрия информационных технологий продажна, как женщина лёгкого поведения на вокзале, причём скрывающая доход от своего сутенёра. В результате человечество тратит астрономические суммы на решения, которые не подходят для поставленных задач в силу нехватки знаний, опыта и способностей у разработчиков или их намерений, а потратив их, сидит и покорно любуется не прорисованными страницами и вращающимся бубликом загрузки.
Что делать? Вооружаться четырьмя действиями арифметики и проводить те же вычисления, которые я привёл в начале статьи. Если оказывается, что в 2025 году программное обеспечение работает медленней, чем в 2000, значит такому ПО и его разработчикам грош цена в базарный день. Для выполнения любой задачи ПО нужно пропустить через вычислительную технику определённое количество машинных команд и прокачать определённый объём данных. Если время ожидания результата намного больше суммы их обработки, значит здесь нас дурят. К сожалению, это наблюдается повсеместно и постоянно. С этим нужно разбираться, а не то мы откатимся в каменный век.
Свидетельство о публикации №225121902093