О неадекватности отбора программистов

:

В ближайшее время мне вновь предстоит озаботиться поиском рабочего места, в связи с чем я вспоминаю свой драматический опыт трудоустройства и прочитанное насчёт собеседований на должность программиста. В частности, удручающее впечатление на меня произвела статья Алексея Колупаева «Нехитрый вопрос на собеседовании или как не попадают в стартапы».

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

« Уверяю вас — пользуясь этой задачкой (и, конечно, еще многими другими) я ещё ни разу серьёзно не ошибся с кандидатом. Ведь формальное знание PHP в кандидате — поверьте, далеко не главное. Значительно важнее — отношение к своему занятию, стремление к развитию, способность играть в команде, видение мира, если угодно. Мне гораздо интереснее, как человек решает задачу, чем её фактическое решение».

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

Итак, задачу автор формулирует так:

<?php
$a = 'abcdefgh';
// Напишите здесь недостающий код,
// чтобы результатом работы скрипта
// была строка $a, повернутая наоборот
echo $a;
?>

Для начала — «нулевое» решение, наилучшее, но, видимо, настолько ужасное с точки зрения автора, что он его даже не упоминает:

$a='hgfedcba';

Гы! Я серьёзно. «Уот ю уонт из уот ю гет» (What you want is what you get), как говорят в «Мак-Доналдсе», или выпьем же за то, чтобы правильно формулировать технические задания! Как поёт Канцлер Ги, « А на столе сидеть — удобно! И не гоните меня со стола…».

Ладно, поехали:

« Номер пять в моем хит-параде занимает ответ „я не знаю, и не буду это писать“. Иногда с вариантом „что за дурацкая задача, в жизни такого не бывает“. Слив, как говорится, засчитывается сразу».

Ай, зря! То, что задачу сию « дают на собеседовании в Microsoft» не говорит в пользу ни неё, ни «Майкрософта». Автор же сам признаёт:

« Задачка, конечно, „плюшевая“. Я сам могу придумать десяток причин, по которым она плоха — не отражает знание PHP, не соответствует реальной жизни…».

Итак, он унижает специалиста, предлагая ему откровенно неадекватную задачу, а потом удивляется, что его посылают. А могли бы и в ухо дать. Коль скоро он вступает на скользкую почву игры со стрессоустойчивостью, свойством, кое программисту при нормально организованном рабочем процессе никогда не должно потребоваться. Вариант номер пять — вполне адекватный ответ уважающего себя профессионала. Что же делать? Как отличить такового от невежды? Да очень просто. Погладь кота, сука! ™ Возьми работника на испытательный срок! Если даже ты какого чёрта не доверяешь диплому государственного образца (что, вообще-то, на грани национальной измены), то обрати внимание, что для специалиста потерянный месяц-другой на той ставке, кою предлагают на испытательных сроках, является достаточно высокой ставкой, чтобы ещё терзать его экзаменационными испытаниями (за кои, между прочим, он ни копейки не получает) в духе, как неодобрительно говаривал Мао, « внезапных атак».

« Номер четыре занимает вариант „В PHP вроде должна быть такая функция…“. Что ж, справедливости ради, должен сказать, что в PHP действительно есть такая функция. Названия её, конечно же, никто не помнит. Это нормально. Но неужели вы думаете, что я задавал эту задачку, чтобы услышать такой ответ? Следом за таким ответом предлагаю реализовать эту функцию самостоятельно».

Не помнить название какой-нибудь экзотической функции в PHP — это действительно нормально. Ненормально в такой ситуации писать её реализацию самому, вместо того, чтобы глянуть в мануал, ибо изобретение велосипедов — большое социальное зло. Помнится, был у меня сотрудник, который перебирал дочерние узлы в DOM-дереве, отбирая по селектору всех потомков, а затем проверяя у каждого родителя! Потому что изобретал велосипеды, там, где надо было изучать Javascript.

Номер три пропустим, он какой-то слабоадекватный (« ну, как-то через массивы»), к тому же в принципе сводится к номеру четыре, за той оговоркой, что человек либо не знал, либо от волнения забыл, что к строкам в PHP уже можно обращаться как к массивам. (Но это если мы имеем дело с однобайтной кодировкой. С UTF-8 фигня получится; нужно использовать соответствующее семейство функций. Гы! То, что автор об этом не вспоминает и все перечисляемые им решения для этого случая не годятся, не слишком говорит в его пользу. Впрочем, с многобайтной кодировкой и встроенная функция (сюрприз!) обращается некорректно, а её mb-аналога нету, так что это вообще отдельная опера. Которая, вообще-то, должна оговариваться при постановке задания.)

$b = '';
for ($i = strlen($a)-1; $i>=0; $i--)
	$b .= $a[$i];
$a = $b;

Автор называет это решение « минимально адекватным для того, чтобы я рассматривал человека всерьёз». На самом деле решение логичное, очевидное и вполне достаточное (для однобайтной кодировки). Работает оно, конечно, в сотни раз медленнее встроенной функции, но куда ж деваться? Но автору этого мало и он выкатывает « джедайские техники»? по коим будто бы опознаются « чемпионы». Первая « джедайская техника» выглядит так:

$b = '';
$l = strlen($a)-1;
for ($i = 0; $i < $l/2; $i++) {
	$b = $a[$i];
	$a[$i] = $a[$l-$i];
	$a[$l-$i] = $b;
}

Для начала хочется проворчать, что нельзя так именовать переменные, имена должны быть говорящими: $char, $half_length, $char_counter, например. Этому нас учит Стив Мак-Коннелл в «Совершенном коде», да это и так понятно (фигура « склонного к насилию психопата, который знает, где вы живете» должна быть в сознании всякого программера). Добавим, что этот код гораздо хуже читается даже при такой замене. Назначение его при беглом взгляде не очевидно, что плохо.

Затем отметим, что это — типичный пример преждевременной оптимизации, кою Доналд Кнут (кстати, всуе поминаемый автором) назвал « корнем всех зол».

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

Наконец, вторая (и, на мой взгляд, наихудшая, хотя, чтобы так написать, надо, конечно, обладать изрядной изощрённостью) « джедайская техника», про кою автор вздыхает — « …так хотелось бы, что-то кто-то написал что-то вроде» (та-дамм!):

$l = strlen($a)-1;
for ($i = 0; $i < $l/2; $i++) {
	$a[$i] = $a[$l-$i]^$a[$i];
	$a[$l-$i] = $a[$l-$i]^$a[$i];
	$a[$i] = $a[$l-$i]^$a[$i];
}

Что это было? На самом деле, этот трюкаческий метод справляется с длинными строками куда лучше предыдущего (с короткими, где-то до нескольких тысяч символов, кстати,— хуже,— а ведь в предложенном примере очень короткая строчка). Но он ещё хуже семантически, ибо применяет числовую, по существу, операцию (побитовое исключающее «или») к символам, подразумевая неявное преобразование типа. Тому, кто так пишет, « лучше было бы, если бы повесили ему жерновный камень на шею и бросили его в море». Ну, и всё равно он заметно уступает по производительности простому, не «джедайскому» методу.

Резюме: Jedi suxx, Sith rules…