Как стать автором
Обновить

Комментарии 144

33 (3) — это лучшее решение, которое при компиляции развертывается в string.Concat(a,b,c)
50 — сравнение строк на идентичность через CompareTo семантически неправильно
56 (2) — есть вероятность что поток закроется после 64,65 :)
56 (2) — есть вероятность что поток закроется после 64,65 :)

Это не ошибка, ведь ниже 64-й строки поток не используется.
Вы правы, спасибо.
Так хотел зацепить конкатенецию, что увлёкся и нахамутал :)
Скорее всего зачем-то в коде хотят подчистить объекты более старшего поколения. Непонятно по коду, зачем. Плюс побочные эффекты.
Два вызова GC.Collect() для отработки финализаторов?

А делать так не стоит, потому что многие молодые объекты, на которые остаются ссылки, могут попасть во второе поколение, в результате вызовут частые излишние сборки всех поколений, а не только 0 и 1.

Я прав?
При первом вызове объект помечается как мусорный и после уборки, в фоне вызывается его финализатор. Как результат, объект остаётся в памяти. При втором вызове, объект будет окончательно удалён. Если финализатор успел вызваться :) По-хорошему, между обоими вызовами необходимо вставить GC.WaitForPendingFinalizers()

Однако, два раза подряд вызывать полную уборку мусора и грузить CPU ради одного финализатора — негуманно. Для аналогичного поведения лучше использовать другие механизмы.
Я понимаю, что это бред. Но не на пустом месте рожденный. В частности хотелось услышать правильный ответ на
Также я ожидаю услышать почему именно два вызова подряд и почему так делать всётаки не стоит
Так ответы на это есть в моём комментарии выше!
да, правильный ответ уже дали в комментариях — в приложении потенциальные проблемы с памятью, и таким образом разработчик «гарантировал» уничтожение обьектов в том числе и из очереди финализации (хотя как уже сказали, это не совсем так).
Плохо это, ко всему прочиму, и тем — что сборка мусора весьма трудоёмкая задача и негативно скажется на производительности приложения.
Закроется только в релизной версии с включенной оптимизацией кода. Иначе локальные переменные трактуются как «живые» вплоть до выхода из области их видимости.
Первые два пункта — абсолютно верно, compareTo дает менее строгий результат, чем equals, например в некотрых локалях «u» и «u с черточкой» выдают compareTo == 0
Такой подход применяли на мне на одном из собеседований, показали какой-то жуткий код на JS, который явно писал верстальщик. На мой взгляд, неплохой вариант, но дать пару задачек помимо этого не помешает, можно совсем простых, типа fizzbuzz, буквально на 10-15 минут.
> 33 (1) – Потенциальная место для использования SQL инъекции. Так как для формирования запроса используется конкатенация а не параметры. А во вторых – не параметризованные запросы не кэшируются сиквел сервером (если СУБД сиквел).
> 33 (2) – Подобный стиль формирования запросов «привязывает» приложение к конкретной СУБД).


и кто вам сказал что там SQL? Может там (в DAL) свой DSL, который очень похож на sql, но таковым не является. Так что это потенциальное место для холивара ) (к слову select *, равно как и запрос там — тоже косяк если уж у вас sql)
Холивар — это прекрасно! Значит человеку есть что сказать! :)
А если в организации только MS SQL, на хрена городить огород с другими базами? Для крутости?
Нечеткая постановка задачи.
Если вы берете человека для того, чтобы он исправлял чужие ошибки — вполне действенный подход.
Но этот метод ровным счетом ничегоне говорит о том, как кандидат будет сам создавать что-то новое.
Это делается для того, чтобы попытаться лучше оценить уровень человека (знания+опыт). Какая разница, что он будет делать?
Ну, разница приблизительно такая же, как если бы при найме хирурга оценивали исключительно его способности в качестве патологоанатома.
Если вы хотите, чтобы человек для вас играл на скрипке — проверьте, как он играет. Сыграть для него самому и выслушать его критику — крайне сомнительный подход.
Нет, мне кажется ваша аналогия вобще не в тему. Любой врач должен владеть очень широким общим набором знаний из медицины. И хирург, и лор. У программистов тоже самое — есть вещи, которые должны знать все, вне зависимости от того, что именно человек будет делать на своей позиции. Это уже сто-пиццот раз обсуждалось, и объяснять это смысла наверное нет. Так вот, здесь проверяется не способность анализировать код (это к вашей аналогии), а именно знания и опыт в предметной области. Увидьте разницу: не проверить, как он может проводить код-ревью, а через код-ревью попытаться оценить его уровень. Совершенно разные вещи.
Поробую еще раз донести свою мысль.
Если вы берете на работу программиста, чтобы он программировал, то надо бы проверить, насколько хорошо он программирует. Можно, конечно, попробовать как-то оценить этот навык косвенно, но зачем? Ведь прямой способ предельно доступен, и к нему на интервью готовы обе стороны.
Когда-то очень давно, когда я сам еще иногда бывал в роли кандидата, меня пытали на интервью «олимпиадными» задачками. Я спросил — а вот если вы меня возьмете на работу, я именно такие задачи буду изо дня в день решать? А если нет (что очевидно), то, возможно, обеим сторонам проще было бы понять, насколько мы подходим друг другу, в прцессе решения типичной реальной задачи? В тот раз, кстати, я интервью прошел успешно, но их психолог меня зарубил на следующем этапе.
Если вы берете на работу программиста, чтобы он программировал, то надо бы проверить, насколько хорошо он программирует.

