пятница, 28 ноября 2008 г.

Пояснения

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

  1. Весь рассказ про историю говорит о том, что развитие средств кодогенерации идет в неверном направлении уже 20-30 лет. Программисты упустили из виду сущность того, чем они занимаются.
  2. Всё, что я сказал про ООП говорит о том, что влияние ООП на языки программирования преувеличено. Термин ООП - не соответствует реальности. Существует только объектно-ориентированный дизайн.
  3. Обзор некоторых особенностей языков показывает, что не всё так плохо. Развитие средств кодогенерации наблюдается, но в темпах значительно ниже возможных.
  4. Вероятно причина всему - сильная коммерциализация явления "программирование", а также дурное влияние методик дизайна и архитектуры на программистов (бедные).
  5. Тут можно почитать схожие мысли. Идея в том, что вся эволюция в языках программирования последние 20-30 лет суетится вокруг именно средств дизайна и архитектуры. Средства же кодогенерации почти не развиваются.
  6. При осознании всего процесса эволюции и со взглядом на всё это снаружи, становится понятно, что не так и что можно поделать. Например: переписать препроцессор языка Си, переосмыслить вид представления поддержки объектно-ориентированного дизайна в языках.
  7. Дизайн/архитектура ПО и собственно программирование это разные процессы, хотя часто и происходят одновременно, параллельно. Оба процесса равнозначно важны и развивать нужно их методику в равной степени.
  8. Полезно остановиться и освободится от жизненной рутины и взглянуть на всё, что ты делаешь вне процесса/системы. Такие моменты дают бесценное понимание некоторых вещей. :-)

среда, 26 ноября 2008 г.

Эволюция языков программирования

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

Заранее предупреждаю, я не имею полного набора фактов относительно истории развития языков программирования. Я не сведущ относительного того кто, когда и главное каких недалал поделок, называя их "языками программирования" и что уж скрывать, меня это не особо интересует. На данный момент времени понятно, что существует ряд популярных языков программирования в которых миллионы мух (вы уж простите, что я так о программистах, конечно же вы самые умные и интеллектуальные и <вставьте ваш комплимент>, но это звучит символично) что-то эдакое нашли. И опираясь на то, что я вижу сейчас и то, что было когда-то (немножко-то истории я всё же знаю), я сделаю свои выводы. И пожалуйста, не подумайте, что я ярый приверженец какой-то одной идеи будь то ООП или функциональщина. Я скорее пытаюсь не вдаваясь в термины/понятия парадигм поделиться своим представлением относительно явления "программирование".

Дженерейшн намба уан. Или его отсутствие.

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

Поколение некст или намба ту.

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

Я немного отойду от главной темы и немного углублюсь в абстрактное понимание процесса программирования. Что это такое по сути? Мы пишем программы на любимых языках и формошлепим иногда, рисуем какие-то GUI элементы, подготавливаем какие-то наборы данных. По сути я называю этот процесс одним словом - кодогенерация. Т.е. если мы пишем в Си статический массив - это кодогенерация, если мы пишем функцию для рекурсивной обработки сложной древовидной структуры - это кодогенерация. Ключевая фишка тут это то, что данные и код это одно и то же. Рисуем картинку для программы - кодогенерация. Да, я понимаю звучит не важно, просто запомните пожалуйста, что я называю это так. Когда нужно будет различить, что я имею ввиду, я буду упоминать кодогенерацию данных или кодогенерацию исполняемого кода :)

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

Третье поколение. Революция.

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

Звездец.

