Debitoor is hiring. No bureaucracy, no legacy code, no bullshit, fury continuous deployment, trips #js #node #react #mongo
×Закрыть

Программирование в форме диалога. Часть I. Зачем это нужно

Технологии программирования постоянно совершенствуются, делая процессы создания и использования программ всё более дешёвыми, как того требуют законы экономики. Удешевление создания программ достигается за счёт большей автоматизации процесса программирования (что позволяет либо уменьшить требования к квалификации программистов, и/или повысить производительности труда программистов). Удешевление процесса использования программ включает в себя как повышение качества программ — уменьшением количества ошибок, уменьшение требований к ресурсам (памяти, скорости CPU, стоимости компьютера в целом) — что тоже может быть достигнуто увеличением уровня автоматизации создания программ. А увеличением функциональности программ (что позволяет в большей степени автоматизировать и облегчить работу пользователей) достигается повышением уровня абстракции, которым может оперировать программист.

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


Для того чтобы увидеть причину этого кажущегося парадокса, достаточно понять, что эти цели (порождённые требованиями экономики) находятся в диалектическом противоречии, и недостижимы одновременно. Уменьшение стоимости разработки программ уменьшит её качество для пользователя, но оно же уменьшит и стоимость программы для потребителя. Увеличение сложности и функциональности программы неизбежно потребует увеличения стоимости разработки и требуемые ресурсы компьютера (то есть — более дорогого компьютера). То есть разработка программы требует определённого компромисса между несколькими противоречивыми требованиями.

Согласно правилу Мура, мощность (производительность и память) компьютеров увеличиваются экспоненциально, уже десятки лет. Сложность программ увеличивается с ростом её размера очень быстро, а стоимость разработки растёт ещё быстрее. Поэтому производители программного обеспечения просто вынуждены постоянно делать выбор в пользу меньшей стоимости разработки в ущерб уменьшению потребления ресурсов. Судите сами — разработка вдвое более сложной программы, при том же уровне оптимизации, потребует в несколько раз больше денег и времени. Пусть фирма M затратит 1 год и 1 миллион, а вторая фирма L напишет более оптимальный код, и вынуждена будет потратить 3 года и 10 миллионов. M выпустит продукт раньше, и захватит рынок, хотя все будут жаловаться, что она тормозит и жрёт непомерно много памяти. Через два года большинство компьютеров уже будут иметь достаточно памяти и скорости процессора, необходимые для работы программы фирмы M. За эти 2 года, конечно, фирма M затратит много денег на исправление программы, но тратить она их будет из своей прибыли, а через 2 года у неё уже будет 3-я версия, исправленная и улучшенная, являющаяся стандартом де-факто на рынке. И тут вторая фирма L выпустит свой продукт. Да, он будет менее требователен к ресурсам и более надёжен — по сравнению с первой версией программы фирмы M. Но увы, он уже никому не будет нужен. Подавляющее большинство пользователей уже будет вполне довольны программой от M, а инвесторы фирмы L будут крайне, крайне разочарованы.

Автоматизация программирования включает в себя много аспектов. Это и оптимизирующие компиляторы, и более высокоуровневая среда исполнения (включающая, например, автоматическое управление памятью, динамическую оптимизацию кода и пр.). Это и более высокоуровневые языки программирования (которые транслируются компьютером в низкоуровневые понятия). Это и автоматизация частичной проверки правильности программы во время компиляции, включая и автоматический вывод некоторых свойств программы (например, вывод типов). Это и более интеллектуальные IDE, с интеллектуальным редактором, отладчиком, рефакторингом кода, анализом потенциальных ошибок. Это и средства метапрограммирования (как статическое, времени компиляции, так и динамическое, времени исполнения программы), автогенерация кода, лёгкость создания DSL (специализированных языков). Это и вспомогательные средства, вроде систем контроля версий кода программы, баг-трэкинга. И многое другое, что в целом можно охарактеризовать как перекладывание на компьютер части работы программиста.

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

Увеличение количества уровней абстракции не обязательно приводит к значительному повышению расхода ресурсов компьютера. Особенно если все эти уровни разрабатывались совместно, в рамках одной задачи, для решения конкретно этой задачи. Но на практике оказывается, что качественная реализация всех этих уровней абстракции — стоит слишком дорого, и просто нецелесообразна для одной конкретной задачи. Мы вынуждены использовать процессоры, не идеально подходящие для нашей задачи, среду исполнения (виртуальную машину, или ран-тайм среду исполнения и стандартные библиотеки какой-то из реализаций языка программирования), язык программирования общего назначения, не идеально подходящий для решения нашей конкретной задачи, и так далее. Самое печальное в этом, это то, что мы не можем «перескочить» через эти промежуточные уровни абстракции. Мы не можем добавить в язык Java команду goto, которая, при генерации кода для конечных автоматов, может значительно повысить скорость исполнения кода. Хотя в абстракции более низкого уровня (байт-коде JVM) эта команда есть. Точно так же мы не можем использовать SIMD инструкции в байт-коде JVM, хотя в наборе инструкций CPU (абстракции более низкого уровня) они есть, и могут повысить производительность некоторых программ в несколько раз.

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

