суббота, 24 июля 2010 г.

[prog] Обозвать Java сложным языком можно только со зла

В перерывах трансляции полуфиналов World Matchplay 2010 (один из крупнейших турниров в профессиональном дартсе) сразу по двум RSS-лентам пришли сообщения о докладе Роба Пайка, в котором он обозвал Java и C++ переусложненными языками (вот видео его выступления – сам я его не смотрел). Естественно, всего этого лишен его новый язык Go. Кто бы сомневался :)

Реклама собственного творения – это, конечно, хорошо. Но в маразм так же впадать не нужно. Обозвать Java переусложненным языком можно разве что со зла. Ущербность Java, имхо, вовсе не в переусложненности, а в чрезмерной примитивизации. В отличии от C++ ;)

Так что, если бы Пайк сказал только про C++, что он слишком сложный для промышленного применения, я бы не разбухал. Но вот обвинить в этом Java…

[comp] Индийский прототип планшетного компьютера за $35

В индии был разработан прототип планшетного компьютера для школьников и студентов, который стоит всего $35. В нем touch-screen, 2Gb RAM (но нет жесткого диска), Wi-Fi и USB-порт. Вроде бы, операционкой там служит Linux. Из софта имеется Интернет-браузер, PDF-читалка, медиа-плейер, средства для проведения видеоконференций. И это чудо может работать от солнечного света. Продажи планируются на 2011 год.

Ну что, приближается iPad-окопец? ;))) Тем более, что разработчики девайса считают, что его цену можно снизить и до $20, а то и до $10 :)

[life.wow] Креслице Gravity Balans

Прикольно, наверное, было бы иметь дома вот такое кресло:

Но, боюсь, сейчас бы я нашел ста тридцати трем тысячам российских рублей более рациональное применение ;)

пятница, 23 июля 2010 г.

[life.humour] Рефлекс на звонок телефона

Года полтора назад сделал для своего телефона рингтон из вступления песни Ain’t No Cure For Love Леонарда Коэна и назначил эту мелодию на номер жены.

Сегодня, впервые за последние шесть или семь месяцев включил в плейере Леонарда Коэна. Когда дело дошло до Ain’t No Cure For Love я на автомате схватился за телефон и попробовал ответить на звонок, которого не было. Рефлекс, однако :)

[life.sport.darts] Свежий nine darts finish на World Matchplay 2010 и не только

Чем больше занимаюсь дартсом, тем больше склоняюсь к тому, что дартс развивает, прежде всего, две вещи:

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

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

Но над всем этим стоит концентрация. Вот ставишь себе цель – попасть тремя дротиками в определенный сектор, допустим в D6. Первый попадает, затем второй… И тут в голове начинают носиться мысли: “ну вот, сейчас и третий туда же…” или “а теперь и третий точно так же…” Все! Концентрация потеряна, третий дротик обязательно улетит совсем не туда.

И это всего три дротика и в один и тот же сектор. А уж творится в голове у дартсиста, когда он идет на 9-ти дартсовый лег? Там же каждый следующий бросок многократно дороже предыдущего.

В этом смысле интересно посмотреть на свежий nine darts finish от Raymond van Barneveld на проходящем сейчас турнире World Matchplay 2010:

Блин, какая концентрация!

PS. Кислая рожа соперника Barney так же внушаить :)

четверг, 22 июля 2010 г.

[prog] Вроде бы простая штука – напечатать timestamp в сообщении в log-файле

Вроде бы простая штука – при записи сообщения в log, получить в строке log-файла нормальный timestamp сообщения. Однако, в некоторых реализациях, все это оказывается очень интересным и неожиданно сложным делом. Например, в упомянутой вчера мной библиотеке ACE.