Пожалуй в конце 80ых и в начале 90ых, такое устройство как компьютер начинает получать известность и массовость. В сущность вливаются реклама и деньги. Всё подвергается жуткой коммерциализации и прочим прелестям от лукавого. Одним словом - неприятно. Но это не самое страшное, появляются некоторые чёрные концепции типа ООП, АОП, которые намеренно отступают от главной сути языков программирования и дают какие-то свои ничем не подкрепленные понятия. Теперь язык программирования не является средством кодогенерации, а становится вдруг средством выражения идей человека в первую очередь, хотя я считаю это в корне не верно. Нельзя избавится от того факта, что программирование это процесс ориентированный на железо. Т.е. Hardware-oriented programming. В ООП появляются какие-то непонятно чем навеенные понятия: наследование, класс, инкапсуляция, объект, полиморфизм. И они якобы имеют какие-то отношение к реальности человеческой или машинной.  Иными словами настал звездец. А теперь я предлагаю вам немного передохнуть, очистить голову от всяких бранных мыслей и продолжить чтение. Далее я раскрою тему того, что я имею ввиду.

Что не так с нынешним путем. Или его отсутствие ;-)

Стоит заметить, что под ООП я имею ввиду все эти новомодные фичи с наследованием, инкапсуляцией, абстракцией и полиморфизмом. Ими в полной мере или частично страдают такие языки как Java, C#, C++, Python, D, Ruby, PHP, Delphi (вероятней всего ваш основной язык программирования в этом списке). А теперь давайте по порядку посмотрим, что же из себя представляют эти фичи.

Абстракцию можно даже не рассматривать, т.к. программирование это такая история про абстракцию. Нет программирования без абстракции. И почему её приписывают к ООП?

Наследование - все помнят типичный пример Shape, Rectangle, Circle. Идея в том, что какие-то структуры данных строятся на основе уже существующих. Каждая Shape имеет площадь, но скажем Rectangle имеет в дополнение к этому такой параметр как отношение сторон, а Circle имеет радиус. Я считаю, что наследование хоть и имеет какую-то логику, но реальная её польза ощутима при использовании понятия полиморфизм. Иначе же это простая композиция данных и/или алгоритмов, т.е. кода. Вообще я бы сказал, что наследование это и есть способ реализации идеи полиморфизма. Помнится в злой науке невнятные понятия частое явление. Есть о чём задуматься? Так, обратно к теме. Пусть наследование и полиморфизм представляют один набор тесно взаимосвязанных фич, на практике же всё это представлено в виде неявного использования таблицы виртуальных функций/методов (vtbl). Т.е. такой простой прием кодогенерации встраивают в язык по какой-то причине и позволяют работать с ним на уровне синтаксиса. Оно и понятно, никому не охото писать myobject->vtbl[METHOD_ID](args). Но фактический в такой фиче нет ничего нового и по сути своей она ничем не отличается от простого использования указателей на функции. Возможно вид несколько иной, пусть и более удобный. Но однозначно фича не стоит того, чтобы о ней писали трактаты и на площадях выкрикивали: "Everything is an object!".

Инкапсуляция - что-то там про сокрытие данных и выставление на показ только интерфейса для пользователя-дебила. Ну хорошо, пусть это средство самоконтроля себя от своих же ошибок. Также можно отнести к средству какого-никакого дизайна/архетектуры, но сомнительно. #define private public - это реальность, а не сказка. Понятно дело, что никакого кода не генерирует. В С++ если использовать класс на прямую, не по указателю, то компилятору обязательно нужно знать все детали его реализации, для определения размера. Так что смысла в кодогенерации нет никакого. Получаем бесплатную порцию жучков мозгоедов.

Про полиморфизм уже было сказано. Подведу я лучше итог по ООП. Однозначно ООП это инструмент разработки дизайна/архитектуры программ и к языку вообще никакого отношения не имеет. Тут правы те, кто знают, что нельзя называть язык объектно-ориентированным, язык может поддерживать средства для работы с объектно-ориентированным дизайном, но не факт, что они вообще нужны.

Куда идти?

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

Более строгая система типов - помимо более строгого контроля ошибок программистов-идиотов, скорее всего несет смысл в виде возможности генерировать более оптимально код. Непосредственно фича кодогенерации, как и система типов вообще.