Можно узнать, как? Попросить его написать программу, что ли?

Либо я действительно не понимаю вашу мысль, либо вы никогда не отбирали людей и не понимаете, что это такое. Дело в том, что выше описан один из способов «проверить, насколько хорошо он программирует». Это моя мысль, и я бы хотел донести ее до вас.
Именно, попросить написать программу. Как ни странно — это работает. Старик Оккам рулит.

Людей я за свои 19 лет профессиональной деятельности набирал неоднократно (мягко говоря), кандидатов через меня, наверное, сотни три прошло в общей сложности. Свой подход к решению этой проблемы выработал уже давно. На мой взгляд — работает он хорошо.

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

Людей я за свои 19 лет профессиональной деятельности набирал неоднократно (мягко говоря), кандидатов через меня, наверное, сотни три прошло в общей сложности. Свой подход к решению этой проблемы выработал уже давно. На мой взгляд — работает он хорошо.

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

Как известно, при найме сотрудника нужно оценить два главных параметра: насколько он адекватен в принципе и насколько он соответствует вакансии технически. Причем первый параметр более важен, т.к. научить человека профессиональным навыкам проще, чем исправить его личностные характеристики, мешающие вам работать с ним по 8+ часов в день в одном помещении.

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

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

Задание при этом я подбираю так, чтобы оно было реально похоже на работу, которую будущему сотруднику придется так или иначе делать в один из своих рабочих дней. В качестве примера: был у меня как-то длительный проект, который практически полностью состоял из работы с двумерными табличками текстовых данных (первая строка — заголовок с названиями полей, все последующие строки — данные по столбцам). Абсолютно все сотрудники так или иначе работали с данными в таком формате. Тестовым заданием было получить текстовый файл с такой табличкой на вход, загрузить в придуманную кандидатом структуру данных, отсортировать строки по значению одного из столбцов и вывести в другой текстовый файл аналогичного формата. И два бонусных (необязательных) задания — показать табличку в UI и открыть ее же в Excel.
Ок, спасибо. Значит все же «написать программу» недостаточно, и вы это подтверждаете. Более того, это даже не первый барьер на собеседовании, т.е. вы предлагаете поработать с кодом не сразу и не всех. Вот тут очень интересно, как вы заканчиваете собеседование после первого этапа, если он провален? Вы сообщаете кандидату сразу, что он не подходит? Или отпускаете его с мнением, что собеседование у вас в компании — это несколько простых вопросов за 20 минут?

Вы рассказываете о свеой компании до начала разговора? Этот вопрос для меня особо актуален. Рассказывать о себе в начале как-то не могу воспринимать. А отвечать на вопросы о себе в конце, когда понятно, что эту человеку будет дан отказ (иногда решение принято уже во время собеседования) — это неприятно и чувствуешь себя лжецом.
Конечно, это необходимое условие, но не достаточное. Я, вроде бы, обратного и не утверждал.

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

Что касается отказа, то я всегда считал (и продолжаю считать), что честность — лучшая политика. Если человек не подходит — не вижу смысла тратить его и свое время. Мне не трудно сказать «нет». Правду говорить легко и приятно.(с)

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

А если говорит что-то вроде «я не смог этому идиоту доказать, что самописная БД без продуманного сценария перехода на мэйнстрим — это бОльшие риски»? :) То есть винит как бы себя («я не смог»), но все же подразумевает, что никто бы в этой ситуации не справился.
Я бы не хотел работать вместе с человеком, использующим подобные формулировки. Причем допускаю, что ему со мной тоже было бы весьма тяжело, так что я думаю, что мы расстались бы к взаимному удовлетворению.
А что, реально такие («идиот») используют? Я всё же образно имел в виду.
Люди бывают очень разные.

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

Вы для этого пишете отдельную программу?
head -n1 infile > outfile # copy header
tail -n +2 infile | LC_ALL=C sort -k {номер столбца} >> outfile

(Для числовой сортировки — добавить ключ -n к sort, если поля разделяются конкретным символом, а не пробелом+табуляцией, то добавить ключ -t туда же.)
Э-э-э… Если вы таким образом хотели пройти интервью на вакансию, закрытую в 2004м году, то вынужден вас разочаровать.

А вот если показать всем нам, какой вы молодец — у вас все получилось!
Это не олимпиадная задачка.

Реальные задачи хорошо давать, но обычно в конторе уже есть свой фреймворк, под который надо писать. И его изучение на хорошем уровне — не одна неделя. То есть, слишком долго для тестового «реального» задания. Хотя, если контора клепает по конвеерному принципу 10 проектов в месяц на стандартных конструкторах, можно дать и реальное задание.
но их психолог меня зарубил на следующем этапе.

