Would you mind getting real or why online С++ tests suck

Dear Madam/Sir,

I appreciate you going into the trouble actually visiting this page.  This post represents this blog owner’s point of view on so-called “Online C++ tests” that are used by recruitment agents to select candidates and explains why its author does not take any of these tests anymore. The sole purpose of the post is to be referred to when he is asked to sit one of these to save him the time explaining his position on this issue over and over again. By writing this post, the author did not intend to insult anyone nor pay revenge of any kind to anyone.

Almost every good software developer can find themselves discussing a new exciting career™ opportunity with the potential employer or their agent. Nine from ten, the candidate will be asked to sit a test. A very easy one, should not be too much trouble, person of such experience will not have any problems completing it in no time, they are told. And this is what is terribly wrong about it. You will have problems. No matter how good you are.

I agree that some initial screening may be required. For example, company needs a junior software developer and they need to be sure that candidates understand basic concepts of certain programming language. In this case test will help. It simply must be well prepared, 100% accurate, 100% correct, 100% meaningful and also short, if not too much trouble. The problem is that most of the tests out there don’t have any of this characteristics. The bigger problem is that they are usually put together by those who have never worked in the software development. And the killer problem is that these tests are filled with inconsistencies, discrepancies or simply full of errors (I wanted to use more colorful language here, but this post is going to be a part of my CV, so I better don’t).

About a year ago I was asked to sit an online C++ test.  I had no objections then. I also was interested in the position. The first question was quite obvious. The second had 4 answers and three of them were correct, but according to the question, only one of them was supposed to be correct. I lost all the interest momentarily. I wanted to stop it right then, but I decided to continue. I don’t regret. At least, now I have the proof how bad these tests are . That’s what question number 4 was:

(more…)

Брейнбенч головного мозга

Внезапно позвонил очередной агентег с очередной lifetime opportunity. И ссылку на тест прислал. По С++.

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

Вот теперь сочиняю ответ. Кстати, не напомните, “нах$й” пишется раздельно, или слитно?

Рабоче-крестьянские зарисовки

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

(more…)

Историческое

По старой памяти установил DevPartner на VS 2010.

Это даже не УГ, это намного хуже.

А когда-то вполне себе рулезная штуковина была.

Оптимизированные грабли

Тут на днях коллеги подложили нам свинью.

#define true false    // happy debugging!

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

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

(more…)

Паттерн “observer” на tr1::function или почти настоящие делегаты

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

Но за удобство приходится платить. В данном случае расплачиваться приходится невозможностью реализовать отписку. И причина тому банально проста. Вот простейший пример

class Subject
{
   public:
       typedef std::tr1::function<void (const MyData&)> typeDelegate;

       void Subscribe(typeDelegate);
       void Unsubscribe(typeDelegate);
}

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

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

Отсутствие возможности сравнивать ставит жиирный такой знак вопроса на самой возможности отписки. Конечно, можно усложнить интерфейс субъектов и обязать подписчиков передавать какой-нибудь уникальный идентификатор при подписке и отписке. Таким идентификатором, например, может быть и указатель на подписчика, совсем как в классическом обсервере.

Делать так можно. Только это кривовато сразу по нескольким статьям. Поэтому нам нужно пойти другим путем.

Вышеозначенный делегат можно создавать динамически и заворачивать в умный указатель. А умные указатели уже можно сравнивать! Значит, получим

class Subject
{
   public:
       typedef std::tr1::function<void (const MyData&)> typeDelegate;
       typedef std::tr1::shared_ptr<typeDelegate> typeDelegatePtr;

       void Subscribe(typeDelegatePtr);
       void Unsubscribe(typeDelegatePtr);
}

Теперь, чтобы подписаться на события субъекта, подписчик должен сначала динамически создать объект типа typeDelegate, завернуть его в shared_ptr, а затем уже этот умный указатель использовать для подписки и отписки:

// Somewhere in subscriber's constructor, for example
Subject::typeDelegatePtr m_Delegate(
    new Subject::typeDelegate(bind(&Subscriber::Process, this, _1))
    );
//...
//   Subscribe for events on _pSubject
_pSubject->Subscribe(m_Delegate);
//
//
//   Unsubscribe from _pSubject
_pSubject->Unsubscribe(m_Delegate);

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

Как видно, если у объекта есть необходимость отписки, он должен сохранять оригинал делегата для этих целей. Если отписка не требуется (а такое бывает часто), локальная копия m_Delegate не нужна – временный экземпляр его можно будет создать при вызове Subscribe().

Можно еще сделать следующий финт ушами – слегка изменить интерфейсы и в субъект передавать не shared_ptr, а weak_ptr, образованный от оригинального умного указателя на делегат, который является членом класса-подписчика. При этом бесплатно решается проблема курицы и яйца: иногда требуется обеспечить, чтобы объект-подписчик автоматически отписывался при удалении, но никакой гарантии, что субъект еще жив, нет и быть не может. Достаточно лишь обеспечить, чтобы субъект проверял, не протухли ли “слабые” указатели (или делал им lock()) перед вызовом делегата, а подписчик владел оригинальным shared_ptr<typeDelegate>. При этом удаление подписчика будет вызывать инвалидацию всех инстанций weak_ptr, образованных от этого указателя, тем самым делая невозможным вызов убитого объекта через делегат, что и даст нам такую вожделенную возможность подписчика замести все свои следы даже без информации о том, на события каких объектов он подписан и живы ли они еще.

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

Fuck the standards!

TR1 уже давно вышел. Это хорошо. Студия 2008 и 2010 уже включают его по умолчанию. Это просто отлично.

Стандарт (а TR1 – это де-факто уже стандарт) – это всегда хорошо. Больше нельзя называться C++ программистом и закатывать истерики при виде безобидного bind. Теперь нужно либо напрячь мозги и таки освоить основы функциональщины, либо идти заниматься гуевой мышевозней.

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

Вот включили они bind в стандарт. И чо (что, шо, So what, нужное подчеркнуть)? А перегруженные операторы не включили! Бо не было их еще в бусте на момент подачи черновиков в стандарт. В итоге в TR1 вот так вот не сделать:

vector<Person> myVector;
//
// Some stuff here
//
vector<Person>::iterator iter = find_if(
myVector.begin(),
myVector.end(),
bind(&Person::GetLastName, _1) == "Pupkin");

А все из-за того, что тот bind, что в TR1, не перегружает оператор “==”, сцуко такой! В итоге, чтобы сделать то же самое, что на куске кода вверху, нужно городить двухуровневый bind с equal_to посередине, от вида которого даже у привычных к boost пассажиров может случится истерика:

vector<Person>::iterator iter = find_if(
myVector.begin(),
myVector.end(),
bind(equal_to<string>, "Pupkin", bind(&Person::GetLastName, _1)));

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

Нинавижу.

А следующего стандарта еще 10 лет ждать.

Околорабочее

По окончанию длинного и жаркого code review, наполненного спорами о сферичности коней в вакууме, коллега вздохнул с облегчением.

Затем сделал заявление: “My life sucks”.

И ушел.

Мораль тут простая – даже истинные приверженцы XP, agile и scrum не всегда могут ограничить итерацию одним днем и минимизировать размер check-in’а.

Крещение ежа ужом

В надежде выполнить и перевыполнить план текущего sprint, коллега вчера заработался крепко за полночь. До трех часов.

В итоге, когда оказалось, что функциональный объект, созданный с помощью boost::bind, нельзя подсунуть как делегат в управляемый код, он послал нафиг scrum, этот самый функциональный объект, управляемый код и неуправляемый код тоже, Майкрософт, Билла Гейтса и Страуструпа со Столлменом на всякий случай и ушОл спать (тоже на всякий случай).

Морали здесь две.

Первая – от работы кони дохнут.
Вторая – за managed C++ от Майкрософта нужно отрезать кончик хвоста. По самую голову.

Workaround day

В 2010 студии M$ столько всего напеределывали, что создание новго проекта превратилась в поиск воркэраунда к воркэраунду. Например, зачем-то напрочь переделали определение custom build tool, причем гуй для его создания и редактирования привинтить забыли. В результате сегодня нашел, что сами  M$ рекомендуют проекты, которые используют custom build tool (ну, мало ли, вам Yacc’нуть чего надо или еще чего страшного натравить на исходники) создавать сначала в 2008 студии, а потом конвертировать в 2010.

Воистину, стоя и в гамаке. Еще и в противогазе.

К чести Студии, конвертирует она проекты без запинки.

Продолжаем есть кактус.

10 visitors online now
10 guests, 0 members
Max visitors today: 11 at 08:39 am MST
This month: 17 at 02-07-2012 06:17 am MST
This year: 29 at 01-23-2012 02:50 am MST
All time: 45 at 02-23-2011 09:11 am MST