суббота, 31 декабря 2016 г.

[life.cinema] Очередной кинообзор (2016/12)

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

В конце туннеля (Al final del túnel, 2016). Мне очень понравилось. Можно, конечно, придраться к ряду моментов. Но просто не хочется.

Изгой-один: Звездные войны. Истории (Rogue One, 2016). Пожалуй, самое достойное продолжение саги "Звездные войны". Как по мне, так на голову выше прошлогодних ЗВ-7. Кроме довольно неожиданного для голливудского фильма финала меня еще очень порадовала тщательность проработки мелких деталей.

Спектральный (Spectral, 2016). Красочно, динамично. Если не вдумываться в сюжет, то очень даже пристойный фантастический боевик.

Новая эра Z (The Girl with All the Gifts, 2016). Хорошее дополнение в копилку фильмов про шустрых зомби, от которых не так-то просто отбиться.

Затаившись (Hidden, 2016). Оказалось очень даже неплохо. Только нужно обязательно досмотреть до конца, ибо лишь события в конце фильма компенсируют некоторую затянутость и уныние первой части фильма.

Меня зовут Джиг Робот (Lo chiamavano Jeeg Robot, 2015). Странный фильм, который оставляет ощущение "что же это было?" Причем в хорошем смысле. Вроде как по сюжету это сказочка для детей. Но сцены насилия и секса явно говорят о том, что фильм рассчитан на взрослую аудиторию. Вот и получается очень своеобразная сказка для взрослых.

Инкарнация (Incarnate, 2016). Двойственные ощущения. С одной стороны достойный образчик жанра "изгнания демонов". Но чего-то не хватило. Да и самый-самый финал оказался слишком предсказуем.

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

Человек человеку волк (Dog Eat Dog, 2016). Редкой укуренности фильм. И если с участием Николаса Кейджа все понятно, он сейчас во всяком дерьме снимается, то вот как туда занесло Уиллема Дефо -- вот это загадка.

понедельник, 26 декабря 2016 г.

[prog.thoghts] Еще несколько слов на тему однопоточного SObjectizer Environment

Тема однопоточного SObjectizer Environment сидит в голове уже довольно давно. К сожалению, она не так проста, как это представлялось ранее. Поэтому руки дошли только сейчас.

Почему тема не так проста. Имеет смысл рассматривать три ситуации:

[prog.thougths] Разрешать ли использование private dispatchers с однопоточным SObjectizer Environment?

В процессе работы над SO-5.5.19 возник вопрос, при поиске ответа на который хотелось бы учесть не только лишь собственное мнение. Так что комментарии всячески приветствуются.

Суть вот в чем. В SO-5.5.19 делается поддержка однопоточного SObjectizer Environment. Однопоточный -- это значит, что такой SOEnv не создает никаких новых рабочих нитей, а все свои операции (т.е. обслуживание событий агентов, таймеров и операций дерегистрации коопераций) выполняет на той нити, на которой однопоточный SOEnv был запущен. Грубо говоря, запустили SOEnv на главной нити приложения, и все события происходят только на главной нити.

Можно отдельно разговаривать о том, зачем и когда такое может потребоваться. Но речь сейчас не об этом. Будем считать, что однопоточный SOEnv нужен, а значит его следует сделать. Но тут всплывает проблема диспетчеров.

Одна из отличительных черт SO-5 -- это возможность создавать экземпляры дополнительных диспетчеров и привязывать агентов к этим диспетчерам. Например, можно создать экземпляр thread_pool диспетчера и привязать 100500 агентов к этому диспетчеру. Потом создать экземпляр active_obj диспетчера и привязать еще пять агентов к нему (каждый агент при этом будет работать на своей собственной нити). А потом создать экземпляр prio_one_thread::strictly_ordered диспетчера и привязать к нему еще 50 агентов. В итоге в SOEnv окажется сразу несколько диспетчеров и куча агентов, каждый из которых работает на своем диспетчере.

Диспетчеры в SO-5 делятся на два вида: public и private диспетчеры.

У public диспетчера должно быть уникальное имя. Экземпляр public диспетчера явным образом регистрируется в SOEnv вместе со своим уникальным именем. И затем по этому имени может быть получен из SOEnv. Грубо говоря, SOEnv знает про все public-диспетчеры. Более того, SOEnv сам запускает и останавливает public диспетчеры.

А вот у private диспетчера имени нет. И экземпляр private диспетчера в SOEnv не регистрируется. Поэтому SOEnv вообще не знает, сколько private диспетчеров существует в данный момент. Соответственно, SOEnv не управляет private диспетчерами.

Собственно, вопрос такой: если пользователь запускает у себя в приложении однопоточный SOEnv, то можно ли разрешать пользователю создавать private диспетчеров для такого SOEnv и привязывать агентов к private диспетчерам в рамках этого SOEnv?

Интересует ответ на этот вопрос с концептуальной точки зрения.

С одной стороны, странным выглядит желание создавать дополнительные private диспетчеры, если выбран однопоточный SOEnv. Казалось бы: хочешь иметь private диспетчеры -- создавай многопоточный SOEnv, а если потребовался именно однопоточный SOEnv, то не создавай private диспетчеры. Просто и логично.

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

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


Получается, что на этот вопрос есть две точки зрения. Хотя мне кажется, что одна из них неправильная. Поэтому прошу читателей помочь определиться с тем, какая именно неправильная.

Возможно, я что-то сумбурно и непонятно описал. Поэтому уточняющие вопросы приветствуются -- с удовольствием разверну тему более подробно.

понедельник, 19 декабря 2016 г.

[prog.c++] Разбор asfikon's "C vs C++". Часть 5.

Завершаем ранее начатую тему. Сегодня разберем оставшиеся цитаты, благо их немного. А в завершении я перечислю свой перечень условий, при которых в современных реалиях выбор языка C предпочтительнее выбора C++.

Приступим.

пятница, 16 декабря 2016 г.

[prog.c++] Разбор asfikon's "C vs C++". Часть 4.

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

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

Итак, приступим.

четверг, 15 декабря 2016 г.