Слишком умный? :)
С психологом у нас не сложилось прям с первого же вопроса… Она спросила «Ну и почему же Вы хотите работать в нашей компании?». На что я ей ответил, что к настоящему моменту я прошел уже 4 этапа собеседования (HR, тесты на общую грамотность и интеллект, письменные вопросы по специальности, собеседование с техническими специалистами) и в результате их компания, очевидно, знает про меня много всего. Но вот я про их компанию и свою предполагаемую работу в ней не знаю вообще ничего (ну, помимо информации на официальном сайте), поэтому никакой уверенности, что я в ней хочу работать, у меня нет. Еще минут через 20 нашей беседы психолог начала заикаться. Через день был звонок «нам показалось, что мы не подходим друг другу», с чем я полностью был согласен.

P.S. На всякий случай — это был CBOSS. Я потом всем своим знакомым и подчиненным (особенно) крайне рекомендовал к ним на собеседование сходить — потрясающий опыт.
Однозначно «слишком умный» :)
У меня знакомого так зарубили после технического интервью в Opera вопросом «что вы хотите изменить в нашем браузере», а он ответил «не знаю, я фаерфоксом пользуюсь» :-) и вроде же, по его словам, прекрасно прошел техническое собеседование. И я недавно собеседовался в Wargaming и очень боялся вопросов про WoT т.к. я ни разу в него не играл и не видел, но прошёл :-).
Ну, собеседуясь в такую крупную компанию можно было и поизучать продукты — сыграть пару боёв, посмотреть, что да как, игра ведь бесплатная. У меня даже обратная ситуация — если кандидаты присылают какие-то проекты, среди которых указаны игры — я обязательно зарегистрируюсь и поиграю часок-другой перед собеседованием, чтобы был предмет для разговора.
Ага, в WoT сыграешь пару боев — очнешься через несколько месяцев ;-)
Опыт УЖЕ есть?)
По-моемому, как раз автор и предлагает проверять знания программиста «от обратного», разве нет? Что в этом методе плохого? Если задуматься, то ваше предложение попросить человека запрограммировать что-либо в качестве тестового задания является тем же самым, вы в итоге будете изучать его код и смотреть что человек знает, а что не знает. Тут же вы заведомо знаете, где сделаны ошибки, и можете оценить кандидатов относительно собственных стандартов.
НЛО прилетело и опубликовало эту надпись здесь
Как человек создаёт что-то новое, мы увидим когда возьмём на испытательный срок, вопрос в том — брать на испытательный, или нет.
А если «чукча» не читатель, то в команде он скорее всего не приживётся…
>Но этот метод ровным счетом ничегоне говорит о том, как кандидат будет сам создавать что-то новое.

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

Это и есть та причина по которой я написал и опубликовал этот пост :)
Люди, квалификации которых я безоговорочно доверяю — не находятся в стрессовой ситуации, не ищут работу и им незачем что-то мне «доказывать». И я точно знаю что они это знают, и если просто отвлеклись на 5 минут глянуть тест — то не могут выступать в качестве чистого эксперимента.
Без определения базиса для оценки далеко не уедешь.
По полученным результатам может ничего не получиться: задача может отказаться или слишком простой, или слишком сложной.
Без нормировочной оценки или много людей «пройдет» тест или много «завалится».

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

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

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

Судя по всему, попробую ваш вариант с анализом кода.
А можно поподробнее про схему?
Пока только в ЛС
НЛО прилетело и опубликовало эту надпись здесь
поколения?
НЛО прилетело и опубликовало эту надпись здесь
Думаю дело в финализаторах: если у мёртвого объекта есть финализатор (где идёт непосредственное закрытие хендлов и т.д.), то финализатор вызывается только при следующей сборке мусора. До сего момента объект просто помечается мёртвым и ставится в очередь на финализацию.
Нет не так. После постановки финализатора в очередь на выполнение объект переводится в следующее поколение, но когда сборщик вздумает собирать это поколение — не известно. В большинстве случаев это будет далеко не следующая сборка.
Да, именно поэтому в двух вызовах Collect() в общем случае нет смысла :) Мы забываем про смену поколения…

Ан нет. Посмотрел MSDN — вызов Collect() без параметров вызывает полную уборку мусора, поэтому двух вызовов должно быть достаточно.
upd: Если между ними был GC.WaitForPendingFinalizers(). Теперь точно всё :)
Есть специальный метод WaitForPendingFinalizers или вроде того. Его лучше вызвать перед вторым коллектом
И что должен делать этот код
lock ((object)777)

Одна из целей — выяснить, знает ли собеседуемый конструкцию lock.
Затем, знает ли отличие между lock (this) и lock ((object)777).
Впрочем, тут более существенная ошибка — lock защищает только присваивание, которое и так атомарно.
> lock защищает только присваивание, которое и так атомарно.

