суббота, 24 мая 2014 г.

[life.photo] Как снимать несколько часов подряд и не получить ничего хорошего?

Очень просто: нужно быть любителем мануальных объективов, но брать фотоаппарат в руки не чаще раза в месяц. Тогда запросто из нескольких сотен снимков более-менее приличными окажутся всего пара-тройка штук. Все остальное уйдет в жуткий технический брак. Причем, что любопытно, когда ловишь момент "по-ковбойски", навскидку, то резкость ловится даже при f=3.2. А когда тщательно выцеливаешь желая сделать хороший портрет спокойно стоящего человека, то промахиваешься мимо и на f=5.6. Может уже просто слепну с возрастом...

Ниже то немногое, что получилось из съемки на соревнованиях воздушных змеев, хотя змеев на фото практически-то и нет :) Снималось все на фикс 1.4/85mm.

пятница, 23 мая 2014 г.

[management] Генри Минцберг "Зачем децентрализовать структуру?"

Позволю себе процитировать небольшую главку под названием "Зачем децентрализовать структуру?" из книги Генри Минцберга "Структура в кулаке. Создание эффективной организации". Из текста я удалил лишь маленький фрагмент, который представлял из себя выдержку из газетной статьи 1960-х годов. Думаю, что тем менеджерам, которым, как и мне, приходилось "руководить" производственным филиалом, территориально удаленным от головного офиса, будет очень хорошо знакомо все, что написано в этой главе. Слово "руководить" взято в кавычки потому, что невозможно руководить, если верховное руководство компании либо не признает децентрализации, либо же делает это только на словах. Проверено, к сожалению, не на кошках :(
Выделение полужирным шрифтом авторское, именно так текст был выделен в книге. Курсивом и подчеркиванием я выделил лишь одно короткое предложение, которое лично мне очень и очень много объясняет.
Зачем децентрализовать структуру?
Что побуждает организацию к централизации или децентрализации структуры? Как и большинство связанных со структурой вопросов, это проблема разделения труда и координации. Централизация -- самое сильное средство координации процесса принятия решений в организации. Все решения принимаются одним человеком, одним разумом, а затем приводятся в исполнение с помощью прямого контроля. Для централизации структур есть и другие причины, но, помимо жажды власти, большинство из них сводится к необходимости координации.
Зачем же тогда организации децентрализоваться? Просто затем, что не все ее решения может объять один центр, разум одного человека. Иногда вся необходимая информация просто не может быть доведена до центра. Возможно, потому во многом она является неопределенной, не строгой. Как торговому представителю компании в Багдаде объяснить находящемуся в Бирмингеме менеджеру характер своих клиентов? Порой информация, переданная в центр, там не осмысливается. В силах ли президент конгломерата "пераварить" данные о ситуации с каждой из сотни товарных линий? Даже если ему представлены отчеты о каждой из них, президенту вряд ли достанет времени разбираться с ними...
...Возможно, самой распространенной ошибкой организационных дизайнеров является централизация процесса принятия решений в условиях подобных ограничений. Уполномоченные на проектирование структуры высшие руководители видят ошибки, совершаемые на нижних уровнях, и думают, что сами бы их никогда не допустили (либо считая себя умнее других, либо полагая, что координация решений не представляет проблем). К сожалению, в сложных обстоятельствах это неизбежно приводит к состоянию, называемому "информационной перегрузкой": чем больше сведений пытается получить мозг, тем с меньшим их общим объемом он реально справляется. А компетентные сотрудники на нижних уровнях иерархии перестают считаться с мнением не владеющих ситуацией вышестоящих менеджеров.
Еще один "подталкивающий" к децентрализации объективный фактор состоит в том, что она позволяет организации оперативно реагировать на происходящие на локальных уровнях изменения. Передача информации в центр и обратно занимает время, а в некоторых случаях промедление "смерти подобно". В одной из рекламных компаний Bank of America говорилось, что благодаря тому, что "на местах" работают люди, уполномоченные принимать решения, банк имеет возможность обслуживать клиентов наилучшим образом.
И последний фактор выбора в пользу децентрализации заключается в том, что она обеспечивает мотивацию сотрудников. Творческим, талантливым людям требуется пространство для маневра. Организация привлекает и удерживает таких сотрудников, продуктивно использует их инициативу только в том случае, когда она предоставляет им право принятия решений. Мотивация имеет огромное значение для профессиональной деятельности (а учитывая сложный характер труда, профессиональная организация имеет сразу два стимула к децентрализации). Кроме того, мотивация является одним из ключевых факторов управленческой деятельности, поэтому некоторая децентрализация серединной линии необходима всегда. Наделение властью менеджеров среднего звена одновременно позволяет им учиться принимать решения, так что однажды кто-то из них сможет занять пост руководителя компании, на котором и принимаются самые трудные решения.
Если вдруг эту заметку прочитают люди, принимающие решения об отказе от децентрализации или же решающие сильно ограничить полномочия своих подчиненных "на местах", то рекомендую обратить особое внимание на заключительный абзац о мотивации. Там все очень правильно написано. Не дадите свободы своим людям -- неизбежно потеряете лучших из них.

четверг, 22 мая 2014 г.

[life.music] Гитарист Keith Medley

Наткнулся на просторах интернета на еще одного классного гитариста:

Историю создания уникальной 27-ми струнной гитары в картинках можно увидеть здесь.

Предыдущая заметка на похожую тему: Estas Tonne.

среда, 21 мая 2014 г.

[life.sport.darts] Дартс в Гомеле: 25-го мая в 12:00 в СШ №66

Информация для желающих поиграть в дартс в Гомеле: 25-го мая в 12:00 в СШ №66 начнется неформальный дартс-турнир. Будут личные соревнования в 501 double-out. Формат турнира определится на месте, в зависимости от количества участников.

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

По предварительной информации, будет порядка 15 игроков, часть из которых имеет опыт участия в официальных соревнованиях. Так что будет с кем пообщаться и на ком попробовать свои силы :)