Нормальные библиотеки для логирования должны состоять из двух составляющих: front-end-а (тот API, который пользователь дергает для отправки сообщений в лог) и back-end-а (не видимая обычно пользователю часть, которая помещает сообщения в файлы, в EventLog, в syslog и еще куда-нибудь). Аналогичным образом устроено логирование и в библиотеке ACE. Front-end-ом служат макросы ACE_ERROR, ACE_DEBUG и т.д. В качестве back-end-ов используются наследники класса ACE_Log_Msg_Backend.

Логирование в ACE выполняется следующим образом:

  • при обращении к макросу ACE_ERROR/ACE_DEBUG… управление передается в ACE_Log_Msg::log(). Нужно сказать, что сообщения для логирования в ACE оформляются так же, как и вывод при помощи функций printf: есть форматная строка и есть список параметров. Так вот, в методе ACE_Log_Msg::log() сначала строится текст результирующего сообщения посредством обработки форматной строки и параметров. А уже потом…
  • сформированное в ACE_Log_Msg::log() сообщение попадает в ACE_Log_Msg_Backend::log(). Где готовое сообщение без каких-либо преобразований записывается туда, куда положено.

Теперь можно вернуться к timestamp-у. Сам ACE не добавляет timestamp к помещаемому в лог сообщению. Если пользователь хочет видеть timestamp в своих сообщениях (интересно, а в каких случаях timestamp видеть не нужно?), то должен добавить в форматную строку своего сообщения ключ %D или %T. И тут-то начинается самое интересное – как и в какой момент этот timestamp появляется. Для этого придется заглянуть в потроха ACE_Log_Msg.

В начале метода ACE_Log_Msg::log() берется текущее время и сохраняется в объекте ACE_Log_Record (туда же затем будет помещено и результирующее сообщение, а затем этот объект пойдет в ACE_Log_Msg_Backend::log). Отлично, вроде бы, взяли время, зафиксировали. Тут есть один тонкий момент – зачем в ACE_Log_Record вообще метка времени, но к этому я вернусь чуть позже.

Далее ACE_Log_Msg::log() производит разбор аргументов форматной строки. И, внимание, если находит ключ %D или %T, то снова берет текущее время! Зачем, спрашивается? Ведь у нас уже есть сохраненная в ACE_Log_Record метка.

Ответа на этот вопрос я не знаю. Одно из предположений такое: в форматной строке можно указать ключ %r, который говорит, что пользователь в качестве аргумента передает указатель на функцию (вроде бы с прототипом void(void)) и эту функцию нужно вызвать и ACE_Log_Msg::log вызывает эту функцию по указателю прямо посреди разбора форматной строки. Зачем такое нужно я не представляю. Но зато это может приводить к следующим эффектам: указываем форматную строку “%D%r%D”, даем указатель на функцию, которая работает 5 секунд, и получаем строку в которой первый timestamp на 5 секунд меньше второго. Что, собственно, говоря, правильно.

Теперь можно вернуться к вопросу о том, зачем в ACE_Log_Record хранится метка времени. Предполагаю, что она там нужна для того, чтобы back-end мог вести суточные/часовые/пятнадцатиминутные файлы. Приходит в back-end очередной ACE_Log_Record, смотрит back-end на метку времени и решает, нужно ли менять log-файл или нет.

Но тут вот какая штука получается. Допустим, back-end ведет суточные логи. В 23:59:59.990 приложение обращается к ACE_Log_Msg. В ACE_Log_Record попадает именно это время. Но затем, по мере разбора форматной строки и обработки ключей %D, %T время уже изменилось и стало, допустим, 00:00:00.050. Именно это значение будет сохранено в строке-сообщении. Далее ACE_Log_Record передается back-end-у, тот смотрит на метку времени, видит там 23:59:59.990 и решает записать сообщение в старый суточный файл. Но в самом файле окажется строка с меткой времени 00:00:00.050. Вероятность этого, конечно, не сильно большая. Но вполне реальная (особенно для приложений, обрабатывающих сотни транзакций в секунду).