дополню: присвоение не всегда атомарно (не для всех типов) — подробнее см. п 5.5 спецификации языка.
Ага, сегодня присваивание атомарно, а завтра инкремент!
Ну и в принципе в геттере свойства ex.Message может быть все что угодно.
вообще обычно private static _syncRoot = new Object(). (object)777 — все-таки из разряда бывает ли public new virtual MethodName()? Ну бывает, но в реальной жизни вы это видели? А даже если видели — это уже косяк, ввиду корявого приведения к базовому типу. Тут тоже самое, каждый раз будет боксинг, но я ни разу ни видел такого кода, а вот lock(this) видел.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Или означает работу с каким-нибудь Excel через COM :))
О, точно. Вспомнил этот пункт :)
Хотели лочиться на число 777, но на value тип лочиться нельзя, поэтому скастовали его в объект.
Однако каждый раз будет делаться боксинг числа в новый объект, и блокировки никогда не произойдет.
17 LastError принято делать ThreadStatic, хотя это тоже не всегда корректно (например, в контексте IIS либо другой среды, использующей пул потоков, корректно использовать OperationContext, а threadstatic приводит к багам)
Хороший метод. Показывает, видит ли кандидат конретные ляпы и насколько умеет ухватывать общее назначение кода, дабы подмечать где «неочевидная бизнес-логика», а где «бесполезная информация в логах».

Если шустро щёлкает первое — можно смело брать джуниором или даже миддлом (по итогам дальнейшего общения), если глобально оценивает код — значит повезло, перед Вами потенциальный senior.
4, 32, 48 — Согласно общепринятому соглашению об именовании, имена символов (переменных, классов, нэймспейсов и пр.) не рекомендуется сокращать. Акроним DAV не является общеизвестным, а значит его тоже нельзя использовать. Ну а если уж использовать, то акронимы длиннее двух букв пишутся как обычное слово, т.е. Dav.
37 — lock не только не работает, но он еще и бесполезен, ибо одиночное присваивание к гонкам не приводит.
50 — String.CompareTo() производит культуро-зависимое сравнение. Т.е. будут проблемы с юникодом и «культурными особенностями», например в немецком "ß" будет равен «ss». Также при таком сравнении некоторые символы игнорируются (мягкий дефис, например).
50 — String.CompareTo() производит культуро-зависимое сравнение

Это только пенальти по производительности или как-то скажется на безопасности приложения.
Можно ли залогиниться, не зная пароль, если мой пароль наподобие qwerty123?
Это незначительно скажется на безопасности, ибо один и тот же пароль можно будет задать несколькими способами. Сколько таких способов — зависит от культуры. Но представьте, что завтра в мире появится такая культура, в которой есть символ-джокер ?, который равен любому другому символу (ну вот такие вот культурные особенности у людей, ничего не поделаешь). И так не повезет, что сервер использует именно эту культуру. Тогда ваш qwerty123 можно будет ломануть введя ?????????..

Кстати выяснилось, что хабр переглючило от символа U+1F0CF.
Хороший способ оценить быстро базовые знания сразу по нескольким пунктам. Эдакая альтернатива тестам.
CompareTo() при сравнении учитывает региональные особенности. Следует использовать CompareOrdinal() или Equals(b, StringComparison.Ordinal).
Является ли для вас на собеседовании показателем успешно сданный 483 экзамен Microsoft, либо иные сертификации?
Экзамены Microsoft может сдать и ребенок заучив дампы из интернета.
Бейте дамперов их же монетой, заучившие и сдавшие по дампам забывают все в том же месяце. Хотите проверить знания? Включите на собеседовании симуляцию теста, например с этого сайта: exambraindumps.com/
Времени экономится уйма
Лично для меня — нет, ибо у меня их несколько и я знаю им цену. :)
От сертификата всего две пользы — первая — когда (если) вы к нему готовитесь (не важно как) — вы узнаёте что-то новое, что может пригодится в будущем для решения задачи, и вторая — для отдела продаж вашей компании которые могут урвать заказ только потому, что у у них есть сертифицированный лид, а у конкурентов — возможно, нет.
Собеседовал недавно «сертифицированного разработчика». Не смог ответить на вопрос, чем отличается переопределение виртуальной функции virtual/override от не виртуальной с помощью new, не говоря уже о том, чтобы объяснить, почему виртуальные функции называются еще методами позднего связывания.
Я так понимаю, что с учетом отношения числа замечаний на количество строк кода, реакцией нормального человека будет подумать «Этот парень идиот», а вслух сказать, что «Тут все надо переделать, и чего, собственно, хотелось добиться?»
Мне, честно говоря, было бы стыдно, собеседуя ведущего разработчика, давать ему исправлять такой код. Для опытного разработчика решение очевидно — проанализировать требования к интерфейсу данного сервиса и переписать его с нуля.
Это хорошо, что очевидно, но по-началу не ясно — опытный ли он, или же взявшись переписать — напишет тоже самое.
Поэтому достойно собеседовать кандидата не так-то просто.
Вопрос же не в том, что надо переделать. А в том, какие тут ошибки. И смысл в том, чтобы оценить то подмножество ошибок, которые заметит кандидат, и то, как он их объяснит. Хотя можно дать и меньший по размеру код с меньшим числом ошибок, или несколько вариантов разного кода с разными ошибками, но в меньшей концентрации. Короче, суть в подходе, а не в реализации.
90% собеседуемых отсеиваются на суперпростых, совершенно тривиальных задачках.
Вот честно говоря не вижу смысла в таких задачах на собеседовании. Я бы в первую очередь разобрался в человеке. Как он с моей точки зрения впишется в команду (или не впишется).
Что касается технической части, то я бы спросил у человека о прошлых проектах. Рассказать что он делал, как. Рассказать о какой-нибудь интересной фиче, которую он реализовал. О каком-то открытии которое он для себя сделал.
В первую очередь человек должен быть с живым умом и желанием расти, мне кажется.
Говоришь-говоришь с ним, чай пьете, потом спрашиваешь: — Пузырьковый метод сортировки знаешь? — Знаю! — Напиши функцию. И все, зависает половина кандидатов.
Не ну я наверное тоже на пару минут зависну вспоминая такую устаревшую и неиспользуемую в моей работе вещь как пузырьковую сортировку. Но главный вопрос — зачем человеку знать ее наизусть?
Вам нужны заучки или люди которые будут решать проблемы? Подсмотреть в гугле какой-то банальный вопрос — две минуты работы.
Пузырьковая сортировка – это фундаментальные знания! Её дают на первом курсе любой технической специальности где хоть как-то читают программирование. Если даже для этого человек лезет в Google, то вряд ли стоит ожидать от него нормальной творческой работы.
Угу. Мне даже в школе давали. 20+ лет назад. И ни разу с тех пор реализовывать не приходилось.
Дело не в том реализовывал или нет! С момента когда я сдал лабораторную на эту тему тоже прошло больше одиннадцати лет, и за это время мне так же ни разу не приходилось реализовывать это на практике. Однако если человеку для реализации алгоритма состоящего из массива, двух циклов и одной дополнительной переменной (без которой тоже можно обойтись) нужен Google, то даже на позицию практиканта он может претендовать с трудом. Если же такого человека берут на должность, хотя бы, разработчик, то мне невольно вспоминается анекдот университетской поры:
— Зная какой я инженер, я боюсь ходить по врачам!
В условиях стресса, на бумажке не допустить ни одной ошибки при реализации?
Во-первых, конечно на это всегда делается скидка. А во-вторых, смотря какая ошибка: написать неправильно границы циклов не то же самое, что написать, скажем, только один цикл, то есть в корне неверную реализацию. Я в свое время писал на бумажке в условии стресса реализацию прохода по графу без использования рекурсии.
А чем плох один цикл?
  i=k=1;
  while(i<n){
    if(i>0 && a[i]<a[i-1]){
      b=a[i]; 
      a[i]=a[i-1]; 
      a[--i]=b;
    }else i=++k;
  }