[prog] Вопрос по организации связей между узлами/процессами на базе открытых стандартов и/или протоколов

Допустим, что у нас есть десяток-полтора узлов внутри локальной сети. На каждом узле работает свой набор прикладных процессов. Разных процессов. Процессы должны обмениваться между собой данными. Например, процесс A должен отослать сообщение процессу B, процесс B -- процессу C, процесс C -- процессу D, процесс D -- процессам A и B. При этом процессы A и B могут работать на одном узле, процессы C и D -- на разных узлах. Взаимодействие может быть как в режиме fire-and-forget, так и в режиме request-reply. Но больше, все-таки, в режиме fire-and-forget. Поток сообщений более-менее приличный: от нескольких десятков тысяч сообщений, до сотни тысяч. Размер сообщений относительно небольшой, порядка 1.5-2 килобайт.

Сходу приходит в голову, что организовать такое взаимодействие можно на базе какого-то MQ-брокера. Т.е. на каком-то узле поднимается MQ-шный брокер, к которому подключаются все остальные, все процессы подписываются на соответствующие топики. При этом процессу A совершенно не нужно знать, где именно работает процесс B. Процесс A просто отсылает свое сообщение брокеру, а процесс B получает сообщения от брокера.

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

Поэтому можно смотреть и в сторону peer-to-peer взаимодействия. Например, на базе модного нынче REST-а. Получится, что в каждом процессе открывается HTTP-вход, на который и приходят REST-запросы. Процесс A делает REST-запрос к процессу B, процесс B делает запрос к процессу C и т.д. Все знают URL-ы процессов, с которыми взаимодействуют и могут сделать запрос напрямую. Что хорошо.

Проблема с REST-ом в том, что он отлично ложится на взаимодействие request-reply. А вот для fire-and-forget уже не так хорошо: зачем, спрашивается, делать отдельный HTTP POST, пусть даже и по keep-alive соединению, если ответ нам все равно не нужен (как и подтверждение доставки)? Понятное дело, что современные HTTP-сервера способны обрабатывать сотни тысяч запросов на одном ядре. Но все-таки...

Как я понимаю, под такие задачи хорошо ложится, например, система взаимодействия процессов в Erlang-е. Там процесс A знает PID процесса B и просто отсылает B сообщения. Если A и B оказались на одной ноде в рамках одной Erlang VM, то для доставки сообщения вообще никаких внешних IPC не будет задействовано. Проблема в том, что это Erlang-овая кухня, которая не подойдет, если нужно организовать интероперабильность процессов, реализованных на разных языках программирования (например, C++, Java, Python).

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

PS. Вопрос вызван не какой-то конкретной задачей, а попыткой осмыслить подходы к реализации нескольких систем, о которых довелось узнать.

понедельник, 12 декабря 2016 г.

[prog.c++] Разбор asfikon's "C vs C++". Часть 3.

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

четверг, 8 декабря 2016 г.

[life.cinema] Очередной кинообзор (2016/11)

Пусть с опозданием, но все-таки очередной отчет о просмотренных фильмах. В начале те фильмы, что мне понравились больше, в конце -- те, которые понравились меньше и совсем не понравились.

28 панфиловцев (2016). Нужно просто идти и смотреть. Очень достойное кино.

Коллектор (2016). Мне понравилось.

Антропоид (Anthropoid, 2016). К западным фильмам на тему Второй Мировой отношусь с настороженностью. Но этот, как мне показалось, вполне достойный фильм.

Морган (Morgan, 2016). Неплохо. Отдельным актерам за их отличную игру я бы вообще сказал отдельное спасибо.

Сноуден (Snowden, 2016). Оливер Стоун, конечно, мастер. Хотя сама история мне лично была не очень интересна, но не отдать дань уважения мастерству режиссера не могу.

Парни со стволами (War Dogs, 2016). Прикольный фильм. Прикольный в том плане, что сопереживания нет вообще ни к одному герою.

Ледокол (2016). Ждал большего.

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

Чудо на Гудзоне (Sully, 2016). Снято, конечно, мастерски. Но смотреть не очень интересно, потому что "фильм немного предсказуем" (с). Понятно, чем все в итоге закончится, отчего происходящее на экране не цепляет.

Зачинщики (Masterminds, 2016). Нормально. Но мне показалось, что фильм больше держится на обаянии нескольких актеров, чем на сюжете или шутках.

Бен-Гур (Ben-Hur, 2016). Красочно. Но настолько все шаблонно, линейно и предсказуемо, что это убивает все остальные впечатления от фильма.

С вещами на вылет (Débarquement immédiat!, 2016). Незамысловатая французская комедия. В меру тупая. Местами смешная. Как по мне, так не достаточно смешная для комедии.

Деньги (Money, 2016). Так себе. Можно и не смотреть.

среда, 7 декабря 2016 г.

[prog.c++] Разбор asfikon's "C vs C++". Часть 2.

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

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

вторник, 22 ноября 2016 г.

[prog.c++] Разбор asfikon's "C vs C++". Часть 1.

Итак, поскольку на удивление большое количество желающих захотело послушать разбор тезисов статьи ув.тов.asfikon-а "Почему не лишено смысла писать код на C, а не на C++", то начнем выполнять обещание. Для того, чтобы не было завышенных ожиданий, сразу обозначу рамки, в которых будет вестись повествование. Посты с разбором "C vs C++" будут представлять из себя цитаты из оной статьи с моими комментариями о том, что в данной цитате представляет ценность, а что можно смело отправлять в /dev/null. Такой формат предполагался мной изначально. Приношу свои извинения, если кто-то ждал чего-то сильно другого. Впрочем, в комментариях можно оставлять свои соображения о том, какие темы вы бы хотели увидеть более раскрытыми. Может быть со временем получится дойти и до них.

Disclaimer. Есть у меня подозрение, что по большей части придется повторять скучные, банальные и давно известные вещи. Но, похоже "вот и выросло поколение"... Так что без скучных банальностей не обойтись.