К чему я все это веду? А к тому, если front-end системы логирования занимается форматированием сообщения и делает это без синхронизации с другими потоками, то может происходить интересная штука. Нить A обращается к logging front-end, front-end успевает получить метку времени, после чего нить A снимают с процессора. Управление переходит к нити B, которая так же обращается к logging front-end. Но для нити B успевает выполниться вся цепочка действий (взятие текущего времени, форматирование сообщения, запись его через back-end). Т.о. запись от нити B попадет в log раньше записи нити A. Но ведь у нити B метка времени окажется большей, чем у нити A. Т.е. может получиться, что в логе сначала будет идти запись, например, от 15:17:59.890, а следом – запись от 15:17:59.770.

Посему я для себя делаю следующие выводы (на случай, если придется изобретать собственную систему логирования):

  • пользователь не должен управлять взятием/не взятием метки времени для сообщений лога. По крайней мере для отдельных сообщений. За метки времени должна отвечать подсистема логирования;
  • подсистеме логирования не нужно поддерживать такие извраты, как вызов произвольной функции по указателю на нее;
  • подсистема логирования должна добавлять к сообщению метку времени и отправлять сообщение в back-end под общим mutex-ом, чтобы обеспечить строгую сериализацию всех сообщений.

среда, 21 июля 2010 г.

[prog] Пару слов о документации к ACE

У библиотеки ACE есть несколько фатальных недостатков (помимо того, что ее писали не мы ;) ). Во-первых, это уж очень old-school стиль (местами даже не C++ный, а вообще C-шный). В особенности с кодами ошибок – функции возвращают –1 при ошибке, а сам код ошибки нужно брать из errno. Во-вторых, у ACE ну уж очень куцая документация. И об этом-то пойдет речь.

Информацию об ACE можно брать из трех типов источников:

  1. Книги (“C++ Network Programming, Volume 1: Mastering Complexity with ACE and Patterns”, “C++ Network Programming, Volume 2: Systematic Reuse with ACE and Frameworks” (эти две переведены на русский язык), “The ACE Programmer's Guide: Practical Design Patterns for Network and Systems Programming”). Имхо, без них за ACE лучше не браться. По крайней мере я не решался широко использовать ACE пока не прочел первые две.
  2. Статьи о разных аспектах ACE, опубликованные на домашней страничке библиотеки (разделы “Technical Papers” и “Advanced Tutorials”). Как мне показалось, там собраны довольно старые статьи и презентации, пользы от которых не много.
  3. Сгенерированная doxygen-ом по исходникам ACE документация (в on-line ее можно просмотреть здесь). Вещь абсолютно необходимая (посмотреть названия классов/методов/полей), но, временами, абсолютно бестолковая.

Очень сильно помогает еще и изучение исходников ACE, но сейчас я все-таки о документации.

Так вот, вместе с дистрибутивами самой ACE можно скачать еще и архив построенной doxygen-ом документации по ACE. А размер этого архива внушает ;) Вот динамика его изменения:

ACE-html-5.2.5.tar.bz2                    06-Oct-2006 17:16   38M  
ACE-html-5.5.5.tar.bz2                    25-Jan-2007 04:51   67M  
ACE-html-5.6.1.tar.bz2                    19-Sep-2007 05:41  175M  
ACE-html-5.6.2.tar.bz2                    14-Dec-2007 05:05  306M  
ACE-html-5.6.3.tar.bz2                    21-Feb-2008 04:53  306M  
ACE-html-5.6.5.tar.bz2                    19-May-2008 05:15  298M  
ACE-html-5.6.6.tar.bz2                    15-Sep-2008 09:58  301M  
ACE-html-5.6.7.tar.bz2                    27-Nov-2008 06:27  301M  
ACE-html-5.6.8.tar.bz2                    09-Feb-2009 21:47  184M  
ACE-html-5.6.9.tar.bz2                    14-Apr-2009 12:32  187M  
ACE-html-5.7.0.tar.bz2                    22-Jun-2009 13:11  188M  
ACE-html-5.7.1.tar.bz2                    13-Jul-2009 17:36  188M  
ACE-html-5.7.2.tar.bz2                    23-Jul-2009 03:59  189M  
ACE-html-5.7.3.tar.bz2                    11-Sep-2009 05:19  197M  
ACE-html-5.7.4.tar.bz2                    12-Oct-2009 15:41  197M  
ACE-html-5.7.5.tar.bz2                    30-Nov-2009 02:27  207M  
ACE-html-5.7.6.tar.bz2                    01-Feb-2010 04:59  315M  
ACE-html-5.7.7.tar.bz2                    03-Mar-2010 03:25  314M  
ACE-html-5.7.8.tar.bz2                    02-Apr-2010 08:47  317M  
ACE-html-5.7.9.tar.bz2                    31-May-2010 04:43  319M  
ACE-html-5.8.0.tar.bz2                    05-Jul-2010 03:29  331M  