Хотя, кажется, это не совсем пузырёк. Значит, не прошёл :(
Хотя, кажется, это не совсем пузырёк. Значит, не прошёл :(

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

Фиг с пузыриками, вполне допустимо и не помнить алгоритм. Благо, есть полно других задачек.
Я искренне рад, что всего пяти людям из тех, кто может голосовать, для того чтобы вспомнить элементарные алгоритмы нужен Google.
А что нужно отвечать — «Не знаю» или «Знаю только название»?
Надо было Вам правильные решения свернуть «под кат», а желающим предложить написать свои варианты найденных ошибок :-)
Имхо, многим было бы интересно :)
Последние лет 8, наверное, вообще не соприкасаюсь с .NET, но ответил бы на эти вопросы. А смысл? Нужен человек, решающий практические задачи. С этой точки зрения какая-нибудь задача для решения была бы круче.

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

Еще улыбают люди, дающие логические задачки. Ведь ни разу не коррелирует с пользой от человека.

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

Если на собеседования пришло десять человек, а вакансия только одна, то тоже ничего страшного?
Поднимайте планку. Хотя да, это просто разные рынки, у нас наоборот, — нехватка кадров.
Мне кажется хороший способо проводить техническое собеседование так:
На кануне прихода собеседуемого тех.лид вспоминает, какие реально технические проблемы или задачи появлялись в последнее время, или вертятся без конкретного решения последний год, ответ на которые не очевиден. Вспомнает что было предложено, от чего и почему отказались, что в итоге попробовали и на чём остановились. Далее перерабатывает эту задачу чтоб она имела более-менее общую формулировку и выкидывает не нужные детали.
И на собеседовании предлаете решить туже самую задачу с коротой они сталкнули и решали сами. Всегда будет что ответить на уточняющее вопросы собеседуемого, + сравнить со своими текущими решениями и таким образом оценить.
По опыту проведения собеседований (со своего места HR-менеджера) лучше всего, с моей т.з., когда кандидат проходит собеседование сидя рядом с руководителем за окошком какой-нить ВижалСтудии (или над бумажным листочком), разбирая вместе написанный кандидатом код.
Помимо формальных задач — посмотреть как человек решил/решает задачу; на этом этапе проверяется намного более важное свойство: возникает ли «индукция» между их головами во время работы. Эта «индукция» покажет, находятся ли эти два человека в одном понятийном пространстве/континуме/фазе; и, соответственно, смогут ли они изъясняться в будущем понятным друг для друга языком.
Ибо бывает так, что два умных человека не могут найти общий язык: им для этого приходится использовать либо постоянные пояснения, что же они имели в виду, либо общение через «переводчик» (какое-нибудь ТЗ, где задачи имеют четко формализованную структуру).

