суббота, 28 марта 2009 г.

Жизнь за окном :)

Когда я начал этот блог, я задумался над тем, о чем же можно будет здесь писать. Одну из рубрик я хотел обозвать “Жизнь за окном” – планировалось описывать в ней разные забавные или примечательные сценки из жизни, увиденные мельком из окна или просто на улице.

Одной из подобных сценок могла бы стать такая: как-то идя из дома на остановку я проходил мимо местного питейного заведения под названием “Лавашня”. Время в районе 11-ти часов утра, будний день. Рядом с рюмочной стоит компашка из пяти-шести уже основательно поддатых мужичков (разного возраста, от 20 до 50 лет на вид). И обсуждают они… Первую космическую скорость. Т.е. на полном серьезе, перекрикивая друг друга, они спорят о том, с какой скоростью должно двигаться тело для того, чтобы выйти на орбиту Земли.

В принципе, ситуация вовсе не забавная. И поводов для гордости за то, что мол у нас даже алкаши настолько грамотные, что могут в подпитии спорить на тему физики и космонавтики, я не вижу. Однако, я сейчас не о том.

А о том, что, как мне кажется, большинство нормальных, не подверженных алкогольной зависимости, и более-менее образованных людей не захотели бы отождествлять себя с этой компашкой. Мол, мы-то из другого теста. Ага :)

Вчера после работы наш небольшой “клуб любителей винишка” в составе четырех человек устроил дегустацию аргентинских и южноафриканских белых вин (белорусского разлива). За свою цену – 8900BYR (108RUR или $3) – очень неплохие вина оказались, кстати. Но самое удивительное, это темы, которые мы обсуждали после второй бутылки :) Например, как и из чего возникает нефть, что изучает органическая химия (и такие частные вопросы, имеет ли алмаз отношение к органической химии, и что такое минералы), какие типы ускорителей элементарных частиц строят или собираются построить, где будет построена первая термоядерная электростанция и чем это грозит… Я думаю, что не нужно лишний раз упоминать, что никто из нас не был силен ни в химии, ни в физике :)

Не знаю почему, но вспоминается фраза из классиков: “Над кем смеетесь? Над собой смеетесь!” :)

PS. Кстати оказалось, что известная байка о тупых американцах из NASA, которые потратили $1M на изобретение ручки для космонавтов, тогда как умные русские писали простыми карандашами, очень сильно не соответствует действительности :)

четверг, 26 марта 2009 г.

Выпустил Mxx_ru 1.4.10

Благодаря настойчивости Тимура Найрулина в Mxx_ru добавлена поддержка специального типа динамических библиотек под Mac OS -- bundle. Новая версия уже доступна на RubyForge.

Так же удалось в конце-концов описать в документации изменения, который были внесены в Mxx_ru 1.4.8-1.4.10.

Приятно, что в последнее время счетчики загрузки Mxx_ru на RubyForge постоянно тикают. Так, на днях количество загрузок через RubyGems перешагнуло через очередную сотню и на сегодня составляет 703. Может и до 1000 со временем доберемся?! ;)

Крутая бага в SObjectizer

Вчера выловил в SObjectizer серьезную ошибку, которая сидела в нем, наверное с незапамятных времен. Проявлялась она в ситуации, когда агент завершал обработку своего собственного сообщения, а в этот момент его на другой нити дерегистрировали. Суть в том, что после выхода из обработчика события для данной заявки уменьшались счетчики ссылок на саму заявку, на экземпляр сообщения и на агента. И вот, когда все счетчики ссылок обнулялись и оставалось только вызвать функцию уничтожения объекта-сообщения, как управление передавалось другой нити. Другая нить дерегистрировала агента и, поскольку ссылок на этого агента не оставалось, то агент и все его SObjectizer-овские внутренности уничтожались. Потом управление передавалось обратно первой нити, которая должна была уничтожить объект-сообщение. Но это уничтожение выполнялось с помощью вспомогательного объекта с описанием сообщения агента. А этот объект уже оказывался разрушенным вместе с самим агентом. Поэтому происходило обращение к повисшему указателю со вполне ожидаемыми последствиями.