До сегодняшнего дня я пользовался документацией еще к версии 5.5.5. Сегодня решил обновить ее до версии 5.7.9. Глянул на размер архива – 319Mb – и слегка офигел. Не верилось мне, что качество doxygen-овской документации настолько улучшилось, что архив вырос в 5 раз. Но раз надо, значит надо, скачал, распаковал.

В распакованном варианте 181Mb занимает все такая же куцая документация по самой библиотеке ACE. Плюс почти гигабайт не менее куцей документации по TAO (реализация CORBA на основе ACE). Абыдно, поскольку документация по TAO мне вообще нафиг не упала.

Такие вот дела. Полный дистрибутив Qt SDK for Windows (с Qt 4.6.3 и Qt Creator 2.0.0) весит 293Mb. Так там и исходники, и примеры, и вспомогательные инструменты, и на порядки более качественная документация по API. И, повторюсь, все это в 293Mb. А у ACE только ущербная документация, 90% которой мне вообще не нужны, но зато 319Mb. Почувствуйте разницу :/

вторник, 20 июля 2010 г.

[life; prog; flame] Вы все еще хотите, чтобы ваш мальчик пошел в хакеры?

Тема навеяна анекдотом и несколькими ссылками на профильных форумах. Анекдот:

Петр Ильич Чайковский, Фредди Меркюри, Борис Моисеев, Сергей Пенкин. Вы все еще хотите отдать вашего мальчика в музыкальную школу?

А хотите ли вы, чтобы ваш мальчик стал известным хакером, автором нескольких книг, высокооплачиваемым специалистом? Чтобы в свои 33 выглядеть как пятидесятилетний пациент туберкулезного диспансера (на снимке ниже он третий слева)? Чтобы мотаться по свету и жить с какими-то шалавами, развлекаясь запихиванием им в жопу сосисек и курурузы, и описывая все это в красках на хакерных форумах?

2010-11-24DSC_0193[1]

PS. За профессиональный успех нужно заплатить. Лично для меня такая цена слишком высока.

PPS. Затронуть эту тему меня заставило одно очень важное правило, усвоенное мной с детства: мужчина о своих отношениях с женщиной никому не рассказывает.

понедельник, 19 июля 2010 г.

[prog] Так почему отладка без отладчика – это хорошо?

Данная заметка является логическим итогом предшествующей серии “Пути к отладчику, с отладчиком и от отладчика” (первая, вторая, третья, четвертая и пятая части).

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

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

Если разобраться, то зачем нужен отладчик? Чтобы посмотреть, как ведет себя программа. А зачем на это смотреть? Ведь это же я написал программу, я должен понимать, как она работает. А если я не понимаю, то получается, что я не знаю собственную программу.

Вот как происходит приобщение к отладчику. Моя программа выдала не тот результат. Почему? Я не знаю. Первая мысль – сейчас в отладчике посмотрю. Смотрю. Допустим, вижу. Я узнал что-то о своей программе, но это благодаря тому, что мне показали. Показали.