Этот этап «думать вместе» лучше всего использовать уже после того, как пройдены формальные тесты: на базовую подготовку (Big-O, и дискретная математика, алгоритмистика).
У тех руководителей, которые используют такой подход, наиболее стабильный коллектив (с одного проекта за несколько лет не ушел ни один программист, команда развивалась только «вширь», вместе с очень успешно развивающимся проектом).
Кстати, очень хороший способ. Именно так собеседовали меня, и через несколько месяцев, за пивом, техлид рассказал, что именно из-за этой, буквально сразу возникшей «индукции», фирма сильно пошла мне навстречу при составлении договора. В свою очередь и я признался в том, что эти 20 минут переубедили меня устроиться именно к ним на работу. Я сразу понял, что сработаюсь с человеком.
— А сколько у вас лет опыта разработки с использованием WPF?
— Я не знаю WPF….
Этот неловкий момент когда ты понимаешь, что предусмотрел всё, кроме самого очевидного…

Ну может от сильверлайт знает, что ж вы так сразу-то ;)
Для того, чтобы подход приобрел какую-то силу, более прогностичную, чем «просто собеседование» я бы проранжировал ошибки по весу и вел суммарный рейтинг. Условие прохождения теста бы уже считалось по рейтингу, а не просто по количеству найденных. Все-таки доступность метода — намного менее страшный грех, чем пропущенное место для SQL инъекции.
Совсем недавно перевел все технические интервью в следующий формат:
— Телефонное интервью, общие вопросы от HR.
— Собеседование в офисе с разработчиками, Общие вопросы (паттерны, O(xxx) и тому подобное)
— После этого, человек отправляется на http://codility.com/ и решает там тетовое задание. И там уже видно как именно он пишет код.
Интересный ресурс, спасибо.
Но вот вопрос — часто ли потом разработчику придется решать такие задачи? Ведь если нет — вы по сути, его обманываете.
Сам круг задач обговаривается устно. Ну и при покупке подписки, выбор заданий существенно расширяется, и не ограничивается задачами на знание алгоритмов и смекалку (как вариант, добавлять свои).
39, 49, 52 говоряят о том, что, помимо всего прочего, этот метод — с сайд-эффектами со всеми сопутствующими проблемами. В итоге, контракт сервиса надо реально перепроектировать :-)
Из моего личного опыта собеседований — важна не только база кандидата, а также и его способность усваивать новую информацию не вставая с места. У нас схема такая: изучаем резюме, предлагаем тестовое задание. Иногда кандидату для выполнения может потребоваться что-то изучить дополнительно, не суть. Руководитель группы просматривает код. Если совсем уныло (а такое бывает) — отказ, иначе — собеседование. При личной встрече задаём вопросы по сильно кривым местам кода, почему так, а не вот так, и как было бы лучше, предлагаем исправить. Даже если кандидат оптимального решения сходу предложить не может, всё равно видно, способен вообще человек понять, чего от него хотят (а это качество нельзя недооценивать), может ли выявлять недостатки своего кода и устранять их, если ему объяснить суть проблемы, или будет тормозить и ссылаться на то, что «в книжке я дотудова ещё не дочитал».
Конечно, есть ещё стандартный список вопросов по технологиям, алгоритмические задачки. Но, на мой взгляд, если вы никогда не видели кода, написанного самим кандидатом, объективной картины о его скиллах вы всё равно не получите, какие бы распрекрасные и глубокие вопросы на собеседовании вы ни обсуждали.
На мой взгляд все такого рода собеседования ничего не говорят об опыте человека. Человек либо знает что то либо нет. Если он притендует на эту должность — это зачет что всё таки он что то знает (либо считает что может справится с этой работой). Лично у меня было много раз когда подавал заявку на вакансию, затем приходило тестовое задание от компании. Я его делал в течении суток двое. Отсылал код. Людям мой код нравился и они назначают мне интервью. Но вот на самом интервью всегда начинаются проблемы. Люди начинают спрашивать какие то вопросы из разряда насколько вы хорошо зазубрили стандарт С++ или также дают бумажку с кодом и спрашивают — какие вы здесь видите ошибки в коде. Меня такие вопросы раздражают так как если я что то забываю из стандарта — то это всегда за 2 минуты моно посмотреть в гугле и писать код дальше. По поводу подхода с бумажкой с кодом — тоже бредовый вопрос. Не ну я не спорю что в бумажке с кодом могут оказаться синтаксические ошибки, или очевидные ошибки например потеря указателя или некорректное освобождение памяти или некорректно организованное наследование без использования виртуальных функций и т.д. Но вот если в бумажке из 60 строк кода допущено 50 ошибок — это уже полный бред. Никто на собеседовании сидя у вас в офисе под прицелом взглядов менеджеров и в состоянии повышенной взволнованности не назовёт вам все 50 ошибок.
На мой взгляд самый действенный подход — это дать человеку тестовое задание на 2-3 дня и не мучить никакими вопросами из стандарта или давать бредовый код с кучей ошибок и ждать что вам вот так распишут все 50 ошибок в коде за 10-15 минут. Да и врядли испытуемый будет покупать на фрилансе вашу тестовую задачу или списывать её под чистую с какого то готового решения. Ну и наконец если человек справляется за короткое время с тестовым заданием то остальное можно узнать за период испытательного срока.
Если бы мне сказали, что это реальный рабочий код, а не шарада, то отметил бы только 20% перечисленного — критичные ошибки вроде замены текущего юзера, выбора первой записи, проверок на null, опасный лог. Остальное могло быть продиктовано политикой кодинга (возвращать WrongPass), постановкой задачи (ввод паролей с умляутами), неизвестными нам багами-фичами (DAL бросает System.Exception), либо не влияло на работу (дурацкий lock). Буквально, на мой взгляд List<> с AddRange тут бесполезны, а метод просится быть статическим, как и переменная с ошибкой просится стать ro пропертью, но мы знать не можем, что это затронет. Причем, раз аутентификатор выглядит так, то остальной код может быть еще хуже и GC.Collect на каждый вызов вставлен не зря. Убрать его не подумав = выйти за пределы основной задачи. И да, с таким рабочим кодом вопрос о дескрипшенах, повышенной связанности и пр. уже не актуален — у пациента отпадает нога и прихватывает сердце, ему некогда волосы красить.
Справедливо, поэтому и не стоит вопроса об автоматизации (собеседует человек). После того как соискатель назвал что увдел — я навожу на проблемные места и спрашиваю а что может быть тут не так. И тогда уже, поидее — человек должен назвать — если знает. Да и я увижу живое общение, и его способности делать предположения и обосновывать их.
Очередной дибильный тест из разряда «кто лучше знает п.5.1.2.4 спефицикации языка — кандидат или собеседующий». Соображалку надо проверять, соображалку. Умный неопытный человек за пару недель обгонит глупого опытного. Давайте кандидату писать код на собеседовании.
Это безусловно справделиво, если я открываю университет для самородков, но когда я набираю разработчиков для боевого проекта, или ищу аварийную замену — то у меня нет ни времени ни желания обучать самородков. Если человек не поленился прочитать первые несколько глав Рихтера — значит он не поленится и в гугл слазить когда прижмёт.
А во вторых, как я написал в начале, одна из задач теста — определить — что означает цифра в опыте соискателя. Если чеовек пишет 10 лет опыта разработки — но не знает чем отличается throw и throw ex — у меня вопрос — что он делал эти 10 лет? Не полагается ли он на волшебство и магию в разработке?
Я не хочу сказать что я против обучения или «молодёжи», совсем даже наоборот! Но не всегда есть возможность взять просто хорошего парня. Как правило бюджет расписан и заказчик контролирует кто работает на его проекте (я не говорю о продуктовой компании). И почти все хотят дешёвых старших разработчиков. «Студент» — это долгосрочная инвестиция которая может и не окупиться… Да и потом — студенты очень часто делятся на две категории: которые растут и уходят, и которые не растут и их уходят…
Ну, с половину ошибок или просто непонятного поведения я обнаружил вообще никогда на C# не писав (правда некоторые неправильно, скажем в перечислении я решил, что ошибка в том, что для Error не задано явное значение и какое оно получит неявно не очевидно без точных знаний спек языка). Это не проверка на соображалку?
Главная, на мой взгляд, ошибка в этом методе состоит в том, что инстанс-метод Login класса LoginService пишет в глобальную переменную (статическое поле) App.CurrentUser. То есть, имеет неожиданные сайд-эффекты.
Нормальный тест, не сильно лезет в спецификацию, не только на технику, но и на стиль.
Некоторые вещи правда на грани фантастики: lock ((object)777) и catch (ex) throw (ex) — нужно сильно жестить, чтобы такое написать.
А про конкатенацию строк, sql и GC.Collect и тд- все правда.
еще бы добавил
28 — если во всех остальных местах переменные объявляются через var, то для однообразия тут надо делать также.
43 — (count<0) Можно заменить на Any() (если верх добавим System.Data.Linq)
49 — dbLogins[0] — Ноль здесь очень похож на «магическое» число
catch (ex) throw (ex) — нужно сильно жестить, чтобы такое написать.

