Пилот «от бога» – мне понравилось.
Размышления и впечатления, которые не хочется держать в себе. О программировании в частности. Ну и о творчестве, и о жизни вообще.
суббота, 6 февраля 2010 г.
[life] Об отсутствии Интернета дома и iPad-е
В связи с поломкой моего ADSL модема три дня дома не было Интернета. Впечатления похожие на отсутствие дома телевизора – первая мысль, что это дикость и жизнь заканчивается, но потом наступает ощущение свободы и, плюс к тому, откуда-то высвобождается большое количество свободного времени ;)
Так что лично мне даже понравилось. Нет соблазна в очередной раз проверить почту, написать ответ в комментариях к блогу, увлечься чтением очередного говносрача на каком-нибудь программерском ресурсе. Лепота, короче.
Жена, правда, расценивала все это совсем иначе – нет Skype, нет доступа к новостям и Интернет-версиям журналов, сайт рецептов Анастасии Скрипкиной не открывается… Светская жизнь закончилась, короче ;)
Но, как и любой экстрим, отсутствие Интернета хорошо в меру. Все-таки оборвались закачки. Учитывая, какую муру показывают по телевизору (по которому я смотрю сейчас разве что новости и спортивные трансляции), это серьезно. Ну и пропала возможность работать дома. Хотя на счет работы дома – это сложный вопрос. Скорее, важна работа именно в одиночестве, без отвлекающих и раздражающих факторов (что невозможно в офисе в принципе).
Так вот, по следам произошедшего подумалось. Все-таки работу нужно оставлять на работе. Вплоть до своего любимого рабочего ноутбука. Пусть он в офисе до утра без тебя постоит. А ты дома без него перекантуешься. Заодно и подсознание поработает и, может быть, вознаградит тебя интересной идеей поутру.
Но дома все-таки Интернет нужен. Как и нужен какой-то девайс, который позволяет легко по Интернету шариться, но который не позволяет заняться серьезной работой. Новости посмотреть, книжку почитать, ролики на YouTube глянуть – это пожалуйста, но вот страничку текста набрать – чтобы с потом и кровью, шоб неповадно було ;)
Нетбук на такой девайс не тянет, особенно если это 11” модель с разрешением в 1366x768, да с полноразмерной клавиатурой. А вот iPad или аналогичный ему планшет – это то, что доктор прописал.
Поэтому интересно будет понаблюдать, во что выльется появление iPad-а. Будет ли он так же востребован, как iPhone? Породит ли он более удачных клонов? Поскольку именно с Apple-овской продукцией связываться не хочется. Уж слишком там на централизованную модель дистрибуции все завязано. Хочется иметь полный контроль над собственным планшетом – захотел, вставил флешку и залил с нее все, что нужно, а захотел – и всю систему переставил. С Apple-вскими устройствами такое не прокатит. А вот с конкурентами – почему бы и нет?
пятница, 5 февраля 2010 г.
[comp.modem] Краткие впечатления от модема TRENDnet TEW-435BRM
Довелось сегодня познакомиться с ADSL модемом TRENDnet TEW-435BRM и сравнить его со своим Acorp W422G.
Сам модем производит хорошие впечатления. Когда берешь его в руки, он выглядит более качественно собранным, чем Acorp. Шустро заводится (по субъективным впечатлениям – где-то за 20 секунд), в отличии от Acorp-а, которому требуется где-то в два раза больше времени.
А вот Web-интерфейс у TRENDnet-а менее удобный, чем у Acorp-а. Вроде бы настроек порядком, но как-то странно они сгруппированы. Больше всего поразило вот что – у модема есть режим ручного подключения к провайдеру. Но я в Web-интерфейсе нигде не нашел кнопки “Connect”. Т.е. параметры подключения задать можно, есть кнопочка “Save”, а вот в какой момент он будет выполнять переподключение – фиг знает. С другой стороны, отображение диагностики у TRENDnet-а мне показалось нагляднее и удобнее, чем у Acorp-а.
Так что впечатления очень приятные, хотя и двойственные. Если бы я сейчас стоял перед выбором – Acorp или TRENDnet, то выбрал бы, скорее всего, TRENDnet. Хотя подчеркну, что я не профи в тонких настройках модема. Не исключено, что из Acorp-а, при умелом обращении, можно выжать больше. Но мне, которому нужен только WiFi и UPnP, TRENDnet более симпатичен.
PS. Web-интерфейс – это отстой. Особенно Web-интерфейс для управления локально подключенной к компу железякой.
[comp.modem] Реанимация Acorp W422G
Уже год пользуюсь ADSL-модемом Acorp W422G (с WiFi точкой доступа). Хорошая и недорогая рабочая машинка. Но во вторник началось странное – модем через WiFi виден, но подключиться к нему не удается – не срабатывает аутентификация. Перезагрузка и включение-выключение модема не помогали. В конце-концов, во вторник вечером удалось установить следующее: если при рестарте модема в него не включен шнурок от телефонной линии, то модем загружался, Ethernet и WiFi работали, можно было общаться с модемом через его Web-интерфейс. Но стоило только воткнуть его в телефонную линию – все, модем зависал.
В среду с утра и того не было. Как его не включай, признаков вменяемой жизни он не подавал вообще. Встал вопрос о том, что делать. Ведь даже один вечер без интернета оказалось тяжело пережить. И не столько мне, сколько жене и дочке ;)
Первая мысль – купить новый модем. К сожалению (или к счастью) у нас в Гомеле не так-то просто зайти в какой-нибудь компьютерный магазин и выбрать себе ADSL-модем с WiFi. Я обошел в среду пять или шесть магазинов и нашел только два таких модема, но оба были несколько дороже того, что я хотел. Ну а раз просто заменить не получается, то нужно восстановить старый.
И тут мне повезло. В Интернете нашлась замечательная статья: Ремонт ADSL модема Acorp W422G. Там были описаны похожие симптомы и указан способ их устранения. Указанные в статье конденсаторы я заменил и модем заработал! Сразу. И даже WiFi не пришлось вручную запускать. Огромное спасибо автору статьи.
Зато с запуском восстановленного модема были приключения. Модем работает, светодиод ADSL-я горит, но подключиться к ByFly не получается. Настраивал, правда, я сам через Web-интерфейс. Поскольку програмулина под названием AcorpAdslWizard почему-то не могла это сделать (видимо, из-за смены прошивки модема). В общем, я решил, что мой ремонт исправил одну проблему, но создал новую. И таки склонился к мысли о замене модема.
Сегодня утром сгонял в магазин, купил TRENDnet TEW-435BRM, подключил, все сам настроил… И опять не смог подключиться к ByFly! С теми же самыми симптомами. Что вселило в меня уверенность в том, что проблема вовсе не в модеме.
После чего последовало 20-минутное телефонное общение с очень приятной девушкой из службы техподдержки ByFly. В конце-концов она мне продиктовала полный список параметров для моего модема и, о чудо, все завелось! Ну а после этого я опять включил свой старый Acorp, задал там точно такие же параметры – и он тоже подключился! :) В общем, TRENDnet я вернул в магазин, а Acorp вновь поставил на боевое дежурство.
Итого:
- три дня без интернета – сильные впечатления (но это тема отдельного разговора);
- около 8 часов на всякую беготню по магазинам, за инструментами, и на собственно ремонт модема;
- стоимость запчастей – 2000 BYR (~30RUR), но, думаю, если бы я знал у кого именно покупать, то все уложилось бы в 600-800 BYR. Затраты на маршрутки и общественный транспорт были в несколько раз больше ;)
По следам прошедших событий хочу выразить благодарность магазину Zeon (остановка “8-е марта”) за то, что они спокойно забрали модем назад.
Большое спасибо Роману Орышко за помощь и любезно предоставленный вольтметр.
И отдельное большое спасибо девушке из службы техподдержки ByFly (кажется, ее зовут Екатерина).
четверг, 4 февраля 2010 г.
[life] Просмотр Cirque du Soleil перед сном – это покруче ужастика будет
Решили вчера вечером с женой посмотреть представление Kooza знаменитого Cirque du Soleil. Блин, это круче, чем смотреть на ночь фильм ужасов. В паре номеров, когда артисты выделывали черт знает что без страховки, было страшно. Т.е. умом ты понимаешь, что если бы произошло что-нибудь трагическое, то в фильм бы это не включили. Но страшно было все равно ;)
среда, 3 февраля 2010 г.
[comp.prog] HipHop от Facebook – трансляция PHP в C++
На opennet.ru нашел интересную новость: Facebook обнародовал свой проект HipHop. Его суть в том, что PHP код транслируется в C++, а результат потом компилируется с помощью g++. Что дает уменьшение расхода процессорного времени на 50%. Как я понял, эксплуатация HipHop-а в Facebook началась около шести месяцев назад, и сейчас с помощью HipHop-а обслуживается до 90% всего Web-трафика Facebook.
Интересующимся рекомендую прочитать официальный анонс от Facebook-а – там подробнее и увлекательнее (со слайдами ;).
Теперь отсебятина ;) Еще раз убеждаюсь в том, что существует дилемма – быстрая разработка или быстрое исполнение. Увеличивая скорость разработки (за счет более высокоуровневых и заточенных под задачу языков/инструментов) мы обязательно жертвуем скоростью исполнения. И наоборот (используя C++, C, Asm) мы выигрываем в скорости исполнения за счет скорости разработки. Попытки убить сразу двух зайцев приводят к возникновению вот таких вот лисапедов ;)
Кстати, думаю, что аналогичная дилемма существует для компромисса между скоростью разработки и качеством (количеством дефектов). Но данная новость не об этом ;)
[comp.prog.flame] Впечатления после очередного code review
Провел на работе очередной code review. Парочкой впечатлений хочу поделиться. Предупреждаю сразу, примеров кода будет много ;)
Во-первых, очень удивляет меня, насколько сильно система отступов и переносов строк влияет на читабельность большого объема кода (порядка нескольких тысяч строк). Когда просматриваешь только одну функцию, то непривычный для тебя стиль переносов не играет никакой роли. Ну написано так, а не как у тебя. Ну и ладно.
Но потом в действие вступает закон больших чисел. Усталость ли, замыливание ли глаз или рассеивание внимания, но из-за непривычного оформления изучать чужой код становиться гораздо сложнее. Целые куски просто выпадают из поля зрения.
Например, вот в этом случае:
return get_valid_path( filename.substr( 0, filename.size() - get_name_of_file( filename ).size() ) + "sqlldr" ); |
В чем здесь проблема для меня? В том, что не понятно, что именно является параметрами substr – выражение сложное и глазу не за что в нем зацепиться. Вот как этот же фрагмент написал бы я:
return get_valid_path( filename.substr( 0, filename.size() - get_name_of_file( filename ).size() ) + "sqlldr" ); |
В этом случае filename.substr() и “sqlldr” находятся на одном уровне вложенности и это подсказывает мне, что они являются равноправными частями одного выражения.
Еще напрягают вот такие выражения:
static bool check( const msg_check_report_wait_t * msg ) { return ( (msg->m_operation_id != c_unknown_operation_id) && (msg->m_uuid != c_unknown_uuid) ); } |
Я бы переписал это чуть компактнее:
static bool check( const msg_check_report_wait_t * msg ) { return msg->m_operation_id != c_unknown_operation_id && msg->m_uuid != c_unknown_uuid; } |
И совсем удивительным для меня оказалось то, что тяжело читаются куски кода, в которых в if-ах единичные операторы все равно обрамляются фигурными скобками. Т.е. когда вот такой код:
int detect_actual_code( int result, int code, const std::string & type_result ) { if ( result == c_more_one_answer ) { // Более одного ответа. return e_fatal_error; } else { // Если был результат 2204050, то // код ответа не может быть 0, т.е. все плохо. if ( (type_result == "2204050") && (code == 0) ) { return e_task_error; } if ( code != e_all_correct ) { return e_task_error; } } return code; } |
встречается слишком часто, то воспринимается он гораздо хуже, чем вот такой:
int detect_actual_code( int result, int code, const std::string & type_result ) { if ( result == c_more_one_answer ) // Более одного ответа. return e_fatal_error; else { // Если был результат 2204050, то // код ответа не может быть 0, т.е. все плохо. if ( (type_result == "2204050") && (code == 0) ) return e_task_error; if ( code != e_all_correct ) return e_task_error; } return code; } |
Уж не знаю, за счет чего. Может из-за того, что снижается объем полезной информации в коде, может еще из-за чего-то. Но эффект имеет место быть. Причем, повторюсь, такой эффект как раз силен в случае, когда за короткое время нужно просмотреть большой объем кода.
Во-вторых, если при первом взгляде на функцию кажется, что ее реализация слишком “мудрена”, то с очень высокой степенью вероятности эта функция будет работать неправильно. И что существует множество простых способов ее улучшить.
Вот пример такой функции. Ее задача – сформировать идентификатор из 11 цифр на основе текущей даты и времени. Оригинальный вариант:
std::string make_timestamped_uid() { // Текущие msec в формат '000' с лидирующими нулями. std::string msec = cpp_util_2::slexcast( ACE_OS::gettimeofday().msec() % 1000 ); // Число чисмолов в '000'. const int c_count_000 = 3; while ( msec.size() < c_count_000 ) { msec = "0" + msec; } // Секунды с какого-то года в виде строки плюсуем к '000'. std::string uid = cpp_util_2::slexcast( ACE_OS::gettimeofday().sec() ) + msec; // Должно быть число в 11 цифр с лидирующими нулями. const int c_count_digits = 11; // Добиваем если не хватило. while ( uid.size() < c_count_digits ) { uid = "0" + uid; } // Обрезаем старшее если получилось больше, чем 11 символов. if ( uid.size() > c_count_digits ) { uid = uid.substr( uid.size() - c_count_digits ); } return uid; } |
Первое, что мне бросилось в глаза – это два идентичных цикла для формирования нужного количества лидирующих нулей. Это действие сразу же нужно было бы выносить в отдельную inline-функцию. Которая бы при этом работала не через while, а через метод basic_string::insert.
Второе – это двойной вызов ACE_OS::gettimeofday() для получения текущего времени. Вполне достаточно было бы и одного.
Потом я задался вопросом – а зачем мы сначала выравнивали значения msec и uid до точных размеров, а потом обрабатывали превышение этого размера? Что-то в этом не то. Без этого вполне можно было бы обойтись. Ведь можно же сразу получать из даты/времени целочисленные значения в нужных диапазонах, а потом просто использовать стандартные средства C++ для форматирования.
Update. Три следущих абзаца оказались гнусным поклепом с моей стороны, поскольку я не заметил операции взятия остатка от деления на 1000. Что, к сожалению доказывает, что в переусложненном коде сложно разбираться
Тут-то всплыла ошибка, допущенная разработчиком make_timestamped_uid. Функция ACE_OS::gettimeofday() возвращает объект ACE_Time_Value. Который является парой <sec,usec>. Где sec – это текущая секунда от 1 января 1970, а вот usec – это микросекунда в рамках текущей секунды. Т.е. точное время – это (sec+usec).
Разработчик думал, что обращение к msec() – возвращает usec/1000, т.е. миллисекунды в рамках текущей секунды. Но ACE_Time_Value::msec() возвращает <sec,usec> преобразованные в миллисекунды (т.е. sec*1000+usec/1000). И даже не это значение, а ту его часть, которая помещается в unsigned long. Получается, что переменная msec всегда будет иметь длину больше трех символов. И что значение этой переменной будет иметь косвенное отношение к текущей миллисекунде.
Счетчик секунд от 1 января 1970 года сейчас – это десять десятичных цифр. К которым добавляется всего один символ из msec. Т.к. этот символ первый (т.е. самый старший разряд), то он будет одним и тем же для очень длительного временного интервала. Значит, несколько последовательных вызовов make_timestamped_uid в течении одной секуды (даже с интервалом в сотни миллисекунд) будет приводить к генерации одного и того же идентификатора. Т.е. функция не будет делать то, на что она была расчитана.
А ведь можно было написать все гораздо проще. Имхо, вот так:
std::string make_timestamped_uid() { const ACE_Time_Value now = ACE_OS::gettimeofday(); char buf[ 16 ]; // Поскольку нам нужно строго 11-ти значное значение, // в котором три самых младших разряда будут занимать // миллисекунды, то от счетчика секунд оставляем // только 8 младших разрядов. const unsigned long s = now.sec() % 100000000ul; // Микросекунды должны быть преобразованы в миллисекунды. // Остаток от деления на 1000 для гарантии в случае, если // usec возвращает значение больше 1000000. const unsigned long m = ( now.usec() / 1000 ) % 1000; std::sprintf( buf, "%08lu%03lu", s, m ); return buf; } |
Если повыбрасывать комментарии, и промежуточные константы s и m, то можно вообще тремя-четырьмя строками обойтись. (Те, кому не нравится sprintf, могут получить то же самое через std::ostringstream, setfill и setw).
Вспоминается замечательный афоризм (за авторством, C.A.R.Hoare):
Есть два способа создания программы. Можно сделать ее настолько простой, что в ней совершенно очевидно нет ошибок. А можно сделать настолько сложной, что в нет совершенно очевидных ошибок.
Ну и в качестве бонуса для тех, что смог дочитать до этого места. В обсуждавшейся выше функции make_timestamped_uid() есть просто смешной фрагмент:
// Число чисмолов в '000'. const int c_count_000 = 3; |
[comp.prog] Вышел Boost 1.42.0
Вышел очередной релиз Boost-а – 1.42.0 (периодичность выходов новых релизов радует). Добавлена новая библиотека – uuid для генерации UUID-ов. Приятно, Boost начинает обрастать действительно полезными вещами ;)
вторник, 2 февраля 2010 г.
[work] Давно не пользовался Word-ом, забыл какое это удовольствие
В течении нескольких последних лет не пользовался Word-ом. Вообще. Документацию, в довольно-таки изрядных объемах, писал в LaTeX-е. По мелочам в Wiki. В общем, отвык. Забыл, какая это радость – ручное управление шрифтами, стилями, отступами и пр.
А тут потребовалось небольшой документик быстро в Word-е сварганить. В 2007-ом Word-е, который, мать его, совершенно непохож на предыдущие. Блин, павбывавбы.
Но самое радостное случилось потом. Отослал документ на рецензию коллеге. Получил обновленный вариант с комментариями. Но не смог открыть. Мой Word падал при попытке открытия файла. Рестартовал и опять падал, и опять рестартовал, и опять падал.
Снес свой Word, взял другой дистрибутив (как раз тот, из которого Word брал мой коллега). Эффект тот же. Причем файл не открывается даже в формате RTF!
Блин, трындец. Чего делать не понятно, время, как обычно, поджимает. А в голове одна мысль – вот ведь глюкавая скотина! ;)
Пока помогло вот что – после деинсталляции Word-а перезагрузил систему и только потом проинсталлировал заново. Пока помогло. Посмотрим, что будет дальше.
Что обидно: когда кому-то нужно передать готовый текст, то можно подготовить его в LaTeX-е или DocBook-е, сгенерировать PDF и всех делов. Но вот когда приходится совместно с заказчиком работать над одним документом, тогда альтернативы Word-у не видно. И дело даже не в самом ворде, это может быть OpenOffice или Lotus Symphony, или KOffice – не важно. WYSIWYG – вот корень зла! ;)
понедельник, 1 февраля 2010 г.
[comp.prog] ACE обновилась до версии 5.7.6
Вышла новая версия библиотеки ACE – 5.7.6. Из основных изменений:
- поддержка iPhone OS 3.1.2;
- поддержка Embarcadero C++ Builder 2010;
- в функции семейства printf добавлена возможность печати объекта ACE_Time_Value;
- ACE компилируется под VxWorks 6.8, но тестирования под этой системой, как я понял, не проводилось.
Плюс еще исправления 12 багов.
Соответственно, до версий *.7.6 обновились TAO и CIAO.
Скачать можно отсюда: http://download.dre.vanderbilt.edu/
Disclaimer: мопед не мой, я только дал объяву. Сам я пока на 5.7.* не перешел, продолжаю сидеть на 5.6.*. Ибо некогда.
[comp.prog] Прочитал статью об Amazon Dynamo и хочу спросить своих читателей
Пару недель назад, по наводке Дмитрия Вьюкова, вышел на интересную статью об архитектуре Amazon Dynamo – распределенной системы хранения информации, используемой Amazon-ом. Статья очень интересная, но большая (15 страниц текста в две колонки).
Поскольку она на английском, а на русском языке такие интересные материалы редко попадаются, то я сначала захотел сделать в своем блоге ее краткий пересказ. Но когда попытался выделить наиболее важные моменты, то мне стало казаться, что это очень непростая задача – коротко (в два-три поста) пересказать много чужой информации (при этом кое в чем я и сам пока не сильно разобрался). Самый хороший вариант был бы перевести ее полностью на русский язык. Но, по первым прикидкам (по два дня на страницу), на это потребуется не меньше месяца. Поэтому появился и еще один вариант – серия постов с пересказом (близко к тексту, но не точный перевод) этой статьи. Каждый пост – это один или два раздела из статьи.
Так вот хочу спросить потенциальных читателей – нужно ли вообще этим заниматься? Интересно ли кому-нибудь читать об архитектуре и работе Amazon Dynamo на русском языке?
Если интересно, то какая форма лично для вас будет предпочтительнее:
- полный точный перевод статьи (где-то в начале марта);
- два-три больших поста с моим пересказом основных моментов;
- серия из 10-12 постов с пораздельным пересказом статьи (с моими комментариями и лирическими отступлениями)?
Так что, как бы банально это не звучало, все в ваших руках ;)
воскресенье, 31 января 2010 г.
[life.sport] Марк Ален поднял белый флаг во встрече с Ронни О’Салливаном
Вчера по EuroSport-у перед началом полуфинального матча между Джоном Хиггинсом и Ронни О’Салливаном на турнире Welsh Open показали последние партии Джона и Ронни в их четвертьфинальных матчах. Впечатлило поведение противника О’Салливана, Марка Алена. Он ошибся в своей серии в решающей партии и потом был вынужден наблюдать за тем, как О’Салливан забивает один шар за другим. Причем делает это настолько мастерски, легко и играючи, что Марку ничего не оставалось кроме как вывесить белый флаг:
Update. Для желающих посмотреть все это воочии, вот видео:
[life.photo] Портреты Юрия Бондера
В сегодняшней воскресной фотоподборке продолжается знакомство с творчеством замечательного фотохудожника Юрия Бондера (1967-2008). Сегодня фотографии, который были занесены автором в категорию “Портрет”.
Другие работы Юрия Бондера из категории “Портрет” можно увидеть на photosight.ru.
PS. Имхо, жанр портрета один из самых сложных и субъективных (и не только фотографии). Кроме того, я не большой любитель этого жанра. Поэтому в мою сегодняшнюю выборку попали только те работы, которые меня сильно зацепили. Боюсь, что мой выбор может составить неправильное впечатление о творчестве Юрия Бондера. Поэтому очень рекомендую сходить на photosight.ru или на photoline.ru.