Ошибки в многопоточных программах начинают напоминать мне важный закон, который был выведен физиками-экспериментаторами:

Все, что может сломаться, сломается обязательно. Все, что не может сломаться, сломается тоже.

Так и здесь. Вероятность возникновения такой последовательности событий, да еще в тот мизерный зазор по времени между обнулением счетчика ссылок и вызовом деструктора объекта, ну очень мала (как мне кажется). И тем, не менее, она воплотилась. Да еще в весьма важном проекте, который работает в режиме 24x7 под постоянно возрастающей нагрузкой.

PS. Я когда-то выдвигал в качестве недостатка языка C++ отсутствие в нем stack trace “из коробки”. Чтобы при сбое программы сама стандартная библиотека C++ выдавала точное место сбоя. Самое смешное, что в данном случае stack trace совершенно не помогал (я его получил таки с помощью StackWalker-а). Поскольку по stack trace не было ясно, что именно провоцировало сбой – долгое время я вообще грешил, что данная ошибка “наведенная”, что сбой в этом месте является порчей памяти где-то в прикладной логике.

среда, 25 марта 2009 г.

Отлично сказано! Так почему же самые продвинутые языки не попадают в мейнстрим?

В спорах с фанатичными функциональщиками на просторах профессиональных форумах постоянно сталкиваешься с непробиваемой уверенностью в том, что будущее за языками вроде Haskell. И если ты этого не понимаешь, значит просто пока не дорос. Но вот замечательное объяснение причин того, что экспериментальные, академические языки не находят широкого применения. Объяснение, которое дал Erick Meijer, один из отцов-основателей Haskell-а, теперь работающий в Microsoft над .NET-языками (Visual Basic и C#):

Since lambda expressions, meta-programming, monads, and comprehensions are abstract mathematical concepts, it might seem remarkable that they show up in contemporary languages such as C# 3.0, Visual Basic 9, and Java, as well as in more experimental hybrid functional/OO languages such as Fortress, Scala, Fortress, and F#. It is especially remarkable since, in the Haskell community, monads are still considered as one of the most advanced and difficult features to master.

The explanation for this apparent contradiction is that the successful programming languages understand developer inertia and obey the Change Function. They offer a solution to deep developer pain with a very low adoption threshold. The reason why most research languages die a quick death, and successful languages a slow one, is because they do not realize that users are in charge. Instead they promise miracles of improved productivity and automatic correctness; as well the fact that in the future their implementations will be fast enough thanks to better and more advanced compiler optimizations [7]. Sometimes a niche language targets a severe enough crisis, one that is larger than the perceived pain of adoption, and hence it gathers enough velocity to escape death. A good example of a language in this category is Erlang. Hopefully, Haskell will escape death as well.

Источник: Confessions Of A Used Programming Language Salesman (ссылка найдена здесь).


PS. А я последние пару месяцев ломал голову, как бы выкроить время и проштудировать Real World Haskell. Теперь с чистой совестью откажусь от этой затеи. Если время найдется, то лучше я плотнее познакомлюсь со Scala или C# 3.0.

PPS. В своей статье Meijer затрагивает проблему контрактов:

What we really need is a dial that we can turn from no static typing on the one extreme, to traditional static typing in the middle, to full contracts and invariants [15, 9, 13] on the other extreme. While we believe that pre- and post-conditions are ready for promotion from the research world to the real world, we feel that object invariants are maybe not yet ready for prime time.

Очень странно. И пред-, и постусловия, и инварианты объектов уже более двадцати лет активно используются в Eiffel-е. И, кстати говоря, являются еще одной причиной хорошей читабельности Eiffel-евских программ. А тут об Eiffel-е не слова. Или Meijer говорит о каких-то других контрактах или же “специалист подобен флюсу и полнота его одностороння”.

PPPS. По ходу чтения статьи (особенно в ее начале) очень удивлялся тому, сколько много всего автор со товарищи написали на Haskell-е (тут тебе и HaskellDB, и Haskell Server Page, и поддержка DHTML, и поддержка COM), да еще и статей настрочили по каждой разработке. В чем же причина такой производительности: значительное превосходство языка Haskell над всеми остальными (особенно в руках его создателей), работа по 10-12 часов в день без выходных или же сделанные разработки не выходили за рамки работающих прототипов? Мне лично кажется, что последнее.

вторник, 24 марта 2009 г.

Type inference как средство криптографии :)