Прежде чем перейти к конкретным цитатам, нужно обозначить важный момент, который позволит лучше понять, почему статьи, подобные разбираемой здесь "C vs C++", некорректны в принципе, безотносительно элементов бреда, спекуляций, подтасовок и передергиваний внутри.

суббота, 19 ноября 2016 г.

[prog.c++] Нужно ли делать подробный разбор статьи "Почему не лишено смысла писать код на C, а не на C++"?

Upd. Первая статья серии здесь: Разбор asfikon's "C vs C++". Часть 1..

В начале года я уже писал о странной тенденции -- активной агитации за использование чистого C вместо C++. Похоже, за прошедшее время ситуация стала только хуже :(

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

Так вот, в одном из флеймов в качестве аргумента была дана ссылка на статью ув.тов.asfikon-а "Почему не лишено смысла писать код на C, а не на C++". Тогда я не стал особо заострять внимание на данной статье (ограничившись лишь парой ироничных комментариев). Очевидно, что я недооценил пагубность ее влияния.

Вчера специально просмотрел статью еще раз. Блин, ну какой же бред там написан! Но ведь кто-то воспринимает написанное там всерьез. И это пугает.

Посему, есть мысль взять и обсудить основные тезисы данной статьи.

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

Пожалуйста, найдите способ высказать свое мнение: комментарием или +1, распространением данного поста, личным сообщением или еще как-нибудь.

Отдельно подчеркну, что основной целью предполагаемой серии постов будет не попытка доказать, что C++ отличный язык, для которого нет альтернативы. А рассказать о C++ объективно, не скрывая недостатки, но и не обмазывая говном достоинства.

пятница, 18 ноября 2016 г.

[prog.c++.bicycle] Пытаюсь наваять совсем простенькую функцию n_times

Когда-то уже заходила речь (кажется в G+), что хорошо было бы иметь в C++ функцию n_times для того, чтобы не нужно было циклы выписывать руками. Т.е. вместо того, чтобы писать:

const auto iterations = std::stoul(argv[1]);
forunsigned long i = 0; i != iterations; ++i )
   do_some_action();

А можно было бы изобразить что-то вроде:

n_times( std::stoul(argv[1]), []{ do_some_action(); } );

Ну и в итоге дозрел до того, чтобы добавить n_times в нашу маленькую библиотечку cpp_util. Самый первый, черновой вариант, выглядит вот так:

templatetypename COUNT_TYPE, typename LAMBDA >
void
n_times( COUNT_TYPE n, LAMBDA && body )
   {
      loops_details::ensure_non_negative( n );
      for( ; n; --n )
         body();
   }

В нем вспомогательная функция ensure_non_negative в случае, если COUNT_TYPE является знаковым типом, проверит, чтобы n имел неотрицательное значение. В случае же отрицательного значения будет порождено исключение std::invalid_argument.

И вот тут у меня есть сомнения. Ведь такая проверка может вести к дополнительным накладным расходам. В каких-то случаях компилятор ее выбросит. Но в каких-то оставит. А это может не понравится некоторой части потенциальных пользователей. Посему есть мысль пойти по такому варианту:

using namespace cpp_util_3;

// Пользователь не против получить исключение, если ошибся
// со значением аргумента.
n_times< checked_loop >( std::stol(argv[1]), []{ do_some_action(); } );

// Пользователь зуб дает, что все будет чики-пуки.
n_times< unchecked_loop >( std::stol(argv[1]), []{ do_some_action(); } );

Или по такому:

using namespace cpp_util_3;

// Пользователь не против получить исключение, если ошибся
// со значением аргумента.
n_times( untrusted_n(std::stol(argv[1])), []{ do_some_action(); } );

// Пользователь зуб дает, что все будет чики-пуки.
n_times( trusted_n(std::stol(argv[1])), []{ do_some_action(); } );

Интересно мнение читателей: вам бы какой вариант был бы более удобен? Вообще без проверок? С проверками всегда? С отключаемыми проверками?

При этом если n -- это беззнаковое значение, то оно не проверяется вообще. Тут в дело вступает совсем простая шаблонная магия, которая устраняет избыточные проверки прям в compile-time.

PS. Кроме n_times еще хочется сделать up_to (или for_every_i):

using namespace cpp_util_3;

for_every_i( 010, [](auto i) { std::cout << i << std::endl; } );

Тут так же можно подумать на счет checked_loop/unchecked_loop...

понедельник, 14 ноября 2016 г.

[prog.flame] Прочел тут давеча "Why Rust"

Проглотил давеча за пару-тройку дней небольшую бесплатную книженцию "Why Rust" от O'Reilly. Книжица толковая. Собрает воедино все основные плюшки Rust-а в небольшом объеме текста. Что для меня очень большой плюс, т.к. эпизодические подходы к разным частям официальной документации позволяли разобраться в том или ином отдельном аспекте, но не создавали целостной картинки того, чем же должен брать Rust. Посему, если кто-то хочет составить себе впечатление об этом языке, но не хочет штудировать официальный "The Book", то имеет смысл взять и одолеть "Why Rust".