А что же писать, если мы действительно хотим как-то отметить, что был exception (например, вывести сообщение и стек в свой log), но сами обработать его не готовы?
Все конечно зависит от контекста, в общем случае у вас получается некоторое смешение ответственности — в лог он добавляет сообщение об ошибке, однако обработать ее не может и выбрасывает точно такое же наверх, а если верхних класс тоже будет настроен так что будет добавлять ошибку в лог и выбрасывать дальше?
Это может быть немного оправдано, если класс ошибки уточняется, вот такой тоже трэш-вариант мне кажется имеет больше смысла
class MyTypeException: Exception
{ ... }

class MyType
{
      public void RunSomething()
      {
             try
             {
                   DoSomething();
             }
             catch (Exception e)
             {
                    ....
                    throw new MyTypeException();
             }
      }
}


Короче в любом случае, мое мнение, если вы столкнулись с необходимостью такой обработки исключения что-то не так с архитектурой.
Вобще любой отлов базового класса Exception, говорит о не понимании, того, что может произойти в блоке try.
Стек теряете, Inner Exception надо использовать в таких случаях. Ну и конечно не Exception в try-catch'е должен быть, а специфическая ошибка и будет не треш.
Специфическая ошибка может быть тогда, когда вы уже знаете, какие ошибки вам могут вернуть. А это не всегда бывает.
Inner Exception поможет, есть тот, кто перехватит ошибку сверху, будет готов проверить, есть ли Inner Exception, и проанализировать его. А иначе уже он потеряет возможность ловить специфические ошибки.
Все конечно зависит от контекста, в общем случае у вас получается некоторое смешение ответственности — в лог он добавляет сообщение об ошибке, однако обработать ее не может и выбрасывает точно такое же наверх, а если верхних класс тоже будет настроен так что будет добавлять ошибку в лог и выбрасывать дальше?