Но мы вынуждены идти на эти расходы (поскольку должны писать всё более сложные программы) с одной стороны, а с другой стороны, пока действует правило Мура об экспоненциальном росте производительности компьютеров — мы вполне можем себе позволить эти расходы.

Но сейчас компьютерная индустрия оказалась на пороге колоссального кризиса, который делает непригодными те принципы развития, которые использовались до сих пор. Производительность компьютеров уже перестала расти экспоненциально. И хотя правило Мура всё ещё действует, и количество транзисторов ещё растёт экспоненциально (а, следовательно, растёт количество памяти, проблема скорости доступа к ней несколько сглаживается огромными размерами кэша CPU, и дополнительные транзисторы используются для более интеллектуального анализа и исполнения кода в CPU, да и многоядерность процессоров повышает производительность компьютера для некоторых типов задач) — он окончится уже в ближайшие несколько лет. Были надежды, что он протянет ещё лет 10, но разразившийся финансовый кризис не позволит тратить огромные средства необходимые для совершенствования техпроцесса, и, по-видимому, правило Мура перестанет действовать уже года через 2 или 3, когда будут внедрены текущие наработки.

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

С системной точки зрения, есть два (диалектически противоположных) способа оптимизация системы, то есть её удешевления и эффективности. Это узкая специализация с одной стороны, и адаптация с другой стороны. Узкая специализация достигается достаточно просто — от более универсального решения отсекается всё лишнее, и в результате мы получаем более простую, дешёвую и эффективную реализацию. Правда, эта узкоспециализированная система позволяет эффективно решать только очень небольшой класс задач, и её эффективность резко падает, если её использовать для решения других задач. А со временем задачи меняются, всегда. И узкоспециализированное решение приходится выбрасывать, и создавать новое, для изменившихся условий. Если условия меняются достаточно быстро, или нам постоянно приходится решать достаточно большой класс задач — то вместо специализации мы можем пойти другим путём, адаптивным. То есть, создать систему или решение, которое можно динамически изменить, адаптировать к новым условиям и задачам. При адаптации эффективность системы может значительно возрасти, практически приблизится к эффективности узкоспециализированного решения. Правда, адаптивная система, как правило, намного более сложна и дорога в производстве, по сравнению со специализированными системами. Но в эволюционном плане адаптивное решение имеет больше шансов на выживание при изменении условий. А при большом разнообразии решаемых задач или большой сложности этих задач — адаптивное решение ещё и более выгодно, так как вместо нескольких узкоспециализированных систем мы можем использовать одну адаптивную, и её стоимость может быть ниже, чем сумма стоимостей всех необходимых специализированных систем.

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

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

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

Переход к написанию программы компьютером — это переход от монолога, к диалогу. При этом, так же как и при диалоге человека с человеком, у компьютера должна быть своя, внутренняя модель программы. У компьютера должна быть возможность вводить новые понятия (в терминах которых эта модель и будет выражена). Он будет общаться с человеком (программистом) на некотором языке (языках), достаточно независимом от внутренней модели программы. Эта модель будет изменяться не непосредственно программистом, а в результате диалога между компьютером и программистом. Эти языки общения будут специально приспособлены для удобства понимания человеком и его команд, а модель программы внутри компьютера будет приспособлена для работы с ней компьютером, а не человеком. Различные языки позволят отображать программу или её части с большей или меньшей степенью детализации, по-разному отображать разные аспекты одного и того же кода. Например, при проектировании пользовательского интерфейса у кода программы есть несколько аспектов — скажем, в терминологии MVC (Model-View-Control), это модель данных, модель отображения, и модель реакции компьютера на действия пользователя. Отображение удобней видеть и редактировать в графическом виде (окна диалогов, кнопки, поля ввода и прочее), модель данных в декларативном виде (структуры, поля, типы, шаблоны ввода и прочие условия правильности данных), реакцию в виде процедурного кода. Большую или меньшую детализация кода программы вы можете представить себе на примере автоматического вывода типов (имеющегося в некоторых языках), только при диалоге с компьютером это будет режим отображения или не отображения (заданных или автоматически выведенных) типов переменных и функций. Или другой пример — программу можно отобразить как низкоуровневый код, или как высокоуровневую модель (что-то вроде UML-подобной модели).

Cм. также продолжение: Часть II. Реализация диалога, предыстория

  • Популярное

1 комментарий

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

Что вам сказать, очень интересная аналитика, сам подумывал о таком решении написания программ, т.е. обмозговывал варианты создания ПО с минимальным участием человека, переложив тонкости написания на плечи ПК. В моём понимании это: общая стандартная (как система СИ) технология «общения» ПКЧеловек, созданная некой группой (группами, компаниями) величайших программистов из абсолютно разных сфер и областей программирования, которые не один год будут работать над единой системой управления созданием программного обеспечения в форме диалога между ПК и человеком, где человек является источником команд и функционала программы, а компьютер — исполнитель и формирователь кода.Возможно, моё понимание далеко от истины, но полагаю, что часть этого будет выглядеть именно так.P.S. замеченные ошибки (опечатки): «...по-разному отображать разные аспекты одно_ (го) и того же кода. »" Большая часть компьютерных фирма разорится, а..."

Подписаться на комментарии