После прочтения у меня сформировалось несколько пунктов, по которым можно что-то сказать.

  1. Блин, синтаксис реально имеет значение. Первое, что отталкивает от желания связываться с Rust-ом (и отталкивает весьма сильно) -- это непонятное для меня желание экономить на всем. fn вместо func или function, impl вместо implementation, mut вместо mutable, u8 вместо uint8 и т.д.

    Казалось бы, ну синтаксис и синтаксис, можно привыкнуть к большой вариативности синтаксисов, почему же Rust-овский синтаксис так раздражает?

    Думаю, что это из-за высокой плотности содержимого в Rust-овском коде. Т.е. когда ты видишь что-то вроде:

    fn firsts<'a, 'b>(x: &'a Vec<i32>, y: &'b Vec<i32>) -> (&'a i32, &'b i32)

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

    func firsts<borrow A, borrow B>(x: borrow<A> Vector<int32>, y: borrow<B> Vector<int32>) -> tuple<borrow<A> int32, borrow<B> int32>

    Upd. Или вот так:

    func firsts(x Vector<int32> in A, y Vector<int32> in B) -> tuple<int32 in A, int32 in B>

    То код читался бы быстрее, особенно при наличии подсвеченного синтаксиса: распознавание отдельных частей выражения было бы проще.

    Да и вообще, если язык задумывался как безопасная альтернатива C/C++, то язык следовало бы делать максимально похожим по синтаксису на C и C++, тем более, что шаблоны в С++ и так позволяют записывать довольно сложные вещи. Так что можно было бы придумать нечто вроде:

    template<borrow A, borrow B>
    tuple<borrow<A, int32>, borrow<B, int32>>
    firsts(borrow<A, vector<int32>> x, borrow<B, vector<int32>> y)

    Имхо, мимикрия возможностей Rust-а под синтаксис C++ позволила бы не только упростить вход в язык для C++ников. Но и позволила бы с намного меньшими затратами переделывать уже существующий код под Rust. Если у меня 10MLOC кода на C++, то, понятное дело, на Rust я это все конвертировать не буду. Но, если у меня всего 25KLOC, то вместо того, чтобы переписывать все на Rust заново, я бы мог просто тщательно пройтись напильником по уже имеющемуся у меня коду и с минимальными услилями превратил бы C++ный код в Rust-овый код. Кстати говоря, когда-то на небольших программках я так поступал с переделкой C++ного кода в D-шный код.

  2. У меня складывается впечатление, что Rust стоит относить к той же группе, что и языки вроде Eiffel и Ada. Т.е. на них нельзя "наговнякать что-то по-быстрому". Нужно сесть, подумать, основательно разобраться в том, что нужно сделать, как это сделать, почему именно так. Потом еще побороться немного с компилятором, чтобы договориться о том, где ты ему веришь, а где он тебе должен верить. В итоге получится работающий код, в стабильность и надежность которого ты более-менее веришь (хотя так это или нет -- это отдельный вопрос, т.к. отсутствие утечек памяти и повисших указателей вовсе не гарантирует корректную работу приложения). Но все это будет не быстро, а по-началу и не легко.

    Так что да, если хочешь, чтобы все было "глобально и надежно" и у тебя есть возможность умножить свои сроки и бюджеты на 1.5, а в замен получить увеличение коэффициента спокойного сна на 15-20%, то Rust может быть хорошим выбором.

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

  3. Есть сильное ощущение, что Rust сейчас пользуется тем, что это новый язык, без груза совместимости с чем-то еще (как у C++ с C) и без необходимости поддерживать туеву хучу легаси кода. Поэтому в Rust-е все можно сразу сделать хорошо и "правильно". Отсюда и появляются нештяки, вроде встроенных в язык АлгТД, модулей и системы Cargo, единственного компилятора для всех платформ и пр.

    Пытаясь сопоставить C++ и Rust понимаешь, что не смотря на то, что в C++ можно обеспечить довольно таки высокий уровень безопасности кода (смотрим хелперы, вроде not_null и иже с ними), все-таки без серьезной модификации языка в C++ не получится завести те же самые АлгТД, а так же избавиться от таких вещей, как возможность вернуть ссылку на временный объект, который будет разрушен после возврата. Здесь Rust находится в заведомо лучшей позиции, чем C++.

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

    let a = ...;
    let b = a;

    приводит к тому, что содержимое a переносится в b. Но не всегда. Если a принадлежит примитивному типу или типу, реализующему трейт Copy, то произойдет копирование. Т.е. в каких-то случаях после b=a значением a пользоваться нельзя и компилятор будет бить за это по рукам. А в каких-то случая -- можно. Имхо, такая неоднозначность не есть хорошо, в частности для обобщенного программирования.

    Отдельным вопросом, о который уже сломано множество копий, является подход к обработке ошибок в Rust-а. Типа, везде должен возвращаться Result. Но и паники есть. Поэтому тем, кто озабочен написанием повторно-используемых библиотек, которые будут использоваться хрен знает в каких обстоятельствах, обеспечению exception safety (или правильно называть panic safety?) в Rust-е придется уделять столько же внимания, как и в C++. Но при этом еще и нужно будет долбаться с протягиванием кодов ошибок. Т.е. придется еще и писать код в духе "без try! ни строчки", как, например, это показывается в стандартной документации Rust-а:

    let f = try!(File::create("foo.txt"));
    let metadata = try!(f.metadata());
    let permissions = metadata.permissions();
    println!("permissions: {}", permissions.mode());

    Правда, в намедни вышедшем Rust 1.13 уже можно заменить try! вопросиками:

    let f = File::create("foo.txt")?;
    let metadata = f.metadata()?;
    let permissions = metadata.permissions();
    println!("permissions: {}", permissions.mode());

    Но тут мы опять приходим к тому, что в Rust-е имеет значение каждая закорючка в коде.

    Опять же, возьмем обобщенное программирование, в котором в Rust-е можно назначать аргументам шаблонов требования -- какие трейты должен поддерживать шаблон. Это сильно напоминает уже готовые concept-ы, которые в C++ все никак не могут завезти. Отсутствие ограничений на параметры шаблонов в C++ приводят к более сложной диагностики ошибок. Но, при этом, в C++ действительно возможен duck typing в compile-time: ну буквально, если шаблон ожидает "утку" в качестве параметра, то ему можно подсунуть все, что угодно, если это хоть сколько-нибудь похоже на "утку". И в этом огромная сила C++ных шаблонов и причина успеха шаблонов в C++. А вот в Rust-е, если шаблон ждет "утку", то и подсовывать ему нужно будет именно, что "утку". Может для тех, кто переходит на Rust с Java или C# это кажется нормальным, а вот мне это кажется очередным ограничением. Очередной попыткой ударить разработчика по рукам (см. пункт №2 выше).

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

  4. В самом начале книги "Why Rust" автор сделал заход, который мне показался жульническим и из-за которого я ко всему остальному материалу относился с изрядной долей скепсиса. Речь о наезде на понятие UB (undefined behavior) в языках C и C++. Мол, если вы в C/C++ обратитесь за пределы массива, то возникнет UB. А вот в Rust-е, мол, никакого UB -- вы получите вполне себе панику в run-time.

    Как по мне, так странный заход. Из категории, "мой дедушка боролся за то, чтобы не было бедных, а не за то, чтобы не было богатых". Типа того, что у программиста руки все-равно кривые, поэтому мы не будем заморачиваться тем, как вообще сделать невозможными выходы за пределы буфера. Мы просто сделаем контроль в run-time. А за счет того, что у нас есть итераторы, а так же компилятор умный, мы большинство таких проверок выбросим и вы даже никаких дополнительных накладных расходов не получите.

  5. Есть у меня подозрение, что подход разработчиков Rust-а можно выразить так: "Мы подумали о том, что вам может пригодится, а что не может, и дали вам то, чем вам стоит пользоваться. Этого вам хватит на все времена." Только вот я не уверен, что они [разработчики Rust] правы в своих убеждениях. Это касается разных вещей в языке. Начиная от необходимости ухода в unsafe для написания банального двусвязного списка, и заканчивая подходом к обеспечению thread safety. Так, есть у меня подозрения, что некоторые C++ные навороты, к которым приходится прибегать при работе с реальными проектами, в принципе возможны в Rust. Посему, если в реальной жизни придется столкнуться с чем-то нетривиальным (вроде реализации своего many-readers/single-writer spin-lock-а), то скорее всего с Rust-ом придется бороться, т.е. его сильные стороны могут начать работать против разработчиков.