Если ему понадобится, он будет добавлять ошибку уже в свой log — и это будет уже разделение ответственности. Действительно, ситуация зависит от контекста.
Вообще любой отлов базового класса Exception, говорит о не понимании, того, что может произойти в блоке try.

Разумеется, за этим они и нужны. Exception — значит, случилось что-то вообще не предусмотренное разработчиком, и всё, что можно сделать — вывести максимум информации об этой ситуации, чтобы потом человек мог разобраться, что пошло не так.
Конечно, это всё зависит от принятых соглашений. Если для кого-то Exception — один из способов возврата из функции, который может случаться и в «штатной» ситуации — ему надо анализировать, что же такое прилетело.
Вот как раз сейчас осознанно пишу код, который содержит catch (Exception ex) :)) И без вариантов, похоже…
Но да, за последние много лет такое впервые.
Простой throw же
Спасибо. Это действительно работает как надо.
А какой процент людей отвечает «полно», с вашей точки зрения. К сожалению, мой опыт показывает, что в основном люди не могут ответить чем Dispose от ~ClassName отличается. Каких сказок не наслушался только.
17) Зачем инициализация. Не надо.
Слишком большой код, собеседование — это всегда стресс, и давать только 20 минут на то, чтобы найти все ошибки в одном большом фрагменте (надо понять, что он делает и что он должен делать — это может быть большая разница, просмотреть синтаксические, логические и архитектурные ошибки) просто несправедливо. Кадидат может быть очень талантлив, но при это быть немного медленным в разностороннем анализе. Я бы лучше предложит несколько задач, содержащие разные типы ошибок, тогда будет проще сконцентроваться (найдите все синтаксические ошибки в этом фрагменте, какие test-case-ы были пропущены для другого фрагмента, какие входные данные могут создать проблемы в третьем фрагменте и т.п.)
Разве это большой код?
Код-то небольшой, но автор статьи ожидает, что кандидаты найдут все ошибки без каких-либо подсказок. Я бы все-таки сгруппировал задачи и использовал несколько примеров.

Простой вопрос — сколько ошибок в строчке «printf(»%s", str);"? Формально это нормальный код, но в разном контексте он может содержать кучу ошибок — NULL указатель (что может быть как валидно, так и не валидно, glibc может печатать "(null)" в качестве вывода), есть ли терминальный нуль, указывает ли на доступную область памяти, работа с юникодом, экспейпинг вывода если печатает в HTML. Многое зависит от контекста, и зачастую вопрос «найди мне все что тут неправильно» просто некорректен, особенно если интервью сильно ограничено по времени.

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

Или даже пример из статьи. Что, если лог потом просматривается через веб-сайт и пишется в HTML как есть? Тогда например, я смогу себе сделать App.CurrentUser.Name, которое будет содержать XSS (если это возможно в программе). Слишком много нюансов, для 20-ти минут — это явный перебор.
1. Вряд ли надо найти все ошибки, достаточно 50%
2. Я не думаю, что собеседующий подразумевает нестандартное использование (что видно на sql-инъекции, тут сразу стали возражать, что это DSL а не SQL), но подразумевается, что не нужно придумывать усложения, а нужно предполагать, что тут самый обыкновенный/типичный код.
Нет, я не ожидаю что найдут всё. Я ожидаю что увидят хотя бы значимое, а затем сам пройдусь по тому интересному — что осталось и ожидаю что беседа будет продолжена (например не заметили throw ex -> спрашиваю чем отличается от throw, если человек хотя бы слышал что есть ситуация когда глушится стэктрэйс — это уже отлично, а вот елси начинает «утверждать» что throw; породжает чтото мифическое и непонятное… то… грустно :) ).
И если видно что человек бойко тянет — то мусолить код смысла никакого нет, выходим на философию разработки и опыт того что интересного доводилось делать и бла-бла-бла :)
>Нет, я не ожидаю что найдут всё.

А предупреждаете об этом соискателя? :) Я вот заметил что различные варианты формальных тестов, отличных от «напиши код (в IDE — рабочий, на бумажке — не обязательно)», у меня часто вызывают ступор, тряску рук, обильное потение и т. п., в условиях собеседования, когда любая ошибка может изменить (вернее не изменить) оставшуюся жизнь.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории