Выкладываю текст моего доклада на Соруком-2017. На самой конференции пришлось сильно ужаться, чтобы влезть в 20 минут, выделенных на доклад. Что, естественно, привело к тому, что часть важных мыслей остались только в тексте.
Для тех, кто не хочет долго читать, есть короткая презентация.
Замечание: В рыжих скобках, такие как [1] — ссылки на примечания. Сами примечания, в конце статьи. В черных скобках ссылки на литературу, список тоже в конце статьи.
Постановка задачи
За последние десять лет вычислительная техника глубоко вошла в быт. Достаточно вспомнить мобильную связь, облачные технологии и IoT.
Вот краткий и совсем не полный перечень технологических прорывов, которые изменили повседневную жизнь и работу:
- 2006 Amazon Elastic Computing Cloud
- 2007 iPhone
- 2008 DropBox
- 2009 Яндекс почта для домена
- 2010 iPad
- 2012 Яндекс.Диск
- 2014 Виртуальное приватное облако — Selectel
Замечу, что многие технологии и устройства так прочно вошли в нашу жизнь, что трудно представить себе, что совсем недавно их не было.
Как мы все понимаем, внедрение новых технологий потребовало существенного объема программирования. Любопытно (и грустно), что при этом технологии программирования использовались старые. По сути, технологии программирования существенно не менялись на протяжении двадцати лет. В конце прошлого века надежда на развитие еще была, достаточно вспомнить бурное развитие OOP, идеи COP (Component-oriented Programming), Generative Programming, DSL (Domain Specific Languages), продвижение в верификации программ. Все эти технологии и идеи по-прежнему как-то развиваются, но надежды на существенное улучшение благодаря им уже нет. Мы по-прежнему программируем долго, дорого и не надежно, а разработка программного обеспечения по-прежнему далека от нормального производства, настолько она плохо планируема и слабоуправляема.
Отсутствие существенного прогресса может быть объяснено принципиальной сложностью программирования (см. например [1]) или тем, что мы подошли настолько близко к совершенству, что развитие может идти только медленно.
По поводу принципиальной сложности, замечу, что сложность обязательно будет, если не ставить себе задачу упрощения, вспомним “Make it simple as possible”. Увы, но задача упрощения вышла из моды. Полагаю, что одна из причин этого – это трудность упрощения.
Что же касается аргумента о «медленности развития…», приведу еще одну аналогию. Мы можем двигаться медленно к цели, потому что идем не прямо к ней, а, под углом (например, 80 градусов). Поэтому КПД очень мал.
Используем прием, предложенный Раймондом Джоунсом в фантастическом рассказе «Уровень шума»[1]. Предположим, что принципиально лучшие технологии программирования (быстрее, дешевле, надежней) существуют, и попробуем хотя бы одну воспроизвести.
Возникает вопрос – с чего начать?
Предлагаю начать со сравнения с другими (устоявшимися) производствами. Для таких производств характерно наличие разных уровней инструментов – на крупносерийном производстве используются другие инструменты и процессы, чем на мелкосерийном, ремесленном и бытовом. В программировании отсутствует «глубина», мы используем практически одни и те же инструменты для студенческих работ и для больших производственных систем[2].
Попробуем разделить области программирования на слои, надеясь выделить разные уровни программирования и упростить задачу за счет внесения структуры.
Очевидно выделенным является b2c сектор, назовем его программированием приложений (см. например, Google Play Market). Для того чтобы приложения могли работать, необходимы обеспечивающие уровни (например, облака) и инфраструктура. Тем самым явно выделяются еще два слоя – производственный или корпоративный (b2b) и государственный (инфраструктурный).
Мы получаем следующие слои, что интересно, с разными приоритетами[3] требований к программам:
- Государственное программирование: защищенность (безопасность), бесперебойность, надежность, производительность (инфраструктура)
- Производственное программирование: надежность, гибкость, предсказуемость, производительность, инновации (OS, SDK, web, облака, …)
- Программирование приложений: time-to-market, конкурентные преимущества, инновации
Другой (сходный) взгляд на разделение программирования был предложен Русланом Богатыревым в обсуждении. Он предложил ввести в программирование понятие аналогичное сопромату. Очевидно, что требования к надежности программы управления АЭС и игрушке на смартфоне принципиально разные. По сути, «материал», из которого изготовлены эти программы, должен быть разным, так как он подвергается принципиально разным «нагрузкам». Следовательно, и средства разработки должны быть разными. Сейчас этого нет.
Для простоты начнем с самого верхнего слоя. Является ли слой приложений самым верхним? Безусловно, что он был верхним слоем до последнего времени, но развитие гаджетов и IoT привело к появлению еще одного слоя, который пока не выделен понятийно.
Например, хозяин умного дома настраивает совокупность датчиков, исполнительных и управляющих устройств, в том числе взаимодействие со своим смартфоном. Можно ли назвать эту настройку программированием? Возможно, что сейчас это еще не программирование, так как у адекватных инструментов для него нет, но это близко к программированию.
Назову такое программирование бытовым программированием.
Бытовое программирование
Бытовое программирование – программирование человеком своих устройств для решения бытовых задач. Бытовое программирование очевидно распространяется на решения семейных задач и (частично) задач индивидуальных предпринимателей и малых предприятий. К «своим» устройствам я отношу не только гаджеты и компьютеры, а также сервисы и ресурсы (например, Яндекс.Диск), которые могут использоваться для решения своих задач.
Главной особенностью бытового программирования является то, что программы делает не профессиональный программист.
Зачем я выделяю уровень бытового программирования?
Во-первых, на этом уровне нет привычных образцов, мешающих думать. Во-вторых, если мы поймем, как программировать на бытовом уровне, мы сможем увидеть, что надо изменить в слоях, обеспечивающих бытовой, в первую очередь, в слое приложений и производственном слое.
Замечу, что требования к инструментам разработки для бытового программирования явно отличаются от требований к инструментам для других уровней. Для бытового программирования важны: легкость программирования, наглядность, унифицированный способ работы с разными устройствами, отсутствие необходимости в длительном обучении и чтении руководств.
Несколько опережая логику рассуждения, скажу, что бытовое программирование, на мой взгляд, — это не синтезирующее программирование в классификации А.П. Ершова [2]. Это, скорее, сборка некого «супер-приложения» из сервисов и компонентов разных производителей, работающих на разных устройствах.
Рассмотрим бытовое программирование на жизненном примере.
Ребенок идет домой из школы. Хочу:
- Получить сигнал, когда он вышел из школы
- Получить тревожный сигнал, если он вышел не вовремя
- Посмотреть маршрут движения на карте – онлайн или позже
- Получить сигнал, что он дошел до дома
Очевидное условие: у ребенка должно быть устройство с GSM/GPS (часы, браслет или телефон)
Что мне, как бытовому программисту, нужно для решения этой задачи:
- Расписание уроков (доступное по сети)
- Гео-локатор в устройстве (доступный по сети)
- Карта с возможностью изображать маршрут на моем устройстве (смартфон, планшет, десктоп)
- Сервис для сохранения маршрута (облако, желательно приватное)
- Сервис, связывающий все компоненты – некий управляющий «диспетчер»
Если все это у меня есть, я могу написать скрипты и расставить триггеры для запуска этих скриптов. Скрипты и триггеры в совокупности и составляют «супер-приложение», решающее задачу.
Набросаю часть решения (то, что нужно запрограммировать):
- Диспетчер отслеживает время завершения урока (сервис времени) и подает сигнал тревоги, если через N минут после завершения урока ребенок не вышел из школы;
- Устройство ребенка посылает сообщение диспетчеру при пересечении границы школы;
- Получив сигнал от устройства (о пересечении границы), диспетчер проверяет время по расписанию уроков – подает сигнал тревоги (на мое устройство), если не вовремя, или сигнал выхода, если вовремя;
- Диспетчер подключает поток координат к карте на моем устройстве для показа маршрута;
- Диспетчер сохраняет маршрут в облаке;
Очевидна похожесть супер-приложения на программу на визуальном языке Scratch. Программа на Scratch также есть совокупность скриптов, срабатывающих по триггерам, например, триггер начала работы, триггер касания объектов на экране и т.д. Разница в том, что супер-приложение является распределенным и меж-платформенным.
Рассмотрим теперь, что нужно бытовому программисту (родителю в данном случае), чтобы собрать супер-приложение:
- Среда разработки: визуальная (a la Scratch) или скриптовая или любая другая. Очевидные требования: наглядность и независимость от платформы, на которой будет исполняться конкретный скрипт (часть супер-приложения).
- Возможность узнать, есть ли нужные сервисы или компоненты на каждом устройстве
- Возможность установить нужные сервисы/компоненты, если их нет.
- Возможность получить интерфейс (способ взаимодействия) необходимых сервисов и компонентов и возможность их использования
- Возможность задать назначение скриптов на устройства
- Возможность задать триггеры: подключить скрипты к событиям (от календаря, от устройства, от часов …)
Самое важное здесь, на мой взгляд, это возможность использование сервисов и компонентов (разных разработчиков, на разных устройствах). По сути, мы говорим здесь о создании объединяющей экосистемы, которая дает возможность доступа к существующим экосистемам (iOS, Android, Java, C++, Linux, Windows…). Замечу сразу, чтобы задача не выглядела слишком большой – дает возможность доступа в рамках нужных для бытового программирования.
Рассмотрим теперь принципиальный вопрос – а нужно ли вообще бытовое программирование?
Задачу с отслеживанием ребенка я могу решить, купив детские GPS/GSM часы, в комплекте которых я получу программу отслеживания для смартфона. Но что если мне надо еще включить мультиварку, чтобы подогреть обед, когда ребенок вышел из школы. Предусмотрит ли разработчик приложения всевозможные настройки для своей программы? В том числе и взаимодействие с устройствами, которые еще не появились на рынке?
Мы можем идти традиционным путем и иметь непрерывное обновление всех приложений (а для этого непрерывную работу разработчиков) или перейти к разработке отдельных компонент и сервисов, которые соединяются скриптовым «клеем». Если мы идем вторым путем, задача разбивается на отдельные (в идеале ортогональные) части, а это должно существенно сократить общие затраты на разработку. Результатом работы профессионального программиста должны быть, в первую очередь, компоненты и сервисы.
Если задуматься, то я не предлагаю ничего нового, например, мы можем вспомнить SLR (Single Responsibility Principle), а так же Unix Way:
- Пишите программы, каждая из которых делает что-то одно и делает это хорошо.
- Пишите программы, которые бы работали вместе.
- Пишите программы, которые поддерживают текстовые потоки, поскольку это универсальный интерфейс
Это нам и нужно, только на новом уровне:
- Пишите компоненты (сервисы), каждая из которых делает что-то одно и делает это хорошо
- Пишите компоненты (сервисы), которые бы работали вместе (которые можно соединить)
- Пишите self-describing компоненты (сервисы)
О самоописываемых компонентах надо поговорить подробнее. В них также нет ничего принципиально нового, вот, например, рекомендации Microsoft для .NET.
Каждая самоописываемая компонента (сервис) должна (по запросу) выдавать информацию двух видов:
- Документацию для человека – назначение компоненты, способы использования, шаблоны использования.
- Формальное описание для обращения к компоненте из скрипта: список функций, сообщений, сигналов, уведомление. Для функций: сигнатура функции (ABI[4], например, LLVM-type). Для потоков данных: название стандартного протокола или формальное описание протокола (для специфических протоколов).
Принципиально тут то, что эта информация «привязана» к компоненте. Документацию не надо брать (искать) извне. Тогда документация точно соответствует версии компоненты/сервиса.
В этом явные отличия бытового программирования от программирования приложений. Приложение должно работать на специфицированном подмножестве всех устройств (например, Android версии 5.0 и выше). А скрипт (составная часть бытовой программы) работает на конкретном устройстве, в конкретном окружении.
Распространение бытовой программы возможно, но, скорее всего, должно делаться уже профессиональным разработчиком, которые делает более универсальными части востребованного супер-приложения.
Кроме запроса к компоненте/сервису, должна быть возможность сделать запросы к устройству, позволяющие:
- Получить каталог всех сервисов и компонентов
- Искать компоненты/сервисы по ключевым словам
- Установить на устройство необходимую компоненту или сервис
- Нужна система защиты, которая позволяет получить информацию только владельцу устройства или доверенным лицам. Сразу же замечу, что это не root access (как бы он не назывался), это другое измерение доступа.
Если снова прибегнуть к аналогии, нам нужен стандарт на то, что я назвал бы «Software USB», позволяющий получить информацию о том, как использовать устройство, компоненту или сервис в бытовом скрипте. Все мы еще помним, как появление USB упростило использование компьютеров. И в этом факте есть немного надежды.
Чтобы завершить разговор о собственно бытовом программировании и перейти к тому, как должны измениться остальные уровни, приведу еще несколько примеров задач, которые сейчас решить очень трудно, и которые должны легко решаться на уровне бытового программирования.
Пример 1. Яндекс навигатор на карте Гугл.
Для бытового программиста Яндекс.Навигатор и Google Maps должны быть компонентами (как и Яндекс.Карты и многое другое). Так как Яндекс.Карты и Google Maps имеют аналогичное назначение, то естественно предположить что один из интерфейсов (разъемов) у них должен совпадать. И тогда, подключение навигатора к другой карте – это несколько строчек кода (или несколько визуальных блоков) в бытовом скрипте.
Замечание: «интерфейс» — это не интерфейс класса на некотором языке. Все интерфейсы бытового программирования должны быть языково-независимы, а типизация должна быть утиной (duck typing).
Пример 2. Объединенный календарь
Я хочу выбрать время для какого-то семейного действия. У меня есть:
- Мой корпоративный календарь
- Корпоративный календарь жены
- Расписание уроков детей
- Расписание дополнительных занятий детей
- Производственный календарь (расписание праздничных и выходных дней)
А если, я хочу позвать друзей, то хорошо бы еще согласовать время с друзьями.
Почему бы мне не сделать объединенный календарь, который показывает все пересечения?
Естественно, что говоря «объединенный календарь», я в действительности, говорю о двух разных сущностях:
- GUI часть календаря, позволяющая показать пересечения событий.
- Календарь-данные — это компонента (сервис), у которой можно запросить множество событий за определенное время.
Календарь GUI я установлю на свое устройство, а потом подключу к нему календари-данные, возможно, делая при получении данных какую-то дополнительную обработку.
На этом примере, мы видим еще одно важное следствие – бытовое программирование вынуждает нас определить Лексикон бытового программирования, по крайней мере, набор стандартных интерфейсов, таких, как «Календарь-данные» и «Календарь-отображение».
Лексикон стандартизует интерфейсы и упорядочивает усилия разработчиков. Стандартам становится выгодно соответствовать, хотя бы потому, что если у конкретной программы Календаря нет интерфейса календарь-данные, то это уменьшает его полезность, а, следовательно, и рыночную стоимость.
Предпосылки бытового программирования
Проверяя на коллегах идею бытового программирования, я убедился в том, что идея воспринимается и принимается без сопротивления. На мой взгляд, это говорит о том, что бытовое программирование готово к реализации, так как почва уже подготовлена.
Основными предпосылками являются уже упоминаемые мной гаджеты, облачные сервисы, IoT. Предпосылки другого рода это:
- Электронные конструкторы (Arduino) и конструкторы роботов
- Визуальные языки программирования (Scratch)
- Программирование на смеси скриптовых и компилируемых языков
- Утиная типизация (например, в GoLang)
Предпосылки второго рода я бы назвал «психологическими», так как они упрощают понимание бытового программирования, хотя и не могут быть непосредственно использованы в бытовом программировании.
Но есть и непосредственные предпосылки, среди которых принципиальным для бытового программирования является технология разработки мульти-платформенных программ. Я использую термин «мульти-платформенный», а не «кроссплатформенный», так как речь идет не о «переносе» программы с одной платформы на другую, а об одновременной работе частей распределенной программы на разных платформах. Увы, на рынке нет ни одной (работающей) технологии и среды разработки мульти-платформенных программ.
Замечание, системы кроссплатформенной разработки существуют, достаточно упомянуть Xamarin, Unity, Marmalade, Lazarus, но они малопригодны для разработки мульти-платформенных программ по нескольким причинам, которые надо обсуждать отдельно.
В то же время, работа над частями, которые должны бы входить в нужную нам среду разработки ведется на уровне продвинутых и успешных проектов (LLVM – многоцелевая генерация кода) и экспериментальных проектов (NaCl Pepper – мульти-платформенная среда исполнения).
Компилирующая система LLVM является существенным и принципиальным заделом для реализации бытового программирования. На мой взгляд, если бы LLVM не было, разговор о реализации бытового программирования был бы невозможен.
Альтернативой могло бы быть использование виртуальных машин (a la Java и .Net), но я считаю этот путь принципиально неверным. Виртуальная машина добавляет еще один уровень сложности, причем взаимодействие кода, исполняемого в виртуальной машине и кода исполняемого за её пределами, как показывает практика, неизбежно. Таким образом, использование виртуальной машины увеличивает сложность разработки и уменьшает производительность, при этом, не приносит никаких существенных преимуществ.
Для того чтобы пояснить мысль о принципиальности LLVM, рассмотрим историю развития многоцелевых компиляторов, разложив такие компиляторы на несколько поколений (основываясь на своем опыте и не претендуя на полноту изложения).
Поколение 1. Исторически первым известным мне способом сделать компилятор, способный строить рабочую программу для нескольких процессоров (платформ) была генерация кода для абстрактной машины и перенос этой машины на разные платформы. Известный пример – P-code для Паскаля (1973 г.). Использование P-code было не первым использованием этого способа, достаточно вспомнить O-code для BCPL (1966 г.) и SILдля Snobol-4 (1967 г). Недостатки использования абстрактной машины хорошо известны на примере Java, а часть недостатков уже упомянуты выше.
Поколение 2. Начиная с 1980-х, компиляторы с языка Си стали доступны для всех платформ и появлялись на новых платформах в первую очередь. Это привело к идее использовать Си в качестве выходного языка (переносимого ассемблера ) для компилятора. Такой способ мы использовали в компиляторе Extacy (1991 г). Extacy позволял строить Модула-2 и Оберон-2 программы для нескольких десятков различных платформ. Перенос на другую платформу не требовал реализации виртуальной машины, и, как правило, сводился к достаточно простым правкам в исполняемой среде (Run-Time System), написанной на Си. В отличие от способа с использованием виртуальной машины, потери производительности не было. Основные недостатки этого способа прямо вытекают из использования Си:
- чем больше семантический разрыв между исходным языком программирования и Си, тем труднее трансляция
- чем больше разница в модели исполнения программ в сравнение с Си, тем труднее реализация исполняемой среды (RTS).
В Extacy на уровне языков Модула-2 и Оберон существенного семантического разрыва с Си не было. А вот среда исполнения Си существенно отличалась от среды исполнения в Excelsior IV, в которой принципиальным была динамическая загрузка модулей и расширяемость системы, и мы даже не пытались эмулировать её через Си на других платформах.
Поколение 3. Один язык, сменная генерация кода. Идея сменной генерации очевидна: делим компилятор на две части. Первая часть (front-end) строит синтаксическое дерево, выполняя необходимый анализ, вторая (back-end) порождает код для конкретной платформы. Вторую часть делаем сменной.
Достоинства: генерация кода для конкретной платформы позволяет учитывать все особенности, строить любую среду исполнения программы.
Недостатки: трудоемкость перехода на новую платформу. Условно половину компилятора надо написать заново.
Я не смог достоверно определить, в каком первом компиляторе в истории использовалась идея сменных генераторов кода, поэтому приведу в качестве примера компилятор OP2 (Oberon Portable Compiler) [3], с которым я познакомился в 1991 году в ETH Zurich. Знакомство с этим компилятором подтолкнуло меня к разработке XDS [4].
Поколение 4. Многоязыковые, многоцелевые компилирующие системы.
Очевидная мысль, которая привела к разработке компилирующих систем: «заменить трансляцию с m входных языков в n машинных языков трансляцией “из m в один” и “из одного в n”» [5].
Компилирующие системы строятся по схеме:
- front-end – перевод языка программирования в промежуточное представление
- middle-end – машинно-независимая оптимизация
- back-end – машинно-зависимая оптимизация и генерация кода
Любопытно, что компилирующие системы, в каком-то смысле, являются обратными по отношению к компиляторам 3-го поколения, так как оптимизаторы и генераторы кода является постоянными частями, а анализаторы языков программирования – сменными.
Не претендуя на полноту изложения, вкратце опишу две компилирующие системы: XDS и LLVM.
Первая версия XDS вышла в 1994 году, она поддерживала компиляцию языков Modula-2 и Oberon-2 в код x86 процессоров и трансляцию в Си. Тогда же была начата работа над машинно-независимым оптимизатором, с появлением которого XDS стала классической компилирующей системой, которая включала не менее 5 языков и примерно столько же генераторов кода.
Разработка LLVM была начата в 2000 г., и сейчас LLVM включает поддержку множества языков и, наверно, всех процессоров, которые есть на рынке.
На первый взгляд XDS и LLVM похожи, как близнецы братья: та же архитектура (front-ends, middle-end, back-ends), схожая оптимизация на основе SSA формы.
Существенным преимуществом LLVM является удачный выбор промежуточного языка. В XDS, как и в OP2 в качестве промежуточного языка (выхода front-end) использовалось синтаксическое дерево. Далее синтаксическое дерево переводилось в форму удобную для оптимизации и далее в форму, подходящую для генерации кода.
Использование синтаксического дерева накладывает ограничение на компилируемые языки программирования из-за возможного семантического разрыва. Для XDS это не имело большого значения, так как все компилируемые языки (Модула-2, Оберон-2, Java, диалект Паскаля (Mitel Networks), SL1 – proprietary Nortel Networks language) были достаточно близкими, но в общем случае, это существенное ограничение.
Промежуточный язык LLVM (LLVM IR) существенно ниже уровнем, это типизованный абстрактный ассемблером. При этом задача преодоления семантического разрыва ложится на разработчика front-end.
Еще одной принципиальной особенностью, является то, что для оптимизатора LLVM IR является и входным и выходным языком. А это позволяет компилировать части кода (компоненты, скрипты) в IR и хранить их в виде IR, а потом переводить в код нужной платформы в любой удобный момент, включая JIT.
И наконец, LLVM – это не монолитное приложение, а набор приложений и библиотек, что-то вроде конструктора «Сделай себе компилятор сам».
Все это делает LLVM уникальным инструментом, как для решения производственных задач, так и для экспериментов в области технологий программирования, в том числе для реализации бытового программирования.
Реализация бытового программирования
Исходя из краткого описания бытового программирования, любой архитектор или грамотный разработчик с опытом легко выстроит шаги, необходимые для того, чтобы сделать возможным бытовое программирование.
Изложу кратко свое видение:
- Среда разработки с возможностями
- Подключения устройств
- Получения каталога компонентов и сервисов устройства
- Поиск среди компонентов и сервисов устройства
- Поиск в общем репозитории (Лексиконе бытового программирования)
- Установка компоненты или сервиса из репозитория на устройство
- Визуальная или текстовая разработка скрипта
- Привязка скриптов к устройствам
- Задание триггеров
- Среда выполнения скриптов (на каждом устройстве)[5]
- Загрузка, обновление и удаление скриптов с устройства
- Реализация триггеров
- Реализация переходников к ОС, позволяющих использовать средства ОС стандартизированным образом
- Стандарт на компоненты, сервисы и способы подключения и взаимодействие
- Репозиторий – Лексикон бытового программирования, содержащий
- Стандартные интерфейсы
- Стандартизованные компоненты разного уровня[6] и сервисы
- «Обертки» для не стандартизованных компонентов и сервисов, которые реализуют стандартные интерфейсы
- Для того чтобы программисты готовили компоненты и сервисы в соответствии со стандартами нужны инструменты, позволяющие добавить нужные обертки к существующим компонентам или код.
- Создание курсов бытового программирования и внедрение обучения.
Заключение
Любопытно, что поиск лучшей технологии программирования привел нас к Лексикону, о котором А.П. Ершов написал в 1983 г. в провидческой статье «Предварительные соображения о лексиконе программирования» [2]:
«Чем лексикон отличается от языка программирования? Он выражает не только и не столько программы, сколько их свойства и наши суждения о них. Язык программирования кодирует объекты предметной области задачи, а наше знание об этих объектах остается за пределами программного текста. Лексикон же является средством описания объектов предметных областей и содержит нотацию для построения баз знаний о предметных областях».
Естественно, что бытовому программированию и использованию Лексикона надо учить, что приводит нас статье А.П. Ершова 1981 г.: «Программирование — вторая грамотность» [4], к новому воплощении идеи о всеобщем обучении программирования. Прошло чуть больше 40 лет, и мы пришли к реальной потребности в воплощении идей А.П. Ершова.
Бытовое программирование придает практический смысл всеобщему обучению программированию, так как в нем есть польза для обучаемых. Сейчас же обучение информатике скорее дает повышение общего уровня грамотности.
Предполагаю, что когда появится Лексикон бытового программирования, начнет наполняться и более общий Лексикон (программирования приложений и производственного программирования) — репозиторий стандартных языково-независимых и кросс-платформенных компонентов.
В настоящее время часть изложенных идей проверена для одной платформы, идет работа над мультиплатформенной средой разработки Вир-2, использующей LLVM.
Список литературы
- Booch, Grady(1997). Object-Oriented Analysis and Design with Applications. Addison-Wesley. ISBN 0-8053-5340-2.
- Ершов, А. П. Предварительные соображения о лексиконе программирования// Избранные труды. Новосибирск, 1994.
- Régis Crelier. OP2: A Portable Oberon-2 Compiler Presented at the 2nd International Modula–2 Conference, Loughborough, Sept 91
- Недоря, А. Е., Расширяемая переносимая система программирования, основанная на биязыковом подходе : диссертация кандидата физико-математических наук : 05.13.11. — Новосибирск, 1993. — 139 с.
- Любимский Э. З., Поттосин И. В., Шура-Бура М. Р.,От программирующих программ к системам программирования // Становление Новосибирской школы программирования. Мозаика воспоминаний. — Новосибирск: Институт систем информатики им. А.П. Ершова СО РАН. — 2001. — С. 18-27.
- Ершов, А. П. Программирование — вторая грамотность// Избранные труды. Новосибирск, 1994.
Примечания
[1] Группе лучших физиков и математиков показали видео, в котором неизвестный изобретатель демонстрировал действие антигравитационного аппарата. В ходе эксперимента изобретатель погиб. Никаких записей после себя он не оставил и перед учеными была поставлена задача повторить его достижение.
Через некоторое время решение было найдено, принцип антигравитации был открыт. После этого, ученым сообщили, что видео с экспериментом было фальшивкой. Уверенность в том, что решение существует, помогла решить проблему.
[2] Корпоративные версии средств разработки не отличаются принципиально от личных. Корпоративные всего лишь добавляют инструменты, не изменяя основу.
[3] Почему я говорю о приоритетах, а не о требованиях? Большинство (общих) требований к программам одинаковы, а вот важность (приоритеты) требований различается для программ разных уровней.
[4] Application Binary Interface
[5] Скрипт должен переводиться во внутреннее (платформенно-независимое) представление (например, LLVM IR), и после этого переводится в код нужной платформы. Тем самым на каждой платформе будет исполняться нативный код скрипта и такой же код используемых компонент.
[6] Стандартизация компонентов – это большая тема. Частично эта тема раскрыта в моем блоге (http://алексейнедоря.рф). Упомяну лишь о том, что компоненты могут быть простые, например, каждая тригонометрическая функции – это маленькая компонента, так и составные компоненты – например, текстовый редактор.
Постоянная ссылка
Постоянная ссылка
Очень много сказанного относится к IoT как оно должно быть.
Нет никаких универсальных и главное расширяемых форматов обмена сообщениями, обработка которых могла бы работать на устройствах не сложнее ARM Cortex-M0 / 20K SRAM.
Для работы таких устройств через LLVM необходим достаточно мощный шлюз с набором кросс-backendов LLVM для всех типов используемых мироконтроллеров. В IoT предусмотрен уровень EDGE, но наличие мощного шлюза при этом становится критически обязательным.
Байт-код универсальнее, т.к. его интерпретацию можно реализовать на МК пожирнее (STM32F3/F4 или F0/F1 с внешней шиной памяти) без внешних сервисов, on-host компиляция из LLVM IR невозможна.
Каждый производитель лепит модели, а то и прошивки, каждая версия из которых не совместима с предыдущими. Железо работает только с сервисом вендора.
Программирование таких распределенных гетерогенных (разнородных) систем возможно только в акторной модели, на асинхронной и негарантированной передаче сообщений. Каждое сообщение должно иметь формат, который устройство или сервис может разобрать и при необходимости обновить свой парсер автоматически при введении новых понятий.
Постоянная ссылка
Впрочем, пакет cross-LLVM уже можно хостить на телефоне пользователя, и он сможет обслуживать все устройства, которые этому пользователю принадлежат.
Постоянная ссылка
Да можно. Примерно об этом стратегия 1+8+N: https://www.gizmochina.com/2019/06/28/huawei-18n-strategy-5g-era/