Шаблоны - неосознанная попытка заменить препроцессор на типизированный препроцессор с возможностями метапрограммирования. Шаблоны сильно полезны в области generic программирования. Непосредственный инструмент кодогенерации. Более совершенная система подобного рода должна рано или поздно заменить устаревший препроцессор. Можно посмотреть в сторону языка D, где препроцессора уже нет и сам язык выполняет его роль на стадии компиляции. Появились даже AST макросы, позволяющие работать с AST напрямую. Однозначно правильная идея развития кодогенерации как данных так и исполняемого кода.

Перегрузка операторов - средством генерации вряд-ли назовешь, скорее синтаксический сахар, но тем не менее польза есть. Просто удобно. А кто не понимает - пусть пишут на Lisp.

Конструкторы, деструкторы - опять инструмент кодогенерации, причем очень простой. Однозначно имеет определенную пользу, т.к. расширяет возможности структуризации кода путем взаимодействия с понятием scope.

Есть в С++ ещё и плохие штуки. Например сломанный static. В Си изначально keyword static является исключительно инструментом кодогенерации данных. В С++ он приобрел невнятное состояние из-за возможности запускать исполняемый код. Это от части проблема того, что в языке нет нормальных инструментов метапрограммирования, от части вероятно недальнозоркость авторов языка. Вроде бы в С++0x должны появиться какие-то фичи связанные с этим в виде constexpr. Посмотрим.

Теперь о GUI. Не поверите как текущие GUI системы себя инициализируют! Вместо того, чтобы программа напрямую содержала snapshot GUI иерархии виджетов и после загрузки программы память сразу начинала с ним работать, в GUI программах содержится код создания этой самой иерархии, который вызывается ровно один раз и является абсолютно не нужным баластом с точки зрения логики. Всё, что можно делать вне runtime'а, должно делаться именно там. Проблема в том, что в современных языках недостаточно выразительных средств кодогенерации данных. Нельзя описать в разумном виде сложную иерархию объектов и использовать её. Языки имеют средство описания массивов например, но в приличном виде невозможно описать скажем red-black tree. Почему? А потому что мыслим в другом направлении. Я однозначно за развитие таких средств, пусть они и будут в виде техник метапрограммирования. Конечно, ничего не мешает мне написать генератор данных и встроить их в Си код, но такие средства должны уметь взаимодействовать сразу с языком программирования. Подведя итоги. В GUI вообще не должно быть кода инициализации самих GUI виджетов. Конечно всегда есть исключения, которые имеют под собой вполне понятное обоснование. Если программа загружает конфиг и в зависимости от значений полученных оттуда что-то меняет в виджетах, это понятно. Но когда программа при каждом запуске запускает один и тот же код, который генерирует в памяти один и тот же набор данных при любых условиях и более того, этот набор данных меньше или равен по размеру самому кода(!), это лишний код и он требует удаления. Поверьте, такой код не редкость!

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

понедельник, 24 ноября 2008 г.

Насекомые

Сегодня немного необычный пост... о насекомых. А именно речь пойдет о Cimex lectularius, он же Постельный клоп.

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

Могут без еды существовать по пол года, самки откладывают в день до 12 яиц. Жрут кровь по ночам, укус не чувствуется, попадает гад не с первого раза куда надо, поэтому оставляет 3-4 точки, чешутся.

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

А ещё режим сна вроде вернул в нормальное русло. Надеюсь завтра всё встанет на свои места.

Мораль: во всём плохом и мерзком, всегда есть что-то хорошее

P.S. Не завидую тем, кто столкнется с клопами.

воскресенье, 23 ноября 2008 г.

Блогонеприязнь

Я столько раз начинал блог, что уже сбился со счету. Не знаю почему я их удаляю каждый раз. Видимо так надо зачем-то кому-то. Но на этот раз, я в самом деле даю публично обещание не удалять его и пусть даже он будет пустовать, как некий nsf.blogspot.com (прямо говорит мне - место занято, кыш), но блог будет жить!