От желающих поиграть ничего особенного не требуется -- нужно просто приехать и поиграть. Ну а кто не может/не хочет, пусть хотя бы поспособствует распространению этой информации :)

[prog.c++] На тему очень хорошего комментария-вопроса про SObjectizer и Qt

Ув.тов.Alex Syrnikov в предыдущей заметке оставил очень хороший комментарий-вопрос на тему возможности сравнения SObjectizer и Qt на какой-то приближенной к реальности задаче. Комментарий большой, я его не буду копипастить, а смысл его сводится к тому, чтобы попробовать решить какую-то задачу на SObjectizer и Qt, а затем сравнить получившиеся результаты.

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

Пока же позволю себе небольшой поток воспоминаний. Изначально SObjectizer-4, появившийся на свет весной 2002-го, не нуждался в сторонних библиотеках, в нем все было свое: свои классы для работы с многопоточностью, с сетью, с DLL-ками. Со временем поддерживать это хозяйство самостоятельно становилось все сложнее и сложнее, поэтому где-то в 2004-м или 2005-м мы начали искать C++ную библиотеку, которая стала бы обеспечивающим кроссплатформенность базовым слоем. Рассматривались самые разные библиотеки, названий многих из которых я сейчас даже и не вспомню. Там были и С-шная APR, и GNU-тая Common C++, и POCO, и wxWidgets. Но выбор делался из ACE, Boost и Qt. Остановились на ACE, хотя решение это было очень не простым.

До сих пор меня время от времени терзает мысль, что если бы мы выбрали Qt в качестве базового слоя, то все могло бы сложиться иначе :) Наверняка тогда было бы две лицензии на SObjectizer -- GPL и коммерческая :))) И, возможно, сейчас бы я не думал над тем, как на SObjectizer зарабатывать деньги... ;)

Тем не менее, это явно был случай, когда не было однозначно правильного решения, да еще и с учетом исторического послезнания. Это же были времена Qt3, разрабатывавшейся еще TrollTech-ем с прицелом только на GUI. Вряд ли кто-то предполагал, что TrollTech будет куплен Nokia, Qt4 сделает огромный шаг в сторону поддержки не-GUI приложений, а сама Qt появится еще и под LGPL лицензией. Оглядываясь назад, я считаю, что выбор ACE вместо Qt себя все-же оправдал. По крайней мере, было много случаев, когда для поиска проблем нужно было глубоко погружаться в код ACE и стиль ACE-овского кода, а так же относительно небольшой объем ACE (в сравнении с Qt) позволял легко это делать.

Но время идет вперед, все развивается. С++11 уже содержит множество механизмов, которые нужны были ядру SObjectizer от ACE. Поэтому лично у меня есть желание максимально отвязаться от ACE в SObjectizer core. Уже сейчас SObjectizer-5 представлен в виде набора построенных друг над другом библиотек. Основа -- это библиотека so_5, которая поддерживает понятия сообщение, агент, состояние, диспетчер и т.д. А уже на so_5 наслаиваются дополнительные библиотеки, упрощающие разработку больших и/или распределенных приложений на SObjectizer: so_sysconf (построение приложения из DLL, как из кирпичиков), so_5_transport (поддержка TCP/IP соединений посредством SO-агентов), mbapi (обмен сообщениями, в том числе и в распределенной среде).