Сейчас в mainstream языки программирования добавляют возможность вывода типов (type inference). Т.е., если раньше в C++ нужно было писать так:

my_class * o = new my_class(...);

то теперь можно будет указывать имя типа переменной всего лишь один раз:

auto o = new my_class(...);

Возможность вывода типов, конечно, штука замечательная. Более того, в некоторых случаях просто совершенно необходимая (например, в C#3.0 вывод типов в сочетании с анонимными типами сделали возможным существование LINQ). Но, на мой взгляд, повсеместное использование вывода типов сделает программы более сложными в понимании.

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

А вот совсем свежий пример на эту тему. z00n поделился ссылочкой на небольшое сравнение производительности разных языков программирования на задаче MINILIGHT: a minimal global illumination renderer. Реализация тестовой программы на языке Scala имеет более чем вдвое меньший объем, чем C++ вариант. Но является ли Scala-вариант более читабельным? Вот фрагмент, на котором я сразу же споткнулся:

   def this( eyePosition:Vector3f, items:Array[Triangle] ) = this(
      {
         // make overall bound
         val bound =
         {
            // accommodate all items, and eye position (makes tracing algorithm
            // simpler)
            val rectBound = items.foldLeft( (eyePosition, eyePosition) )(
               (rb, item) =>
               {
                  // accommodate item
                  val ib = item.bound
                  ( (rb._1 clampedMax ib._1), (rb._2 clampedMin ib._2) )
               } )
            // make cubical
            val cube = Vector3f( (rectBound._2 - rectBound._1).fold(Math.max) )
            ( rectBound._1, (rectBound._2 clampedMin (rectBound._1 + cube)) )
         }

         // convert to array
         Array.range(0,6).map( i => (if(i < 3) bound._1 else bound._2)(i % 3) )

      // delegate to main (recursive) constructor
      }, items, 0 )

Представте себе, что у вас под рукой нет IDE, а только листинг программы (как раз то, что мы имеем, заглянув на страницу minilight). Какие типы имеют bound, rectBound, ib? Заметили ли вы, что данный конструктор на самом деле является вызовом еще одного конструктора, а все эти вычисления – всего лишь блок кода, который вычисляет значение первого параметра для второго конструктора?

Или вот еще интересный вопрос по данному фрагменту: здесь item.bound и последующее выражение в скобках – это два разный действия или же вызов функции bound:

                  // accommodate item
                  val ib = item.bound
                  ( (rb._1 clampedMax ib._1), (rb._2 clampedMin ib._2) )

Наверное, это все-таки два разных действия. Но понять это можно только присмотревшись внимательно, и увидев во второй строке использование ib внутри выражения.

В общем, с некоторым напряжением жду перехода на C++0x, в котором вывод типов уже будет реализован. Боюсь, вывод типов будет еще одной штукой в C++, требующей крайне осторожного применения.

В заключение. Самый толковый подход к декларации типов я пока видел в Eiffel. Там устранена главная проблема – дублирование имени типа при инициализации переменных. Т.е. если в C++ (Java) мы вынуждены были писать:

my_class * o = new my_class(...);

то в Eiffel это записывалось бы как:

local
  o: MY_CLASS
do
  o.make (...)

Т.е. есть явное указание типа переменной, но нет дублирования имени типа при ее инициализации. Не в последнюю очередь поэтому программы на Eiffel-е были самыми читабельными из тех, которые мне приходилось видеть (но и одними из самых объемных по количеству строк кода).

понедельник, 23 марта 2009 г.

Перечитал “Путь камикадзе”

Последние две недели перечитывал “Путь камикадзе” (Death March) Эдварда Йордана. Впечатления неоднозначные.

Первые несколько глав, в которых описываются типы безнадежных проектов, причины их возникновения и причины, толкающих разработчиков к участию в подобных проектах, читаются с удовольствием и на одном дыхании. Я лучше стал понимать, почему же я сам неоднократно ввязывался в безнадежные проекты. Менталитет морского корпуса и желание забежать на Эверест босиком играют тут не последнюю роль :)