Пора подводить сухой остаток. При наличии свободного времени, было бы полезно попробовать переписать какой-нибудь из маленьких C++ных проектиков и посмотреть на практике как это -- программировать на Rust-е. Но времени нет, а C++ного кода, который востребован и нуждается в развитии -- больше чем нужно. Посему смысла сейчас бросаться в Rust для меня нет. Не хочу сказать, что не верю в перспективы Rust-а и что у него нет шансов. Скорее всего шансов как раз предостаточно. Слишком уж много C++хейтеров сейчас вынуждены писать на C++ и страдать. Понятно, что большинство из них не имеет никакого влияния на выбор языка реализации для проектов. Тем не менее, Rust может найти свое место под Солнцем (и, скорее всего, найдет). Только вот у меня нет пока желания с Rust-ом связываться. Если Rust достигнет успеха, можно будет на него переключиться. Но пока этого не произошло, дальнейшая работа с C++ выглядит перспективнее.

воскресенье, 13 ноября 2016 г.

[business] Ищу примеры документов "Technical Assistance Agreement" и/или "Support Service Agreement"

Знаю, что некоторые компании бесплатно выпускают OpenSource-продукты под пермиссивными лицензиями (BSD, MIT, Boost и пр.), а продают техподдержку и консультации. Например, есть бесплатная библиотека POCO (не самая плохая, кстати говоря) и есть компания Applied Informatics, которая стоит за POCO и которая продает техподдержку пользователям POCO. Текст соглашения о такой техподдержке можно найти в виде PDF-ки на сайте Applied Informatics.

Поскольку мы выпускали, выпускаем и будем выпускать SObjectizer под BSD-лицензией, которая разрешает бесплатно использовать SObjectizer в каких угодно проектах, хоть открытых, хоть закрытых, то есть мысль попробовать предгалать платную техподдержку для SObjectizer. Для того, чтобы понять, как это все оформить, хочется ознакомиться как можно с большим количеством документов типа "Technical Assistance Agreement", "Support Service Agreement" и тому подобных. Но документов, касающихся техподдержки именно открытого, бесплатного ПО.

Буду признателен за ссылочки на подобные документы, которыми читатели поделятся в комментариях. Заранее спасибо!

пятница, 11 ноября 2016 г.

[software.business.thoughts] Очередное откровение от Св.Маркетинга...

...или N-ое подтверждение мудрости "век живи, век учись, а дураком помрешь".

SObjectizer -- это небольшая, но сложная штука. Понятное дело, что пытаясь продвигать SO-5 в массы, невольно хочется получить "признание заслуг" от опытных разработчиков, от гуру, которые собаку съели в теме многопоточности, а может и не одну. Это же естественно: ты проделал большую и непростую работу, оценить которую могут далеко не только лишь все, и положительная оценка от опытного проффи выглядит как заслуженное признание проделанной работы.

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

А это означает, что "признание" нужно искать не среди многоопытных гуру, а среди зеленых новичков, для которых написание многопоточного кода -- это действительно непонятно, сложно и больно. А это означает, что и маркетинговые материалы нужно готовить с учетом совсем другой аудитории. Грубо говоря, нацеливаться нужно на "чайников", которых каким-то боком занесло в C++, но которые еще не успели набраться достаточного самомнения опыта, чтобы самостоятельно принимать решения "в этой разработке мы применим такие-то и такие-то подходы и будем использовать такие-то и такие-то инструменты".

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

Нет, ориентируясь на чайников нужно вести рассказ по-другому, начиная с самых основ. Нельзя просто сказать, что многопоточное программирование сложно. Нужно показать это на простейших примерах. И на этих же примерах затем показать, как асинхронные сообщения облегчают жизнь. А потом уже рассказать, что при работе с асинхронными сообщениями есть свои модели, например, Actor Model и Comminicating Sequential Processes. И что есть готовые инструменты (готовый инструмент, вообще-то), которые отнюдь не противопоставляют эти модели друг другу, а позволяют использовать и то, и другое. И все это уже собрано в одном флаконе, распространяется бездвоздмедаром и может использоваться где угодно, влючая закрытое программное обеспечение... :)

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

четверг, 10 ноября 2016 г.

[book.business] Добил книгу "Кодекс выживания"

Закончил затянувшееся чтение книги "Кодекс выживания" (авторы: Дэвид Хэнна, Георгий Мелик-Еганов и Максим Ильин).

Как мне показалось, книга состоит из воды и банальностей в духе "делайте все правильно и все у вас будет хорошо" в перемешку с интересными примерами из жизни.

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

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

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

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

вторник, 8 ноября 2016 г.

[prog.flame] Шаблоны, множественное наследование, policy classes... В общем, маленькая иллюстрация того, за что я люблю C++ :)

Просто малюсенький фрагментик из одного из проектика:

namespace probe_common {

template<
   // Какой диспетчер нужен агентам-пробникам.
   typename PROBE_DISP_POLICY,
   // Как быть с child_deadliner-ом.
   typename CHILD_DEADLINER_POLICY >
class a_studies_manager_t
   :  public so_5::agent_t
   ,  protected PROBE_DISP_POLICY
   ,  protected CHILD_DEADLINER_POLICY
{...};

}

namespace probe_X {

using base_studies_manager_t = probe_common::a_studies_manager_t<
      probe_common::one_thread_probes_disp_policy_t< probe_disp_name_t >,
      probe_common::no_child_deadliner_policy_t >;

class a_studies_manager_t : public base_studies_manager_t
{...};

}

PS. Вообще, читая профильные форумы, на которых люди разной степени адекватности и вменяемости хейтят C++ и агитируют кто за Go, кто за Rust, кто за, прастихоспади, plain old C, у меня складывается ощущение, что владение C++ -- это конкурентное преимущество :) Поэтому не нужно никого агитировать за использование C++, меньше народу -- больше кислороду ;)

четверг, 3 ноября 2016 г.

[prog.flame] Потролю хейтеров множественного наследования :)

Кусочек кода из реального проекта:

class has_tlv_with_value_tag_t
   :  public cls_3::tags::tag_scalar_t< tlv_maniputators_details::cls_tag_type_t >
   ,  public script_parsing_context_holder_t
   ,  public tlv_maniputators_details::tag_id_constraints_holder_t
   ,  private tlv_maniputators_details::encoding_helpers_t
   {

И да, ни один из классов предков не является абстрактным классом (интерфейсом в терминологии Java), в каждом из них есть и атрибуты, и методы.

понедельник, 31 октября 2016 г.

[business] А вот по поводу современных, модных и молодежных сайтов...

От сайтостроения очень далек. Однако, даже для меня заметно, что многие современные сайты (будь то сайты компаний целиком, или же сайты посвященные отдельным продуктам) построены по одному шаблону. Вроде как у этого безобразия даже определенное название есть: lending page (она же "целевая страница"). Что лично меня не радует. Но, с большой долей вероятности, это мои личные тараканы.

А вот что по этому поводу думают уважаемые читатели?

Этот подход, этот самый landing page, -- это на самом деле такой прорыв в маркетинге, что без него никак?

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

Т.е. хочется понять, имеет ли смысл придумывать что-то свое уникальное, дабы выделиться на общем фоне одинаково ярких, бесполезных и не очень удобных однотипых landing pages? Или не стоит рыпаться и дуть против ветра?

PS. Интерес сугубо практический, но в детали вдаваться пока не хочется.

[life.cinema] Очередной кинообзор (2016/10)

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

Расплата (The Accountant, 2016). Мне показалось слегка затянуто, но вполне смотрибельно.

Девять жизней (Nine Lives, 2016). Милая, вполне себе предсказуемая комедия. Посмотрел с удовольствием.


Джек Ричер 2: Никогда не возвращайся (Jack Reacher: Never Go Back, 2016). Ожидал большего. Посмотреть вполне можно, но остается ощущение, что на нормальный сюжет и сценарий просто не хватило денег.

Механик 2: Воскрешение (Mechanic: Resurrection, 2016). Вот уж действительно: видел один фильм с Джейсоном Стейтемом -- видел все. Отличное кино для того, чтобы выключить мозги и посмотреть на чувака, круче которого только горы и яйца.

Все о мужчинах (2016). Ждал худшего, но оказалось вполне себе нормальное кино. Без изысков, конечно. Но могло быть и хуже.

ARQ (2016). Фильм из категории дешево, но сердито. Посмотреть можно, хотя масштабности не хватило.

Нерв (Nerve, 2016). Мне показалось, что фильм рассчитан на гораздо более молодую аудиторию. О том, что посмотрел не жалею, но и не могу сказать, что понравилось.

Искусственный интеллект. Доступ ограничен (I.T., 2016). Предсказуемо и не очень интересно.

В долине насилия (In a Valley of Violence, 2016). Попытка снять атмосферный, но недорогой и не масштабный вестерн. Попытка так себе.

Не дыши (Don't Breathe, 2016). Тот самый случай, когда "замах на рубль, удар на копейку". Очень добротное и многообещающее начало, которое заканчивается каким-то полным маразмом.


Инферно (Inferno, 2016). Мне показалось, что это очень дорогостоящая бредятина.

Ну и напоследок нечто под названием "Кингсглейв: Последняя фантазия XV". В свое время довольно приятные впечатления уровнем графики оставил первый анимационный фильм "Последняя фантазия", снятый 15 лет назад. Прошло немало времени, уровень графики вышел, как по мне, на совершенно потрясающий уровень. А вот сюжет и все остальное, к сожалению, просто пробило дно и устремилось куда-то в сторону минус бесконечности. Просто непонятно, как можно было вложить столько труда в такую редкостную муть...

суббота, 22 октября 2016 г.

[prog.c++] Слайды моего доклада на CoreHard C++ Autumn 2016

Для тех, кто не смог поприсутствовать на самом докладе:

вторник, 18 октября 2016 г.

[prog.wow] Самое удивительное для меня в судьбе Erlang-а в Ericsson-е между 1986-ым и 1995-ым

Читаю сейчас урывками историю Erlang-а от Джо Армстронга. Одну вещь ну очень тяжело лично мне осознать, пока не получается и все.

Дело в том, что судя по тому, что рассказывает Армстронг, Erlang в Ericsson-е не выходил за пределы лабораторий до 1995-го года. При том, что собственно над тем, что стало Erlang-ом Армстронг начал работать в 1986 (а вообще к проблематике создания языка для упрощения разработки софта для телефонии он подключился на год раньше, в 1985-ом). В самом конце 80-х были эксперименты по прототипированию на Erlang-е. В начале 90-х группа Армстронга убедила руководство начать раздавать Erlang заинтересовавшимся людям за пределами Ericsson-а. В 1993-ем вышла книга про Erlang. И Ericsson создал дочернее подразделение Erlang Systems AB для коммерциализации Erlang-а. Но в самом Ericsson-е Erlang был востребован в продакшене только в 1995-ом, когда стартовали AXD после неудачи проекта AXE-N.

Т.е. девять лет несколько разработчиков на зарплате Ericsson-а делали что-то, что сам Ericsson не использовал. И, особенно в первые два-три года, никто даже и не знал, во что это в итоге выльется.

Афигеть просто.

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

Внушаить.

воскресенье, 16 октября 2016 г.

[prog.memories] Любопытное из воспоминаний Джо Армстронга про историю Erlang

Увидел в статье "A History of Erlang" от 2007-го (бесплатная PDF-ка легко гуглится):

But the Smalltalk was very slow -- so slow that I used to take a coffee break while it was garbage collecting.

Т.е. Smalltalk был настолько тормознутым, что приходилось отвлекаться на чашечку кофе, пока Smalltalk занимался сборкой мусора. Как я понимаю, речь шла о Smalltalk для BSD Unix на Vax 11/750. В 1985-86 годах.

Забавно. Может кто-то из нынешней молодежи лучше поймет, почему в конце 80-х и в девяностых мейнстримом становились языки вроде C++.

четверг, 13 октября 2016 г.

[prog.wow] Новость про новый язык P от Microsoft

Собственно, вот сама новость: Microsoft Open-Sources P Language for Safe Async Event-Driven Programming. Небольшая цитата оттуда:

Microsoft describes P as a domain-specific language to model communication between components of an asynchronous system, such as an embedded, networked, or distributed system. A P program is defined in terms of finite state machines than run concurrently. Each of them has an input queue, states, transitions, a machine-local store, and can send asynchronous messages to the others.

Или, в моем корявеньком переводе на русский язык:

Microsoft описывает P как язык, заточенный под моделирование взаимодействия между компонентами в асинхронной системе, вроде встраиваемой, сетевой и распределенной системы. Программа в P определяется в терминах конечных автоматов, которые работают параллельно. Каждый из них имеет входящую очередь, состояния, переходы, локальное хранилище и может отсылать асинхронные сообщения другим [участникам].

Звучит как-то до боли знакомо...

Ба! Да мы же сделали это в SObjectizer-е фиг знает когда и уже много лет пользуемся полученными плюшками ;)

Правда, в P обещают верификацию. Вот чего у нас нет, того нет...

понедельник, 10 октября 2016 г.

[prog.c++] Статистика по использованию try-catch в исходниках SO-5.5.18

На волне темы про использование исключений подсчитал, как часто в исходниках последней стабильной версии SO-5.5.18 встречаются блоки try-catch. Общий объем ядра SO-5 порядка 25KLOC (не считая пустых строк и комментариев). Всего насчитал 25 блоков try (в двух-трех блоках по 2 секции catch). Из общего числа catch-ей:

  • в 10 случаях catch используется для преобразования одного типа исключения в другое. В нескольких из этих случаев перед пробросом нового исключения выполняются действия по очистке/откату операций;
  • в 7 случаях в catch-е иницируется вызов std::abort() (перед этом зачастую идет логирование проблемы);
  • в 4-х случаях исключение "проглатывается". В двух из них предварительно логируется;
  • в 3-х случаях ловятся исключения, выпущенные из обработчиков событий агентов. В этих catch-ах происходит то, что описывалось в свежей статье на Хабре;
  • в одном случае ловится исключение, выпущенное из обработчика события агента, для фиксации этого исключения в std::promise. Этот сценарий используется для синхронного взаимодействия агентов;
  • в одном случае используется логика на исключениях: с помощью исключения разрывается цикл выборки событий из очереди одного из диспетчеров. Оказалось, что такая реализация цикла самая простая;
  • и в одном случае catch используется для эмуляции noexcept для старых VC++ компиляторов.

В общем, получается где-то по одному try-catch на тысячу строк кода.

Отдельно можно сказать про случаи с проглатыванием исключений. В двух из них исключения логируются, но выбрасываются, т.к. исключение вылетает из нотификаторов регистрации и дерегистрации коопераций. Эти нотификаторы вызываются когда основная операция (т.е. либо регистрация, либо дерегистрация) уже завершена, была сделана попытка проинформировать пользователя об этом. Но не получилось. На основную операцию такой сбой повлиять не может, сделать что-то осмысленное с исключением уже нельзя, а прерывать все приложение через std::abort() в данном случае представляется слишком жестоким.

А вот два других случая с игнорированием исключений интереснее. Один из них такой (сорри за качество английского):

   //! Switching storage from map to vector.
   void
   switch_storage_to_vector()
      {
         // All exceptions will be ignored.
         // It is because an exception can be thrown on staged 1-2-3,
         // but not on stage 4.
         try
            {
               // Stage 1. New containers to swap values with old containers.
               // An exception could be thrown in the constructors.
               map_type empty_map;
               vector_type new_storage;

               // Stage 2. Preallocate necessary space in the new vector.
               // An exception can be thrown here.
               new_storage.reserve( m_map.size() );

               // Stage 3. Copy items from old map to the new vector.
               // We do not expect exceptions here at v.5.5.12, but
               // the situation can change in the future versions.

               // Use the fact that items in map is already ordered.
               std::for_each( m_map.begin(), m_map.end(),
                  [&new_storage]( const map_type::value_type & info ) {
                     new_storage.push_back( info.second );
                  } );

               // Stage 4. Swapping.
               // No exceptions expected here.
               m_vector.swap( new_storage );
               m_map.swap( empty_map );
               m_storage = storage_type::vector;
            }
         catch(...)
            {}
      }

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

Какова мораль? Да нет никакой морали. Просто любопытно стало. Думаю, что для библиотек небольшое количество try-catch -- это нормально. В прикладном кода плотность испрользования try-catch наверняка выше.

пятница, 7 октября 2016 г.

[prog.flame] Длина строки кода таки важная штука

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

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

Еще раз убедился в том, что ограничение на 78-80 символов для длины строки кода -- это вполне разумно.

PS. Длинная строка -- это когда 100+ символов.

вторник, 4 октября 2016 г.

[prog.c++] Официальный анонс конференции Corehard C++ Autumn 2016 в Минске

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


Добрый день, друзья!
22 октября сообщество CoreHard.by проведет очередную большую конференцию выходного дня, посвященную языку С++ и сопутствующим «хардкорным» технологиям. Спикеры из ведущих IT-компаний Беларуси, России и не только соберутся вместе, чтобы рассказать о своем опыте в разработке и тестировании. Мы собрали лучшие доклады на самые различные темы: модели акторов и бинарная совместимость, эффективная работа с JSON в С++, рефлексия для С++ и GMock framework, рассказы непосредственных участников о разработке Bing и PVS-Studio для Linux и многое-многое другое.
Приглашенные спикеры:
  • Антон Полухин (Яндекс, Москва) – активный разработчик C++ библиотек Boost, автор книги “Boost C++ Application Development Cookbook” и представитель в международном комитете по стандартизации С++ от России. Антон расскажет о том, как организовать рефлексию в C++14 на этапе компиляции без макросов и вспомогательной разметки.
  • Егор Кишилов (Microsoft, Редмонд, США) более 8 лет работает в Microsoft, все это время занимаясь разработкой поисковой системы Bing. Егор расскажет о том, как построена разработка в Microsoft и что из себя представляет поисковая система Bing.
  • Святослав Размыслов (PVS-Studio, Тула, Россия) руководит отделом, занимающимся разработкой ядра анализатора PVS-Studio для анализа C и C++ кода. Святослав расскажет о том, как создавалась версия PVS-Studio под Linux.
  • Евгений Охотников – независимый разработчик с более чем 20-летним стажем, занимается OpenSource-инструментарием для упрощения разработки многопоточных приложений на языке C++. Евгений расскажет о моделях акторов для С++.
Полную сетку докладов ищите на нашем официальном сайте.
Конференция состоится в субботу, 22 октября и будет проходить в два потока.
Совместно с компанией JetBrains мы проведем розыгрыш лицензий на продукты ReSharper C++, CLion, AppCode среди участников.
Друзья, регистрация обязательна, спешите зарегистрироваться наофициальном сайте конференции.
Приходите, будет интересно!
С уважением,
Команда CoreHard.by

понедельник, 3 октября 2016 г.

[prog.c++] Вопрос за двоичную сериализацию в С++

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

Что вы использовали в этих случаях?

Какой-то готовый инструмент, вроде asn1-компилятора, protobuf, thrift, cap'n'proto, cereal, boost::serialization или что-то другое? Писали все сами?

Насколько важна для вас была кросс-платформенность результирующего бинарного представления?


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

Буду признателен как за ответы на эти вопросы, так и на распространение ссылок на этот пост.

пятница, 30 сентября 2016 г.

[prog.flame] portfile.cmake из Vcpkg супротив рецепта для MxxRu::externals

Попробовал представить, как сделать адаптацию SO-5 под новую волшебную пилюлю от Microsoft под названием Vcpkg. Проблевался. Какую только херню, пардон май френч, народ готов жрать только потому, что эта херня от MS или от Google. Поразительно.

Суть Vcpkg в том, что под каждый проект, который хочется затянуть в этот самый Vcpkg, нужно создать файлик portfile.cmake, в котором будут находится инструкции по доставанию исходников этого проекта и по его сборке (если проект нуждается в сборке). Для примера покажу, как выглядит portfile.cmake для библиотеки Range-V3. И как это же самое выглядит в виде рецепта для MxxRu::externals.

Итак, portfile.cmake для Vcpkg:

include(vcpkg_common_functions)
set(SOURCE_PATH ${CURRENT_BUILDTREES_DIR}/src/Range-V3-VS2015-ede9ad367fd5ec764fecb039c874614bd908e6b6)
vcpkg_download_distfile(ARCHIVE
    URLS "https://github.com/Microsoft/Range-V3-VS2015/archive/ede9ad367fd5ec764fecb039c874614bd908e6b6.zip"
    FILENAME "range-v3-ede9ad367fd5ec764fecb039c874614bd908e6b6.zip"
    SHA512 e978c7694471d8616c248647b77689f377b3e2517347abde8629b140e5994de8bf686565a24cdd7dd222f325d43b775f5e478c91220dce75313985499b134637
)
vcpkg_extract_source_archive(${ARCHIVE})

file(COPY ${SOURCE_PATH}/LICENSE.txt DESTINATION ${CURRENT_PACKAGES_DIR}/share/range-v3)
file(RENAME ${CURRENT_PACKAGES_DIR}/share/range-v3/LICENSE.txt ${CURRENT_PACKAGES_DIR}/share/range-v3/copyright)
file(INSTALL ${SOURCE_PATH}/include DESTINATION ${CURRENT_PACKAGES_DIR} FILES_MATCHING PATTERN "*.hpp")
vcpkg_copy_pdbs()

Тоже самое для MxxRu::externals:

MxxRu::arch_externals :range_v3_vs2015 do |e|
  e.url 'https://github.com/Microsoft/Range-V3-VS2015/archive/ede9ad367fd5ec764fecb039c874614bd908e6b6.zip'
  e.sha512 'e978c7694471d8616c248647b77689f377b3e2517347abde8629b140e5994de8bf686565a24cdd7dd222f325d43b775f5e478c91220dce75313985499b134637'

  e.map_dir 'include/*' => 'dev/range-v3'
  e.map_file 'LICENSE.txt' => 'dev/range-v3/*'
end

Резюмируя. Если кому-то действительно нужно, чтобы SO-5 был доступен из портов Vcpkg, то дайте знать. Мы сделаем. Но только если это кому-то действительно нужно. Ибо Vcpkg выглядит как говно и пахнет как говно. А посему вмазываться в говно и сопровождать потом это говно просто так не хочется, только если на то будут причины.