Маниакальный веблог » Управлениеhttps://softwaremaniacs.org/blog/category/management/2016-08-04T14:18:21.403000-07:00ManiacИван Сагалаев о программировании и веб-разработкеhttp://softwaremaniacs.org/media/sm_org/style/photo.jpgНайм: вы всё делаете не так
2016-08-04T14:18:21.403000-07:00https://softwaremaniacs.org/blog/2012/07/19/hiring-wrong/Найм инженеров-программистов, если точнее… За свою карьеру программиста я помню ровно один раз, когда я успешно прошёл техническое собеседование, это было в 2002 году, через два года после моего выпуска. После этого все попытки делать это "правильно" неизменно проваливались, и меня в итоге брали на работу люди, которые меня уже ...
<p>Найм инженеров-программистов, если точнее… </p>
<p>За свою карьеру программиста я помню ровно один раз, когда я успешно прошёл техническое собеседование, это было в 2002 году, через два года после моего выпуска. После этого все попытки делать это "правильно" неизменно проваливались, и меня в итоге брали на работу люди, которые меня уже знали или по совету других или по моим публичным свершениям. После того, как совсем недавно я не прошёл очередное собеседование, я естественным образом пришёл к заключению, что у нас в индустрии есть проблема: компании и люди не умеют нанимать инженеров.</p>
<p>Несмотря на то, что к своему заключению я пришёл естественно, я понимаю, что не для всех может быть очевидно, отчего это я так уверен, что проблема не <em>во мне</em> (видите, я умею смотреть на ситуацию критически). Что ж… Последние лет двенадцать я разрабатывал бизнес-софт под Windows, проектировал и реализовывал веб-сервисы, писал тьюториалы (до книг, правда, так и не дошло), делал доклады на международных конференциях, управлял проектами и выпускал их, руководил маленькими и не очень группами разработчиков, нанимал инженеров, преподавал курсы, вёл open-source проекты. И не только я один считаю, что многие из этих вещей получались в целом неплохо. Не стану и дальше утомлять вас самолюбованием, скажу только, что я давно перестал мерять свою квалификацию по результатам часового собеседования.</p>
<p>В любом случае, достойны внимания слова́, а не тот, кто их произносит. Вот вам моё мнение о том, что не так с наймом, и как это исправить.</p>
<p><a name=more></a></p>
<h2>Что не так</h2>
<p>Кажется, сейчас уже в компаниях ушли от головоломок в стиле "как подвинуть Фудзи" и дают таки программистские задачи. Это хорошо! Однако эти задачи обычно или из базовой информатики или абстрактные задачи на теорию графов, теорию множеств и т.д. Неплохо, если кандидат умеет переворачивать связный список и может оценить алгоритмическую сложность своего решения. Но это не говорит ничего о тех навыках, которыми инженеры пользуются для собственно работы: понимание задач из реального мира, оценка компромиссов, нахождение и изоляция багов, оптимизация производительности, тестирование кода, подбор инструментов, чтение документации.</p>
<p class="picture right"><img src="/media/blog/hiring-3x4.jpg"></p>
<p>Есть ведь целый отдельный класс "задачек для собеседования". Таких, как всеми нежно любимая с полем из клеток 3×4 и маркером в левом нижнем углу, который умеет двигаться направо и вверх, и где надо посчитать количество разных маршрутов до правого верхнего угла. Или любая задачка про числа Фибоначчи, которые иногда маскируются под робота, шагающего по лестнице на одну или две ступеньки…</p>
<p>Судя по своим собственным ощущениям, я могу сказать, что мозги работают совершенно по-разному, когда я решаю такие задачи, чем когда работаю над чем-то практическим. Практические задачи обычно не ограничены искусственными условиями, призванными сделать их более заковыристыми, или набором инструментов, разрешённых для их решения. Также у них часто не бывает одного правильного ответа. И я лично знаю вполне состоявшегося программиста, который периодически практикуется в решении этих задач, чтобы "не терять полезный навык". Да что там, есть даже <a href="http://www.amazon.com/Programming-Interviews-Exposed-Secrets-Programmer/dp/047012167X">отдельные книги</a>, посвящённые конкретно этой теме!</p>
<p class=note><small>Неплохим с инженерной точки зрения решением задачи с полем 3×4 может быть захардкоженный ответ 10. А если её надо решать для поля произвольного размера, то ваше классическое тупое решение через рекурсию заткнётся довольно быстро, в зависимости от способностей вашего рантайма. И на этом моменте, чтобы иметь возможность предложить полезное решение, уже стоит начать интересоваться, какую, всё таки, конечную задачу мы решаем.</small></p>
<p>Один инженер из Google однажды поведал мне, что там считается, что существует корреляция между теми, кто хорошо умеет решать такие задачки, и теми, из кого потом могут получиться хорошие инженеры. Может, оно и так. Но оно совсем не учитывает инженеров, которых вы <em>не</em> наймёте, используя такой фильтр. Большинство компаний просто не могут позволить себе роскошь раскидываться талантами таким образом (сомневаюсь, на самом деле, что и Google может себе это позволить). Также этот подход не учитывает того, что нет в природе такого обобщённого понятия, как "инженер-программист". Разные вакансии требуют разного <em>уровня</em> квалификации и разной <em>специализации</em>. Нет смысла требовать от новичка понимания компромиссов между бизнес-требованиями и реализацией, так же, как нет смысла требовать от опытного ведущего разработчика умения не задумываясь написать из головы перевод инфиксной нотации в префиксную. То же справедливо и для разных областей: разработчики игр часто не слишком дружат с исключениями, а большинство JavaScript-программистов — с управлением памятью.</p>
<div class=note>
<p><small>Меня однажды позвали на собеседование на Java-позицию, чтобы поспрашивать кандидата про Питон, так как тот обмолвился, что с Питоном знаком. Поговорив с ним немного, я узнал, что он ещё студент, интересуется ещё и Эрлангом, а также работает с ребятами из группы над веб-сайтом для кафедры. Я также задал несколько технических вопросов на темы, с которыми он, по идее, ещё не должен был быть знаком, просто чтобы грубо оценить уровень подготовки. Дальше я выдал ему задачку Пола Грэма про аккумулятор (промотайте до "<a href="http://paulgraham.com/icad.html">Appendix: Power</a>"), которая в Питоне решается нетривиально: нужно знать о некоторых неочевидных деталях реализации CPython.</small></p>
<p><small>Он не смог её решить сам, но после достаточного количества подсказок с моей стороны мы, в итоге, до решения добрались. Что интересно, это то, что мы с собеседователем из Java-команды пришли к совершенно обратным выводам. Он сказал: "Он ни на что сам не ответил, мы его не берём", на что я сказал: "Тогда дайте я возьму его к себе!"</small></p>
<p><small>Я, конечно, и не ожидал, что <em>студент</em> должен знать подобную бесполезную муть. На самом деле, я был практически убеждён, что парень грамотный, уже к тому моменту, когда он рассказал про тот веб-проект, который они делали с друзьями в свободное время. Чего ещё нужно-то от человек без какого-либо опыта, кроме страсти к программированию и базовых навыков для занятия им? Единственным, зачем я вообще дал ему ту задачку, было убедиться, что он умеет строить гипотезы, проверять их и анализировать результаты.</small></p>
<p><small>Я в итоге действительно нанял его к нам, и насколько я знаю, он до сих пор счастливо работает в Яндексе.</small></p>
</div>
<p>Кстати, дайте-ка ещё я раскрою ту штуку про "не задумываясь написать из головы"…</p>
<p>Типичное собеседование — это напряжённый разговор между кандидатом и одним или несколькими собеседующими. Напряжённый он потому, что кандидат по сути находится в стрессовой среде. Людям вообще обычно не нравится, когда их пристрастно оценивают, а для программистов это особенно болезненно, потому что большинство из нас к тому же интроверты. Но хуже всего то, что кандидат чувствует необходимость решать задачки <em>как можно быстрее</em>. Даже если времени больше, чем достаточно, он всё равно <em>предполагает</em>, что чем быстрее он справится, тем лучше будет выглядеть. Наличие такой предполагаемой "награды", как оказывается, <a href="http://www.youtube.com/watch?v=u6XAPnuFjJc">самая большая помеха для когнитивной деятельности</a> (вы, скорее всего, уже видели этот ролик, но посмотрите ещё раз).</p>
<div class=note>
<p><small>Во время последнего собеседования у меня получилось выйти из ступора и придумать решение для довольно простой задачки практически сразу, как я вышел из комнаты на 5 минут в туалет. И это невозможно сымитировать.</small></p>
<p><small>И с обратной точки зрения, один довольно толковый кандидат как-то прислал мне два интересных варианта решения задачи, которую он никак не мог победить за полчаса до этого, когда сидел со мной в комнате. Всего-то и надо было — доехать до дома и расслабиться.</small></p>
</div>
<h2>Как это делается</h2>
<p>Основной посыл, который я попытаюсь здесь донести: <em>спрашивать</em> правильные вопросы — это только полдела, важно ещё и правильно <em>интерпретировать</em> ответы. Я даже возьму на себя смелость утверждать, что собеседующий больше ответственен за то, чтобы раскрыть способности кандидата, чем тот — за их демонстрацию. Помните, вы ведь не специалиста по продажам нанимаете, не ждите от гика, что он будет "зажигать".</p>
<p>Теперь — к сути.</p>
<p>Как говорит Джоэл Спольски с своём <a href="http://www.joelonsoftware.com/articles/GuerrillaInterviewing3.html">Guerrilla Guide to Interviewing</a>, вы должны начать с представления компании и себя, а затем поспрашивать кандидата о его последнем проекте. И это всё правда, и работает ровно по тем причинам, которые Джоэл красноречиво изложил в статье. Также, хотя совсем устранить стресс собеседования не получится, таким образом его можно по крайней мере уменьшить.</p>
<p>Ваш собственно технический вопрос должен быть упрощённой задачей из реальной жизни. Он должен быть практическим по всем тем причинам, о которых я только что говорил, и он должен быть упрощён, потому что возня с мелкими деталями занимает слишком много времени, а ваше собеседование длится не неделю.</p>
<p><a name=task></a>
В качестве примера, вот одна из моих любимых задач:</p>
<blockquote>
<ul>
<li>У вас есть текстовый лог IP-адресов с количеством байт, которое они скачали. Формат строчек простой — <code>xxx.xxx.xxx.xxx \t <number></code>.</li>
<li>Лог размером в несколько гигабайт, достаточно большой, чтобы не помещаться в память комфортно.</li>
<li>Также у вас есть таблица диапазонов IP-адресов, выданных различным странам. Формат строчек — <code><integer>-<integer> <country code></code>. Целыми числами представлены IP-адреса.</li>
<li>Размер таблицы порядка 100 000 строчек.</li>
<li>Вам нужно вывести top-10 стран по количеству скачанного контента.</li>
</ul>
</blockquote>
<p>Задачка, хоть и простая, но в ней, как оказалось, достаточно тонких мест, которые могут рассказать вам о кандидате довольно много.</p>
<p>После того, как вы выдали задачку, уйдите из комнаты минут на 15. Нет, правда, не сидите у людей на голове, когда они пытаются думать. Пусть закроют глаза, погрызут ручку, походят туда-сюда или вокруг стола, засунут голову под стол или пусть читают описание задачи нараспев — всё, что умные люди могут делать, чтобы сосредоточиться.</p>
<p class=note><small>Я знаю человека, который буквально пел строчки кода во время отладки. Похоже, это помогало, так почему бы и нет?</small></p>
<p>Ещё вы должны обязательно уточнить, что вы не ожидаете никакого готового решения к моменту, когда вернётесь. Скажите, что у задачи вообще нет какого-то правильного ответа, и вам больше интересен общий подход к решению. Помимо прочего, отсутствие требования иметь работающий код, даёт вам возможность писать его на чём угодно: на листах бумаги, на доске или на лаптопе. Пользуйтесь тем, что у вас есть.</p>
<p>Если кандидат таки решит задачу без особых проблем, то в этом нет ничего хорошего. Потому что это ни о чём не говорит. Возможно, он действительно очень умный, а возможно, ему просто повезло и решение "вдруг" пришло к нему в голову, или у него просто есть склонность решать задачи именно такого типа. Но дело в том, что основное занятие инженеров — решать проблемы, на которые они <em>не знают готовых ответов</em>. И ваша задача на собеседовании состоит в том, чтобы поставить их как раз в такое положение и наблюдать, как они из него выходят.</p>
<p>Во время этого процесса совершенно нормально вести дискуссию. Именно так и решаются реальные проблемы. В разговоре хорошо видно, как человек рассуждает. Делает ли он обоснованные заключения или перебирает варианты в надежде, что вы сами подскажете правильный? Зацикливается ли на незначительных деталях или умеет посмотреть на задачу целиком? Задаёт ли полезные вопросы? Может ли абстрагироваться от уже решённых частей задачи? Эта часть собеседования — самая продуктивная, она даёт вам наилучшее представление о специалисте.</p>
<p>Важно также помнить, что инженерные навыки не располагаются по линейной шкале, и вы не должны пытаться посчитать какую-то кумулятивную оценку, которая поместит кандидата слева или справа от воображаемой "точки найма". У людей разные склонности и разный опыт, и не нужно ждать, что у всех в голове один и тот же набор знаний, которые вам кажутся "базовыми" и "обязательными". Другими словами, не списывайте людей со счетов только потому, что они неверно оценили алгоритмическую сложность, не знают какой-то конкретный метод сортировки или не помнят задержку поиска данных на вращающемся диске в миллисекундах. Хотя, конечно, если человек не слышал вообще ни про одну из этих вещей, это уже подозрительно.</p>
<p class="picture right"><img src="/media/blog/pai-mei.png"></p>
<p>Ещё отдельное примечание про найм программистов с большим опытом на ведущие вакансии. Не доставайте их слишком усердно своими дурацкими задачками! Короткая задачка пойдёт в качестве разогрева, но больше всего информации вы получите, просто разговаривая об их собственном опыте. Просто, потому что у них его больше, чем "крутых скиллов" и знаний из учебника. В конце концов, именно этим они и ценны. Поэтому погружайтесь в детали их прошлых проектов, старайтесь с ними спорить, играйте роль адвоката дьявола, чтобы они объясняли вам, почему именно они принимали те или иные решения. Таким образом вы сможете увидеть, действительно ли они занимались чем-то конкретным или же просто числились в команде. А в лучшем случае вы можете узнать что-то полезное и сами :-).</p>
<p>Также смиритесь с тем, что вы будете время от времени нанимать и плохих специалистов. Такие вещи, как, например, способность сохранять продуктивность в течение долгого времени, просто невозможно оценить на собеседовании. Человек может быть толковым, но через пару месяцев окажется, что он невыносимый лентяй. С такими проблемами надо бороться другими методами, и это уже совсем отдельная история.</p>
<h2>Кто должен этим заниматься</h2>
<p>Этот вопрос, вообще-то, относится к разделу "что не так", но я решил оставить его на десерт, потому что он представляется самым спорным.</p>
<p>Я глубоко уверен, что оценка качеств других людей — суждение о людях, если хотите — это особый навык. Хороший инженер не обязательно будет хорошо собеседовать. И эта работа тоже творческая, поэтому её не получится формализовать по пунктам и просто дать всем инженерам их выучить. Если вы спросите человека, который умеет хорошо нанимать, как у него это получается, вы часто можете услышать что-то вроде: "Я просто разговариваю с человеком и вижу, хорош он или нет". И всё.</p>
<p>Так что, вместо того, чтобы заставлять каждого инженера из вашей команды проводить собеседования по очереди, как своего рода повинность (это я про вас, Google), постарайтесь заметить тех людей, у кого нанятые ими чаще оказываются хорошими работниками, и пусть только они этим и занимаются.</p>
<h2>Ссылка</h2>
<p>На этот пост меня вдохновила чудесная статья "<a href="http://hitesh.in/2012/hiring-process/">How I hire writers</a>" Хитеша Сарды. Особенно её предпоследний абзац.Модерирование по Дарвину
2011-01-28T16:03:04.426000-08:00https://softwaremaniacs.org/blog/2011/01/28/moderation-by-darwin/У меня на форуме нет официальных правил и нет специального раздела, где можно поныть и поспорить с модераторами. Подозреваю, что большинство читателей сайта даже не знают, кто именно там модераторы, хотя и намеренного секрета из этого не делается. Тем не менее, как мне кажется, форум уже несколько лет сохраняет довольно ...
<p>У меня на <a href="http://softwaremaniacs.org/forum/">форуме</a> нет официальных правил и нет специального раздела, где можно поныть и поспорить с модераторами. Подозреваю, что большинство читателей сайта даже не знают, кто именно там модераторы, хотя и намеренного секрета из этого не делается. Тем не менее, как мне кажется, форум уже несколько лет сохраняет довольно стабильное и высокое отношение сигнала к шуму (это, кстати, не то же самое, что "интересность" для конкретного человека).</p>
<p><a name=more></a></p>
<p>В несостоятельности идеи официальных правил я убедился в конце 90-х, когда был сомодератором пользовательской конференции одного московского провайдера. Причины, в общем-то, вполне очевидные:</p>
<ul>
<li>невозможно выразить многообразие отношений конечным набором формулировок</li>
<li>никто не заботится о поддержании актуальности правил</li>
<li>и главное, правила никто не читает</li>
</ul>
<p>В конце концов остаётся единственное работающее правило: модератор всегда прав. Оно хорошее, но и его можно применять неправильно. В частности, публичные выяснения отношений вредят форумам очень сильно. Каждый такой вопрос интересен только двум людям, которые о нём спорят, и поскольку он не относится к теме форума напрямую, он только добавляет мусора и отнимает время.</p>
<h2>Меметика</h2>
<p>Поэтому когда у меня появился свой форум, я решил поэкспериментировать с другим подходом, который многим может показаться радикальным.</p>
<p class=strong><strong>Единственным средством модерирования форума является удаление сообщений.</strong></p>
<p>Это простое средство работает по принципу естественного отбора, описанному Чарльзом Дарвином для эволюции видов, и обобщённому уже в наши дни в <a href="http://www.ted.com/talks/susan_blackmore_on_memes_and_temes.html">теории мемов</a>.</p>
<ul>
<li>Разные люди пишут на форуме разные сообщения — это обеспечивает <strong>вариативность видов</strong>.</li>
<li>Люди, приходящие на форум, видят, о чём и как там разговаривают, и стараются вести себя так же. Эта социальная особенность обеспечивает необходимую <strong>наследственность</strong>.</li>
<li>Модераторы удаляют сообщения, которые им не хочется видеть на форуме. Поскольку модераторов немного, нам довольно просто прийти к взаимопониманию о том, к чему мы стремимся на форуме. Это создаёт консистентную <strong>внешнюю среду</strong>, в которой сообщения борются за выживание.</li>
</ul>
<p>Из трёх этих пунктов первые два происходят естественно, и только третий требует внешнего участия. Поэтому я и называю его единственным инструментом. Кстати, говоря формально, именно поэтому этот отбор искусственный, а не естественный, но суть та же.</p>
<h2>Эмоции</h2>
<p>У этого подхода есть одна эмоциональная составляющая, которая меня беспокоит с самого начала. Когда ты удаляешь сообщение человека, ничего ему не объясняя, неминуемо возникает опасность того, что человек обидится. В этом нет никакой проблемы <em>формально</em>, потому что форум ничего не обещает участнику. Но чисто по-человечески это никому не нравится, конечно.</p>
<p>После раздумий я пришёл к выводу, что это меньшее зло. Удаление сообщения безлично, и у нормального человека есть все основания предполагать, что его тут не ненавидят лично, а он, возможно, просто в чём-то не разобрался. Скорее всего, он попробует написать что-то ещё. Тролли же чаще всего и так очень хорошо представляют, почему именно их сообщения удаляются, да и в любом случае <em>их</em> моральные переживания меня никогда не беспокоили :-). </p>
<p>В качестве последнего средства всегда есть мои <a href="http://softwaremaniacs.org/about/">личные контакты</a>, и я помню буквально пару случаев, когда люди мне писали, и я объяснял, почему удаляются их сообщения. Непублично такое общение происходит гораздо спокойней и эффективней, чем на людях, где все мы склонны отстаивать свой имидж.</p>
<h2>Отход от теории</h2>
<p>Ещё мы делаем некоторые вещи, которые не укладываются в изложенную выше концепцию единственного средства воздействия: </p>
<ul>
<li>подправляем форматирование кода</li>
<li>"деидиотизируем" заголовки топиков (чаще всего я удаляю бесполезное слово "вопрос")</li>
<li>отделяем ответвления разговора в новые топики</li>
<li>явно <a href="http://softwaremaniacs.org/forum/python/28345/">разъясняем новичкам местные обычаи</a></li>
</ul>
<p>Хотя мне кажется, что и в этих случаях простой отбор тоже работал бы, цена была бы слишком высока. Об этих специфичных мелочах нереально просто так догадаться большинству вполне вменяемых людей, поэтому скорее всего они бы просто уходили с форума, не пытаясь разбираться. То есть, естественный отбор произошёл бы на другом уровне: сам форум бы вымер, не выдержав конкуренции с другими. А это не в наших интересах :-).Трудности безболезненного планирования
2006-08-10T06:14:21-07:00https://softwaremaniacs.org/blog/2006/08/10/painless-scheduling-problems/Статья Дж. Спольского, которую я только что рекомендовал, называется "Безболезненное планирование разработки софта". Безболезненность эта происходит от того, что исполнение плана не требует ни сложных программ, ни драконовских мер по контролю. Но Джоел, все же, слегка слукавил. Попользовавшись этим методом какое-то время я обнаружил, что совсем уж безболезненным он не ...
<p>Статья Дж. Спольского, которую я <a href="/blog/2006/08/10/plans-vs-plans/">только что рекомендовал</a>, называется "<a href="http://joelonsoftware.com/articles/fog0000000245.html">Безболезненное планирование разработки софта</a>". Безболезненность эта происходит от того, что исполнение плана не требует ни сложных программ, ни драконовских мер по контролю. Но Джоел, все же, слегка слукавил. Попользовавшись этим методом какое-то время я обнаружил, что совсем уж безболезненным он не является. Хотя может быть я просто еще не достиг просветления в нужной мере, но все равно поделюсь теми трудностями, которые мне встретились.</p>
<p><a name=more></a></p>
<h3>Дизайн</h3>
<p>Самая большая трудность заключается действительно не в исполнении плана, а в его составлении. То, что план должен быть детализирован до очень простых задачек по нескольку часов, подразумевает, что функциональность надо заранее полностью спроектировать. И вот сидеть и придумывать в голове, как оно "будет", гораздо сложнее, чем просто делать, что делается, и по ходу смотреть, что получается. Но! Эта трудность действительно необходима. Стоит потратить на это день, два, неделю, но это позволит заранее выяснить очень много дополнительных вопросов и заранее увидеть многие ложные пути. Это в итоге сильно экономит время, потому что продумать и отменить ложный путь хоть и сложнее, но существенно быстрее, чем сделать и переделать. И менее нервно.</p>
<p>Этот процесс требует тренировки. У меня стало получаться нормально планировать проекты к третьему или четвертому разу. Тут главное — не опускать руки, когда сразу не получается.</p>
<h3>Разная предсказуемость</h3>
<p>Трудность планирования также сильно зависит от специфики задачи. Задачу легко раскладывать на составляющие, если разработчики с этой задачей уже знакомы. Если же нет, то прогноз будет уже отнюдь не таким точным. Это само по себе нормально, потому что план в любом случае позволяет контроллировать неожиданные трудности. Но в общем и целом, чем стандартней задача, тем точнее она планируется.</p>
<p class=note><small>Обратное, кстати, неверно. Если ваш план разваливается, то это не означает автоматически, что вы делаете что-то грандиозное :-).</small></p>
<p>Хуже всего в этом смысле поддаются планированию три вещи: исследования, творчество и отладка багов. Именно поэтому задачи такого рода надо стараться решить как можно раньше (исследования в самом начале, странные баги — сразу после обнаружения), потому что чем раньше вы от них избавитесь, тем быстрее план уточнится.</p>
<h3>Долгосрочное планирование</h3>
<p>Выполнение многих задач зависит от того, как именно выполнены предыдущие. Такие зависимости выстраиваются в цепочки и приводят к тому, что чем дальше простирается план (когда его надо уже называть План™), тем менее предсказуемым становится. Спланировать на многие годы вперед можно, видимо, только очень тривиальные задачи. Поэтому имеет смысл такие планы не строить вообще, а разбить всю большую задачу на достаточно крупные куски и планировать их отдельно. Они, кстати, естественным образом становятся мажорными номерами версий :-).Планирование планированию рознь
2006-08-09T16:03:15-07:00https://softwaremaniacs.org/blog/2006/08/09/plans-vs-plans/Наткнулся недавно на интересный блог: Алекс Лебедев пишет про разработку. Блог открылся недавно, но там уже есть некоторое количество интересных статей. Хотя лично меня в первую очередь привлекло то, что причины, побудившие автора уйти с зарплаты и начать работать самостоятельно, уж очень во многом совпадают с моими :-). Одну из ...
<p>Наткнулся недавно на интересный блог: <a href="http://alexlebedev.com/blog">Алекс Лебедев пишет про разработку</a>. Блог открылся недавно, но там уже есть некоторое количество интересных статей. Хотя лично меня в первую очередь привлекло то, что причины, побудившие автора <a href="http://alexlebedev.com/blog/%d0%bf%d0%be%d1%87%d0%b5%d0%bc%d1%83-%d1%8f-%d1%83%d1%85%d0%be%d0%b6%d1%83-%d0%b2-%d1%81%d0%be%d0%b1%d1%81%d1%82%d0%b2%d0%b5%d0%bd%d0%bd%d1%8b%d0%b9-%d0%b1%d0%b8%d0%b7%d0%bd%d0%b5%d1%81/">уйти с зарплаты и начать работать самостоятельно</a>, уж очень во многом совпадают с моими :-).</p>
<p>Одну из недавних <a href="http://www.alexlebedev.com/blog/%d0%be-%d0%b2%d1%80%d0%b5%d0%b4%d0%b5-%d0%b8%d0%b7%d0%bb%d0%b8%d1%88%d0%bd%d0%b5%d0%b3%d0%be-%d0%bf%d0%bb%d0%b0%d0%bd%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f/">статей, посвященную планированию</a>, мне очень хочется прокомментировать.</p>
<p><a name=more></a></p>
<p>Когда-то я прочитал уже ставшую классической <a href="http://joelonsoftware.com/articles/fog0000000245.html">статью о планировании Джоела Спольского</a>, которая показалась мне очень логичной. За последний год у меня была возможность потренироваться с этим подходом, и должен сказать, что как только я его "<a href="http://en.wikipedia.org/wiki/Grok">грокнул</a>", я убедился, что он реально работает. Буквально, Джоел оказался прав практически во всем. Поэтому, если ваши планы все время проваливаются, я утверждаю, что "вы просто не умеете их готовить". Поэтому эту статью я теперь рекомендую к обязательному прочтению всем разработчикам и их менеджерам. Больше того, лучше всего прочитайте ее прямо сейчас.</p>
<p>Статья же Алекса Лебедева оставила у меня странные впечатления, потому что сначала я был совершенно не согласен, потом совершенно согласен, а с выводом — не согласен опять :-).</p>
<p>Немного разобравшись в причинах этого эффекта, я и хочу расставить акценты.</p>
<p>Первая часть начинается так:</p>
<blockquote>
<p>Регулярно сталкиваюсь с желанием того или иного руководства составить подробный план работ и строго следовать ему. Зачем это нужно? Никакой объем планирования не может ускорить работу.</p>
</blockquote>
<p>Я бы уточнил: никакой объем планирования разработки, <em>составленный руководством</em>, не может ускорить работу. Дальше автор углубляется в описание того, почему планы не работают, почему не помогает ни жесткий контроль исполнения, ни военная дисципина. Это все так, но я в корне не согласен с тем, что проблема лежит в самом <em>факте</em> подробного планирования. Реальная причина неработы такого подхода только в том, что никто, кроме того человека, который пишет код, не может физически знать, сколько на это уйдет времени. Ни руководитель, ни его коллеги разработчики. Только он сам, и как раз только тогда, когда спланирует все подробно.</p>
<p>А вот дальше автор делится работающей моделью планирования:</p>
<blockquote>
<p>Всегда имейте максимально полный и актуальный список работ. Расставляйте приоритеты и работайте в первую очередь над высокоприоритетными вещами. Оценивайте трудоемкость работ и примерные даты окончания. Только не пытайтесь зафиксировать сроки и взвалить ответственность за их соблюдение на разработчиков.</p>
</blockquote>
<p>Согласен всеми руками. Главное отличие плана, который работает, от плана, который не работает — это то, что первый является <em>инструментом</em>, которым менеджер пользуется для управления проектом, а другой — психологическим пугалом со взятыми с потолка сроками. А психологические пугала на людей с высоким уровнем интеллекта не действуют.</p>
<p>План-инструмент не ставит условий, а просто информирует: "нам осталось сделать такие-то вещи, исходя из скорости нашей работы, мы будем делать их столько-то". И все. Не должно быть никаких санкций по поводу того, что реальный срок исполнения каких-то задач не совпал с запланированным, потому что тогда разработчики начнут врать в плане, он потеряет актуальность и с ней — смысл (никто не пользуется линейкой с неверными миллиметрами). Если через какое-то время становится видно, что планируемое время постоянно не совпадает с реальным, надо просто пересчитать остаток плана, исходя из реальности.</p>
<p>А вот для того, чтобы план был наиболее близок к реальности, он просто обязан быть подробным. Никто не знает, сколько занимает "система профайлов пользователей", потому что в это понятие можно включить от двух часов до полугода работы. Только когда это разбито на задачи "создать таблицу с полями A, B, C", "вывести поля в виде формы", "обработать submit" и т.д., тогда это можно посчитать.</p>
<p>Даже дедлайны, которые являются сутью традиционных "планов", на самом деле тоже имеют смысл. Они, например, могут быть продиктованы какими-то внешними причинами, и их действительно нельзя нарушать. И здесь план-инструмент позволяет команде сделать информированный выбор, от каких функций надо отказаться, чтобы успеть. А не обманывать себя до самого последнего момента, что "надо только еще чуть-чуть постараться и поднажать". Так не бывает в разработке, потому что программист не может заставить мозг "думать быстрее", и как любой творческий человек, не может генерировать у себя в мозгу озарения по собственному желанию.</p>
<p>Поэтому на вопрос в конце статьи:</p>
<blockquote>
<p>Вы все еще думаете что вам нужен подробный план работ?</p>
</blockquote>
<p>... ответ — конечно да.Жесткое ТЗ
2006-07-03T03:56:54-07:00https://softwaremaniacs.org/blog/2006/07/03/fixed-spec/Наверное каждый программист сталкивался в своей работе с неприятностями, вызванными нечеткими договоренностями. Заказчик (или начальник) ставит задачу устно и довольно неподробно. Программист, тем не менее, вполне понимает, о чем идет речь, соглашается сделать за определенные деньги или время, а потом оказывается, что заказчик имел в виду другое (читай: гораздо больше), ...
<p>Наверное каждый программист сталкивался в своей работе с неприятностями, вызванными нечеткими договоренностями. Заказчик (или начальник) ставит задачу устно и довольно неподробно. Программист, тем не менее, вполне понимает, о чем идет речь, соглашается сделать за определенные деньги или время, а потом оказывается, что заказчик имел в виду другое (читай: гораздо больше), и вроде как договоренность уже есть, и надо делать, и получается, что программист работает гораздо больше, чем рассчитывал.</p>
<p>После одного-другого таких случаев программист обычно решает, что отныне и навсегда все отношения с заказчиком/начальником <strong>обязательно должны</strong> регулироваться жестким техническим заданием.</p>
<p><a name=more></a></p>
<h3>Обратная сторона жесткости</h3>
<p>Такой подход действительно логичен и хорошо защищает разработчика от неприятностей, но у него есть и другая сторона, которую его приверженцы часто упускают: спецификация задачи до начала ее реализации чаще всего сильно расходится с тем, что же действительно нужно от системы заказчику. И здесь разработчики часто встают в агрессивную защитную позицию: "если этот весь из себя мегабизнесмен сам не знает, чего хочет, то сам виноват".</p>
<p>Во-первых, это просто неверная постановка вопроса. Потому что если заказчик действительно не знает, чего хочет, то это не значит, что он не готов платить деньги за то, чтобы ему это объяснили, предложили варианты и оценили каждый вариант во времени/деньгах. А вот это перекладывание ответственности и поиск виноватого в грядущем провале — это как раз то, что отличает разработчика, обиженного на предыдущего заказчика, от разработчика, который хочет решить задачу. Другими словами, не надо заранее планировать провал.</p>
<p>Во-вторых, заказчик не знает, чего хочет, совсем не потому, что он идиот. Просто реальность оказывается куда сложней умозрительных представлений о ней.</p>
<p>Пример. Как читатели моего блога, несомненно, в курсе, недавно я был погружен в разработку Некого Музыкального Сервиса™, в котором люди обмениваются музыкой в виде альбомов. Так я и спроектировал, что в системе у нас будут Пользователи, а у каждого — список Альбомов. И в системе можно будет искать альбомы по, скажем, названию и получать их список с указанием, какому пользователю они принадлежат. Затем, когда эта простая модель стала разрабатываться в подробностях, у меня возник вопрос, который до этого ни разу не возникал: а что если у разных пользователей будут одинаковые альбомы? Надо решить, будет ли система считать все эти альбомы одним и тем же или же таки разными. Немного подумав, я решил, что пусть будут разные, потому что у разных людей эти альбомы могут быть в разном качестве и разной полноты (есть не все треки, например). Да и сами владельцы альбомов могут, например, быть в отпуске, и тогда будет иметь смысл попросить тот же альбом у другого человека. Логично, да?</p>
<p>Когда мы начали активные тесты, мгновенно стало очевидным, что такой вариант не работает. Представьте себе результаты поиска музыки, скажем, Beatles: это есть почти у каждого меломана, и часто практически все альбомы. В итоге на странице результатов поиска мы имеем 200 одинаковых альбомов "A Hard Day's Night", тянущихся несколько страниц, 200 одинаковых альбомов "Revolver" и т.д. Дальше — больше. А в какой из этих альбомов надо ткнуться, чтобы оставить комментарий? А надо ли раздельно хранить 200 почти одинаковых картинок обложек?</p>
<p>В общем и целом выходит, что если систему оставить в таком состоянии, то она будет совершенно бесполезной в части поиска музыки и ее комментирования, а это 2 из 5 ключевых требований. Многовато.</p>
<p>Причем, все эти проблемы выглядят очень очевидными, когда с ними сталкиваешься, но факт в том, что ни заказчик, ни программист не подумали о них в самом начале. Хотя думали, и думали напряженно (за себя, по крайней мере, могу ручаться :-) ).</p>
<p>Итак, если в двух словах:</p>
<p class=strong><strong>ТЗ с жестко зафиксированными условиями часто приводит к созданию бесполезного продукта.</strong></p>
<p class=note><small>В общем-то, многих разработчиков это как-раз устраивает: неважно, что там получится, лишь бы деньги были. Но я нахожу такую позицию попросту нечестной, каким бы немодным это понятие ни казалось.</small></p>
<h3>Изменяющаяся спецификация</h3>
<p>Ответ на вопрос, что с этой проблемой делать, дает <a href="http://www.martinfowler.com/articles/newMethodology.html">agile-методология</a>.</p>
<p>Общая идея состоит в том, что спецификацию задачи стоит считать не выбитой в граните конечной истиной, а постоянно изменяющимся документом, отражающим <em>текущее</em> видение ситуации. Тогда из штуки, про которую все знают, что "все серьезные люди должны это писать", но которую задвигают подальше, потому что она реально бесполезна, она вдруг магическим образом превращается в полезный инструмент, с которым все сверяются по ходу проекта. Добавлю, что это не то же самое, что отсутствие спецификации вообще, потому что тогда, напротив, никто ни в какой момент времени не знает, куда движется проект.</p>
<p>Чтобы такое гибкое ТЗ действительно было полезным инструментом, нужно выполнение нескольких условий:</p>
<dl>
<dt>Больше функций = больше ресурсов</dt>
<dd>Очевидно, требования спецификации не могут меняться бесконтрольно. И это уже то, что часто упускают из вида многие заказчики и начальники: изменение требований неминуемо ведет к изменению времени на разработку и оплаты за нее. Каждый раз, когда заказчику хочется включить что-то новое или углубить что-то старое (<a href="/blog/2006/04/30/what-is-hard/">каким бы простым оно ни казалось</a>), это должно согласоваться с разработчиками в сторону увеличения выделяемых ресурсов.</dd>
<dt>Спецификацией надо заниматься</dt>
<dd>
<p>Должен быть отдельный человек, ответственный за спецификацию. Он должен владеть текстом и каждый день сверяться с тем, соответствует ли то, что все делают, тому, что планируется. Эти вещи периодически начинают расходиться, потому что, как это типично для людей, то и дело кто-то что-то недопонимает. Эти расхождения надо обсуждать и либо менять спецификацию, либо менять то, как она выполняется.</p>
<p>Заниматься этим должен человек, который умеет формулировать мысли письменно. Причем, он может быть как со стороны разработчиков, так и со стороны заказчиков, потому что спецификация — это не диктующий документ, а фиксирующий, и ее написание — это не столько управляющая позиция, сколько обслуживающая. Тем не менее, это вполне себе полноценная работа, и в зависимости от размера проекта она может потребовать полной занятости специально для этого назначенного человека.</p>
</dd>
<dt>Спецификацию должны читать</dt>
<dd>Поскольку это инструмент, им должно быть удобно пользоваться. У этого понятия много аспектов, которые очень хорошо описал Дж. Спольски в статье про <a href="http://local.joelonsoftware.com/mediawiki/index.php/Russian#.D0.A4.D1.83.D0.BD.D0.BA.D1.86.D0.B8.D0.BE.D0.BD.D0.B0.D0.BB.D1.8C.D0.BD.D1.8B.D0.B5_.D1.81.D0.BF.D0.B5.D1.86.D0.B8.D1.84.D0.B8.D0.BA.D0.B0.D1.86.D0.B8.D0.B8_.D0.BC.D0.B0.D0.BB.D0.BE.D0.B9_.D0.BA.D1.80.D0.BE.D0.B2.D1.8C.D1.8E">функциональные спецификации</a>. Ее обязательно нужно прочитать всем, кто так или иначе участвует в разработке софта.</dd>
</dl>Что такое "сложно"
2006-04-30T05:31:55-07:00https://softwaremaniacs.org/blog/2006/04/30/what-is-hard/До сих пор в блоге я почти не касался вопросов, связанных с организацией процесса разработки софта. Мне есть, что сказать по этому поводу, благо я видел этот процесс с разных сторон: разработчика, проектировщика, руководителя отдела. Это первая статья в категорию "Управление", которая посвящается таким вопросам. Надеюсь, это все будет полезно ...
<p>До сих пор в блоге я почти не касался вопросов, связанных с организацией процесса разработки софта. Мне есть, что сказать по этому поводу, благо я видел этот процесс с разных сторон: разработчика, проектировщика, руководителя отдела. Это первая статья в категорию "<a href="/blog/category/management/">Управление</a>", которая посвящается таким вопросам. Надеюсь, это все будет полезно и программистам, и начальникам, и заказчикам, и возможно будет как-то содействовать уменьшению непонимания, существующего между ними.</p>
<hr>
<p>Знакомая ситуация: начальник обращается к программисту с предложением (требованием, угрозой — нужное подчеркнуть :-) ) реализовать какую-нибудь нужную вещь в системе, на что тот, не долго думая, отвечает: "не, это сложно..." Тут же возникает конфликт, потому что начальнику эта самая вещь кажется далеко не такой сложной, и он подозревает, что программист просто ленится.</p>
<p>Ситуация эта, вопреки бытующему мнению, не является никаким "необходимым злом" в общении с программистами и вполне разрешаема.</p>
<p>Но начать я хочу с выяснения того, что такое на самом деле "сложно". Я готов предложить очень простое формальное определение этого понятия.</p>
<p><a name=more></a></p>
<h3>Определение</h3>
<p class=strong><strong>Сложно — это то, что ваш программист называет сложным.</strong></p>
<p>Легче не стало :-). Но это ведь <em>формальное</em> определение, а оно всегда нуждается в дальнейших разъяснениях.</p>
<p>Что это определение подразумевает в первую очередь — это то, что сложность невозможно померять объективно в каких-то взвешенных единицах. Это всегда субъективное понятие. Для программиста графических интерфейсов задача подвешивания к веб-сайту RSS-потока включает знакомство с другим языком программирования, чтение статей "что такое RSS", потом "что такое XML", потом "как делать XML в PHP". Это сложно. Веб-программиста это займет на какой-нибудь час, потому что та бибилиотека, с которой он работает, содержит волшебную функцию "повесить RSS-поток на сайт", и он про нее знает (час уйдет на уточнение того, что же именно будет в потоке, и где же именно разместить иконочку). Кроме специализации огромное значение имеет авторство кода. Починить свой баг на порядок проще, чем чужой, даже если они из одного и того же раздела программирования.</p>
<p>Само слово "программист" в определении тоже имеет смысл. Большое заблуждение многих заключается в том, что программирование — это такая же работа, как, скажем, бухгалтерия, и любой человек может быть программистом, если прочитает несколько умных книжек и потренируется. На самом деле это не так. Способность программировать — это своего рода талант, который можно сравнить со способностью рисовать картины.</p>
<p class="picture right frame"><img alt="Я нарисовал свой автопортрет на рисунке в клетку, и выглядит он как насмешка, причем неумелая." src="/media/blog/autoportrait-sketch.jpg"></p>
<p>Любой человек может изучить технику академического рисунка, и рисовать он будет <em>гораздо</em> лучше, чем мы с вами, но вот художником он от этого не станет. Аналогично, та сложность, которую программист способен прикинуть по формулировке задачи, сильно отличается от той, что видна другим. А случаи, когда задача в реализации оказывается еще сложнее, гораздо более часты, чем обратные.</p>
<p>Впрочем, многие в это не верят, считая такую позицию просто попыткой набить себе цену :-). Переубеждать не буду. Во-первых, надежно это можно сделать только переставив свои мозги оппоненту, а во-вторых, это не так уж и важно для предмета разговора. Двинемся дальше.</p>
<p>Дальше все проще. "Сложно — это то, что <strong>ваш</strong> программист называет сложным." Это означает, что раз работу выполнять именно ему(ей), то его(ее) мнение и является определяющим. Да, возможно вам задача кажется простой. Да, возможно вы убеждены, что ему(ей) просто лень подумать. Да, возможно вы считаете, что ваш программист уже полтора года применяет не те языки, библиотеки и фреймворки, и вообще в .NET (J2EE, ASP, SAP — любимое подчеркнуть) все это работает само. Это, очевидно, не имеет ровно никакого значения, потому что ваш программист умеет то, что он(она) умеет, а вы не возьметесь программировать вместо него(нее).</p>
<p class=note><small>И маленькое дополнение: если вы скажете ему(ей) о том, что его(ее) инструменты — отстой, это <em>не</em> будет являться дополнительной мотивацией.</small></p>
<p>Чаще всего, на самом деле, имеет место и то, и другое: и задача сложней, чем кажется, и у программиста мозги заняты совсем другим. Вот это и есть — практическая сложность. И ее надо решать.</p>
<h3>Решение задачи</h3>
<p>Начну с того, чего делать не надо. Не надо пытаться на програмиста давить, заставлять чувствовать себя виноватым, взызвать к чувству ответственности и т.д. Любому человеку с интеллектом все эти "хитрости" и "приемы" из бульварной литературы типа "Как управлять людьми" слишком очевидны. Нормальный программист просто расстроится, потому что знает, что нельзя заставить мозг работать по-другому, а плохой программист будет старательно делать вид, что он ринулся в бой, но результата из этого не получится (совет: если ваш программист плохой, увольте его, никаких других способов это исправить нет).</p>
<p>Вместо этого надо добавить к вопросу еще одну метрику помимо сложности — важность. По личному опыту скажу, что часто программисты, отвечая на вопрос "а не сложно ли будет...", отвечают на уже следующий вопрос: стоит ли важность задачи времени на ее реализацию. Многие программисты считают (и часто вполне обосновано), что достаточно хорошо представляют себе общую ситуацию, чтобы сразу сделать вывод об общей целесобразности работы. И этим ответом просто стараются сэкономить всем время.</p>
<p>Но часто они ошибаются. Поэтому надо явно попросить программиста оценить <em>именно</em> сложность, в отрыве от всего остального, выразив ее в самых понятных единицах: часах работы. Причем, надо быть готовым к тому, что сама оценка тоже займет время, и потребует множества уточнений условий. Больше того, если в ответ вы услышите что-то вроде "ну... (пауза 2 сек.)... неделя где-то", то это оценка не срока, а строгости выражения вашего лица. Сделайте доброе лицо и попросите программиста все же подумать как следует денек-другой, как это будет реализовываться, все посчитать, и сказать, сколько займет часов.</p>
<p>И последнее замечание. Задача программиста — программировать. А организовывать процесс программирования, в который входит и взаимооценка сложности с важностью — это ваша задача, дорогие руководители.