Зато оставшаяся часть книги оставляет одно главное впечатление: мне, как разработчику, читать ее не интересно. Большая часть материала предназначена менеджерам разного уровня. Может быть поэтому, по ходу чтения возникает впечатление о том, что пока читаешь, все вроде правильно, логично и понятно. Зато стоит оторваться от книги, как сразу задаешься вопросом: “А о чем, собственно, шла речь?” :)

В первый раз читал “Путь камикадзе” году эдак в 2002-м. Сейчас по ходу перечитывания вспоминались только первые главы. Так что, похоже, тогда книга произвела на меня похожие впечатления.

Тем не менее, пара моментов из второй половины книги все-таки запомнилась:

- в безнадежном проекте менеджер отвечает за то, чтобы разработчика не заботили бытовые проблемы. Мол, если у программиста заболел ребенок, то хороший менеджер сам позаботиться о том, чтобы доставить ребенка и его родителей на прием к доктору. Очень важный момент, имхо. И, наверное, показатель того, что я вряд ли когда-нибудь стану хорошим менеджером. Ведь такое внимание к людям должно быть врожденным;

- технология, особенно новая, еще не опробованная, не способна вытянуть безнадежный проект. Нужно запомнить это. Поскольку меня иногда бросает в крайность – сменить инструментарий для того, чтобы избавиться от проблем, донимающих меня в данный момент. Например, заменить библиотеку ACE на что-нибудь другое. Или перейти с C++ на Scala или D. Интересен и другой вывод: навязанный проектной команде новый или неподходящий инструмент может стать причиной провала. Однако, во многих случаях, инструментарий не может стать причиной неудачи проекта. Поэтому к высказываниям вида “Мы провалили проект потому, что использовали язык X и библиотеку Y” нужно относиться очень скептически.

Если кто-то еще не читал “Путь камикадзе” – прочтите. Книга затрагивает множество вопросов. Наверняка какие-то из них окажутся вам интересными. Тем более, что она совсем небольшая по объему.

И мой маленький совет: в бумажном варианте читать приятнее, чем в электронном.

воскресенье, 22 марта 2009 г.

Велосипедостроители, блин!

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

Раньше в сливных бачках использовались очень простые механизмы – сопло, из которого подается вода; поршень с резиновой накладкой, для закрывания сопла; рычаг с поплавком. Вода, заполняя бачок, поднимает поплавок. Поплавок приводит в действие рычаг. Рычаг прижимает поршень к соплу и все! Если со временем вода продолжает поступать даже при прижатом поршне, значит причин может быть всего две:

- ограничено движение поплавка и он не может достаточно сильно воздействовать на рычаг;

- мелкие частички ржавчины или кусочков старых труб, которые поступают из сопла, повредили резиновую накладку, и она не обеспечивает герметичного закрывания сопла.

Все просто, понятно и устраняется в течении нескольких минут.

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

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

Блин, товарищи инженеры-конструкторы, запомните, пожалуйста: принцип KISS применим не только к программному обеспечению!

Усталость от работы

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

Наиболее полно термин “усталость” подходит к написанию документации. Здесь после рабочего дня и голова пустая, и глаза болят, и поясницу ломит. Да и вообще физическое состояние такое, как будто мешки с картошкой таскал. Вот это действительно усталость в традиционном смысле слова – добираешься домой и единственное желание упасть и не вставать больше :)

