Очередное философское отступление
Начав описывать Вир, я вынужден говорить о частностях, так как Вир – это вполне конкретная среда разработки со своими конкретными плюсами и минусами.
При этом я хочу, чтобы за деревьями лес был все же виден, хотя внимание деревьям приходится уделять.
Почему главное для меня – это лес? Потому что я пытаюсь все время говорить о программировании в большом, а не программировании в малом.
Если мы посмотрим на историю, то мы постепенно переходили от программирования в малом к программированию больших систем. Начало — программирование с помощью коммутации кабелей (ENIAC) и дальше переходы
- к возможности выполнять программы в памяти
- к подпрограммам
- к библиотекам функций
- к структурному программированию
- к модульному программированию
- к ООП
Понятно, что историческое развитие шло нелинейно (см. например, модульное и ООП), и я сильно упрощаю картинку. Тем не менее, в целом она верна и, на мой взгляд, верны следующие утверждения:
- Структурное программирование, типы данных и библиотеки функций позволили нам достаточно адекватно программировать в малом.
- Модульное программирование, ООП и фреймворки – в какой-то степени упорядочили программирование в среднем.
- Для программирования в большом, на мой взгляд, пока мало что сделано.
Если есть сомнения, готов обосновать эти утверждения.
Еще раз повторю, что меня интересует программирование в большом: от распределенных приложений до распределенных много под-системных систем, работающих в неоднородной вычислительной среде.
У меня есть свои предпочтения (и наоборот) в языках программирования, но я избегаю писать об этом. На мой взгляд, компоненты должны разрабатываться на том языке, на котором удобно разрабатывать конкретную компоненту: «Пусть расцветает сто цветов!»
Важно не то, на каком языке и каким образом разработана компонента, важно другое – можно ли использовать компоненту более одного раза, можем ли мы накапливать качество, двигаться к упрощению и управляемости процессом разработки программ и к повышению качества/надежности программ?
Я убежден в том, что основой программирования в большом является сборка – конструирование программной системы из готовых компонент.
Собственно, так оно есть по факту, хотя мы почему-то предпочитаем это не видеть.
Пусть у нас есть приложение, которое сделано обычным образом. Для определенности рассмотрим программу на компилируемом языке.
Если мы попытаемся увидеть картинку целиком, то она будет примерно такая:
Само приложение собрано из специализированных исходных текстов, написанных для этого приложения, и из текстов более универсальных, и из статических библиотек. Полученный монолит не может работать сам по себе, он обязательно использует динамические библиотеки, частью стандартизованные, например, CURL, шрифтовые библиотеки, а частью более специализированные, например, библиотеки предметной области.
Естественно, что каждая из DLL тоже собрана из частей, более того, какие-то исходные тексты могут быть использованы для разных «больших» компонент и многократно присутствовать в коде.
И все это «хозяйство» использует OS API, которое в свою очередь, использует программные сервисы и оборудование.
Если мы возьмем приложение на скриптовом языке, то это только увеличит количество слоев компонент.
Что я хочу этим примером сказать?
Обычное или в терминологии Ершова «синтезирующее программирование» всегда используется на нижнем и среднем уровне, на верхнем уровне используется сборочное программирование (не буду говорить всегда используется, мне не важно, всегда или нет, достаточно того, что используется почти всегда).
Если мы принимаем этот очевидный факт, то на лицо психологическая проблема, мы используем сборочное программирование, но в упор его не видим и не развиваем. Как поет Dimie Cat:
Is there a problem I don’t wanna face
Or is it simply what we call «happiness»?
Пока мы не видим проблему, мы счастливы (может быть), но программы пишутся долго, мы выходим за рамки бюджета, не умеем планировать, программы работают as is и т.д.
Не пора ли перестать есть кактус и задуматься?
Собственно, Вир – есть эксперимент по сборочному программированию, эксперимент достаточно суровый, в каком-то смысле экстремальный, так как в Вире я пытался максимально использовать сборочное программирование на всех уровнях разработки.
На мой взгляд, это единственный разумный способ продвинутся в сборочном программировании, так как все не-экстремальные эксперименты, типа DCOM, провались. И провалились они из-за того, IMHO, что экспериментаторы пытались скрестить всех ужей со всеми ежами, и, заодно, со всеми кактусами.
Для того, чтобы понять суть сборочного программирования, нужен чистый эксперимент. Вир и есть такой эксперимент.
Как использовать результаты проведенного эксперимента?
Я никоим образом не предлагаю отказаться от всего, что уже сделано в программировании. Более того, в Вире я постоянно использую DLL, библиотеки, объектные файлы, ассемблерные вставки, естественно OS API и т.д. Чистота эксперимента здесь обеспечивается тем, что любые «внешние» части для использования заворачиваются в «обертку», и становятся стандартными компонентами для сборки.
Еще раз повторю – не важно, что внутри (если компонента соответствует своей спецификации), важно, чтобы компоненту можно было подключить.
На мой взгляд, главный результат эксперимента с Виром – это выделение способов подключения, а эти способы различны для компонент разных уровней. И, тогда, второй или, скорее, первый по значимости результат – это раскладка компонент на уровни.
Применение результатов может быть разным. На одном полюсе стоит разработка Вира-2. На другом, использование понимания уровней компонент/способов подключения для работы с существующими системами.
Например, берем какую-нибудь разлапистую программную систему и пытаемся упорядочить её, выделяя, стандартизируя и обертывая компоненты. Очевидно, что для этого придется делать некий мета-сборочный инструмент и возможность строгой проверки (статической или динамической) интерфейсов и протоколов.
Говоря о проверке совсем коротко, надо делать что-то вроде языково-независимых симфайлов. Симфайлы использовались в модульных языках программирования для контроля совместимости модулей. Забавно, что я писал на близкую тему почти 30 лет назад (в 1987 году): «Симфайлы как интерфейс операционной системы».
И последнее, еще раз замечу, что существенной помехой в переходе на сборочное программирование (более значимой, пожалуй, является только то, что большинство программистов не хочет думать? либо не могут себе этого позволить в нынешней реальности) является то, что для внедрения сборочного программирования нужно затратить достаточно много ресурсов и времени. Выделение компонент и стандартизация дает положительные итоги (ускорение, упрощение разработки), но не сразу, а это вступает в противоречие с любимым нынче time-to-market.
Для перехода к сборочному (производственному) программированию нужен «заказчик» у которого:
- Есть стратегические цели с горизонтом планирования в десятки лет минимум
- И достаточно денег, чтобы подождать отдачи несколько лет
Постоянная ссылка