Так вот мне хотелось бы отказаться от ACE в so_5, оставив использование ACE только там, где требуется работа с системой (so_sysconf, so_5_transport), чтобы so_5, ядро SObjectizer, было минималистичным и не имело бы внешних зависимостей. Но сейчас этому препятствует две вещи: хорошая реализация таймеров в ACE, а таймерные сообщения -- это один из краеугольных камней SObjectizer, и задействование ACE Logging в коде всех SObjectizer библиотек. Поэтому далеко не факт, что от ACE получится избавится и обойтись только возможностями C++11 и своими собственными силами.

Однако, как я уже сказал, жизнь не стоит на месте, все течет, развивается и изменяется. Будущее SObjectizer уже не определяется только нуждами и задачами Интервэйла. Поэтому, если будут веские доводы сменить ACE в качестве базового слоя для SObjectizer на Boost или Qt, то почему бы и не обдумать такой вариант.

PS. На данный момент SObjectizer зависит не только от ACE, но и от Ruby. Впрочем, если бы в качестве системы сборки использовался SCons, то была бы зависимость от Python. Тут уж должен сработать принцип OpenSource -- авторы библиотеки используют то, что удобно им. А если кто-то хочет иметь что-то еще и у него есть время/желание/возможность воплотить это в жизнь, то милости просим... :)

вторник, 20 мая 2014 г.

[prog.c++] Как разогнать вчерашний пример

В продолжение вчерашней темы про очередь из std::function-объектов. С подачи ув.тов.Timur Rakhmatullaev в код были внесены две правки, которые существенно ускорили работу варианта с std::function.

Первая правка заключалась в использовании метода queue::emplace вместо queue::push. Огромное спасибо Тимуру за напоминание об этом методе -- в C++11 расширился API стандартных контейнеров, но я об этом постоянно забываю.

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

void
fn_test()
   {
      fn_demand_queue_t queue;
      fn_demand_generator_t generator;

      generator.on_type_1( queue );
      forsize_t i = 0; i != ITERATIONS; ++i )
         {
            fn_demand_t d = std::move(queue.front());
            queue.pop();

            d();
         }
   }

Результаты замеров существенно изменились. Так, если под GCC 4.8.2 я получал в старом варианте вот такие результаты:

fn_demands: 31.302s
oo_demands: 21.397s

То в новом варианте получается уже вот так:

fn_demands: 17.039s
oo_demands: 19.798s

Интересный эксперимент получился. И да, сутью эксперимента было посмотреть, какие накладные расходы будет нести средней руки разработчик, если начнет использовать очереди из std::function-объектов.

Под катом обновленный код теста.

понедельник, 19 мая 2014 г.

[prog.c++11] Еще на тему использования функционального стиля в современном C++

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

Если нужно, что бы заявкой в очереди сообщений был какой-то самостоятельный объект, то в традиционном объектно-ориентированном подходе нужно было бы определить базовый класс, для примера, demand_t с виртуальным методом handle(), от которого нужно было бы наплодить столько наследников, сколько вариантов поведения требовала бы прикладная логика. И, в старом-добром C++, все это делалось бы на объектах, да еще и с применением какого-то варианта умного указателя, т.к. в очереди заявок сохранялись бы указатели на demand_t (а в самом хардкорном варианте в очереди были бы голые указатели, за временем жизни которых нужно было бы следить вручную).

Но стандарт C++11 уже несколько лет как утвержден. И теперь у C++ разработчиков есть выбор: делать ли такие заявки посредством объектных иерархий или же задействовать std::function (а так же лямбда-функции с замыканиями). Но, если делать выбор в пользу std::function, то не придется ли платить за это больше, чем за объекты и std::shared_ptr?

Ради проверки этого я написал для себя небольшой тест, исходный текст которого упрятан под кат. Проверял под VC++11, VC++12 и GCC 4.8.2 под 64-х битовым Windows 7.

Upd. Ув.тов.Андрей Валяев обнаружил ошибку в моем коде. После ее исправления выяснилось, что код на std::function где-то на 35-40% медленнее кода с std::shared_ptr и объектами.

Upd2. Посредством небольшого трюка можно разогнать очередь std::function очень сильно и std::function начнут обгонять std::shared_ptr.

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

И еще одно небольшое дополнение напоследок: думаю, ситуация, когда заявка будет иметь всего один метод handle, т.е. когда объект-заявка может быть представлена функциональным объектом один-в-один, является частным случаем. На мой взгляд, велика вероятность, что у объекта-заявки будет несколько виртуальных методов. Если не сразу, то в процессе эволюции кода. И если иерархия конкретных заявок изначально представлена в виде объектной иерархии, то произвести модификацию кода с объектами будет проще, чем с std::function.