Кодирование вызывает похожий эффект. Но, к счастью, не настолько сильный. И психологическая, и физическая усталость не такая сильная, как при документировании. Не знаю, чем это вызвано. Может быть тем, что при кодировании есть гораздо большая положительная отдача: написал кусок программы, покрыл ее тестами, убедился, что все работает и… И хорошо! Душа поет! :) Может быть дело еще и в том, что при кодировании редко возникают ситуации, когда ты работаешь “отсюда и до обеда”, когда ставишь себе цель написать столько-то разделов такой-то главы за сегодняшний день. И ближе к концу рабочего дня начинаешь понимать, что нужно выдавить из себя еще вот эту страничку, а затем еще одну, а затем и еще одну… Может быть, дело еще и в том, что кодированием занимаешься находясь “на пике формы”, когда еще не было накопления усталости от всего, что было раньше. А вот документирование – это уже самый конец проекта, когда огромное количество сил потрачено на проектирование, экспериментирование, кодирование, тестирование, опытную эксплуатацию и пр. И после всего этого – за сегодняшний день нужно написать 20 страниц документации… пристрелите меня… ;) В общем, резюмируя: от кодирования устаешь. И физически устаешь, и психологически. Но не очень сильно.

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

Но вот усталость от экспериментирования и от отладки программ уже другого рода. Не столько физическая, сколько психологическая. Насколько я могу вспомнить, я редко сильно физически устаю, когда приходится выискивать баги в программах. Может быть потому, что отладка заставляет больше двигаться – вскакивать, мерить шагами коридор, грозить кому-то кулаком, стучать в сердцах по столу… :) Но вот психологическая усталость от отладки серьезно отличается от таковой при кодировании/документировании. Она гораздо сильнее. Может быть за счет более сильного нервного напряжения. Еще хорошо, когда отладка завершается успешно и злобный баг, на который было убито несколько мучительных часов тестирования, таки найден и устранен. Тогда просто чувствуешь себя очень усталым победителем. Но вот если баг не найден… Вот это действительно хреново. Поскольку мысли о его поиске не покидают тебя. Даже не смотря на попытки переключения на какую-то другую тему. Меня в такие моменты иногда одолевает очень серьезная рассеянность. Несколько раз в магазине я забывал забирать сдачу или взять с собой купленные продукты. И, что интересно, я не думал в эти моменты о программе. Просто вообще ни о чем не думал. Было состояние какого-то опустошения.

Состояние, надо сказать, неприятное. Самое плохое, что это очень асоциальное состояние, провоцирующее конфликты. Находясь в нем невозможно обсуждать шторы или пытаться играть в выдуманную ребенком роль. Просто потому, что ты отстранен от всего этого, но ты понимаешь, что нельзя вот так относится к своим близким. Но ты так же понимаешь, что и переломить себя не можешь. Еще хуже, когда такое состояние прострации внезапно прерывается какой-то догадкой. Как шило в задницу. Которое заставляет тебя бросить все и если не уткнуться в компьютер проверять ее, то хотя бы записать на листочке бумаге. Ты срываешься с места и заседаешь на полчаса-час за письменным столом, чтобы краем уха услышать в другой комнате: “Папа опять не может поиграть с ребенком”…

Да, а еще бывает, что просыпаешься среди ночи из-за того, что во сне тебе приснилось решение проблемы. У меня такое однажды было. В принципе, довольно жуткое это дело…

С тяжестью психологической усталости от отладки может сравниться разве что усталость от этапа мозгового штурма. У меня это вообще самая неприятная стадия работы над проектом, хотя есть люди, которые именно от этого получают наибольший кайф. Очень тяжело, когда в проекте все размыто: цели четко не определены, пути их достижения не ясны. Можно сделать так. А можно и эдак. А почему нужно делать так? И что хорошего будет, если мы (не)сделаем вот эдак? А что плохого? А почему?

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

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

Из-за этого в состоянии опустошенности и рассеянности во время этапа мозгового штурма я попадаю гораздо чаще, чем на этапе отладки. И внезапные “озарения” так же возникают чаще. А возникнув, озарения требуют к себе внимания. Ведь иногда недостаточно просто зафиксировать идею, иногда идея заставляет тебя “выкуривать” ее, вращая и рассматривая с разных сторон. И так в любое время суток, в любом месте. Просто бум: “А что, если вот так?…” И все, на несколько часов ты потерян для общества :)

Вот такой поток сознания получился… Хотел еще что-то вставить про “состояние потока”. И о том, при каких раскладах мозговой штурм оказывается тяжелее, а при каких – проще. Но, видимо, уже в другой раз. Если кому-то будет интересно (в чем я не особо уверен).