В этом вся разница – без отладчика я вынужден доходить до причины сам. С отладчиком мне показывают проблему. Это как с детскими логическими головоломками – додумался ли ребенок сам или же ему кто-то показал решение. Додуматься самому гораздо важнее. Клетки мозга в правильном порядке структурируются. И память о решении на более долгий срок в мозгу отпечатывается.

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

Поэтому теперь, когда я вижу, что программа выдает что-то не то, я не лезу в отладчик смотреть, как это происходит. Я начинаю думать, как же это может происходить. Что должно случиться в программе, чтобы она повела себя так, а не иначе? В процессе обдумывания выделяются ключевые точки в программе, в которых принимаются какие-то важные решения. Остается лишь понять, в какой именно.

Иногда это оказывается совсем просто. Иногда нет. Зачастую не хватает нужно глянуть значения переменных, на основе которых программа принимает решения. Нужен ли для этого отладчик? С точно таким же успехом можно обойтись и отладочными печатями. Главный вопрос здесь не в том “как смотреть”, а в том “что смотреть”. Прежде, чем вставлять отладочную печать в код нужно подумать о том, что я смогу увидеть, нужно ли мне это, достаточно ли мне этого. Нужно подумать. А проблема отладчика (как проблема шпаргалки) в том, что он провоцирует не думать. Добавим переменную x в окно просмотра – не вопрос! Что-то x мало оказалось, давай еще и y – давай, какие проблемы! А может еще и z – давай, делов-то! А еще можно по живому поправить код и посмотреть, получилось что-нибудь или нет. Не получилось? Тогда можно еще раз поправить и посмотреть. А потом еще и еще. Хотя можно было просто подумать :)

Так что коротко резюмирую главную свою претензию к отладчикам – отладчики провоцируют неосознанный поиск проблем. Тогда как, например, отладочные печати – осознанный поиск.

Далее, есть очень большой класс задач, в которых от отладчика вообще пользы мало. Например: многопоточность, многопроцессовость и распределенность, реальное время, обработка больших объемов данных, куски кода на конечных автоматах (да еще генерируемых автоматически, как в случаях с lex/yacc), работа с внешним оборудованием, встраиваемое ПО. Поэтому хочешь, не хочешь, а научиться обходиться без отладчика придется.

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

А об специализированных инструментах нужно сказать отдельно. Есть несколько их типов, без которых разработчику не обойтись. В первую очередь это профайлер. Нельзя заниматься оптимизацией без профайлера. В крайнем случае можно мастерить средства для замера времени работы участков кода самому – но это уже в самом крайнем случае. Лучше взять нормальный, готовый профайлер.

Для C/C++ разработчиков так же важным инструментом будет средство для обнаружения утечек и расстрелов памяти. Вроде valgrind-а. Причем такой инструмент заменить самодельным велосипедом намного сложнее, чем профайлер.

А вот отладчик к числу таких обязательных инструментов все-таки не относится. Я использую отладчик для обнаружения мест возникновения Access Violations в программах. Если отладочными печатями обнаружить их не удается. В этом качестве отладчик бывает полезен. Но далеко не всегда, особенно в многопоточном C++ном коде после проезда по чужой памяти.

Ну и еще один приятный бонус для тех, кто может отлаживать свои программы без отладчика. Вам будет проще осваивать новые, перспективные языки, которые еще не успели обзавестись собственным отладчиком :) Т.е. вы сможете сделать свой вывод о том, что “D/Scala/F#/Groovy++ (не) взлетит” гораздо раньше, чем те, кто будет ждать готовой интеграции со студией или эклипсом :)

[life.cinema.wow] Чужой-IV и Амели: казалось бы, что общего?

Если верить kinopoisk.ru, то Жан-Пьер Жёне был режиссером и Чужого-IV и Амели. Афигеть, я не знал.

Хотя… И тот, и другой фильмы – сказочки для взрослых и не очень ;) Чему уж тогда удивляться? Разве тому, как автор заурядного фантастического боевика сумел заделать настолько уникальный фильм, как Амели.

[work] Отличный способ обеспечить рабочее настроение утром в понедельник

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