Pull to refresh

Comments 116

Чего не скажешь о третьей картинке с мужчиной по центру, сидящего спиной в наушниках.
Но я гарантирую, что наступит момент, когда мы все будем ломать головы над проблемой перед самым дедлайном, когда мы вымотаны в край, на нас все злятся, а на кону стоит наша работа и репутация.
Если такие моменты гарантировано наступают в этой конторе — это лучшая иллюстрация того, что интервьюер, мягко выражаясь, переоценивает себя и постоянно что-то делает на собеседованиях «не так», что приводит к найму «не тех».
Да ладно, в любой команде/компании всегда бывают жесткие запары. Необязательно из-за того что сотрудники некомпетентны. Сервера падают, случаются атаки на приложения или инфраструктуру в целом, клиенты внезапно осознают проблемы с требованиями — триггеров «аппокалипсиса» очень много может быть. И вот в таких, в идеале редких, ситуациях умение оперативно мобилизировать все свои скиллы очень важно.
Запары — да, бывают. Но тут же реально АД описан:

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

2. когда мы все будем ломать головы над проблемой
Почему ВСЕ должны ломать голову над одной проблемой? Опять ошибки в управлении.

3. на нас все злятся, а на кону стоит наша работа и репутация
Не слишком ли много «мы», «все», «нас», «наша»? Какой-то «колхоз», а не фирма по разработке ПО!
Как я понимаю у автора напрочь отсутствует представление о персональной ответственности конкретных людей за конкретные участки работы.
Почему ВСЕ должны ломать голову над одной проблемой?

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

Как я понимаю у автора напрочь отсутствует представление о персональной ответственности конкретных людей за конкретные участки работы.

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

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

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

И если это именно он нанял некого условного Васю в свою контору на конкретную должность, на которой этот Вася так облажался в аккурат перед дедлайном — неужели виноват только Вася?

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

Есть такая техника Мозговой штурм. Возможно автор имел в виду именно это?
Что-то в нашей конторе я подобных запар за последние семь лет не помню. Может быть, у вас что-то не так?
Меня всегда удивляла ситуация, когда на собеседовании рассказывают какие все профессионалы и как идеально все делают, но при этом очень активно интересуются стрессоустойчивостью. Хорошо стресс интервью не устраивают.
Так-же по коду сразу видно что интервьюер не читал Чистый код Мартина. Он там дело говорит. Код должен быть читаемым и без комментариев. Необходимость прокомментировать код говорит от том что его нужно рефакторить. А уж комментировать каждую строчку это мягко говоря излишество. Пустая трата времени.
Лучшее что может сделать интервьюер — дать такие гарантии на как можно более раннем этапе собеседования. Это обоим сэкономит уйму времени.
UFO just landed and posted this here
Везде хороша золотая середина.
UFO just landed and posted this here
Дык, любителям самодокоментирующегося кода можно предложить написать ЗАЧЕМ этот простейший код это делает:

for(var i = 0; i < arr.length; i++) { if(arr[i] === 'ok') ok = true; }
В смысле, зачем он не прекращает бессмысленную беготню по массиву после первого тру? Действительно, это стоит прокомментировать. Может, оператор "=" здесь перегружен и имеет кучу побочных эффектов?

Или оператор [] перегружен, и на самом деле читает не данные из памяти, а дёргает внешнее устройство, которое совершает какие-то действия — например, ампулы встряхивает.

UFO just landed and posted this here

Не то чтобы, но вообще...


ok = arr.includes('ok');
ok = arr.indexOf('ok') != -1;
ok = arr.some(e => e === 'ok');

P. S. На JS почти не пишу. Так, мимо проходил. Бесполезные циклы в коде не перевариваю — хоть с комментариями, хоть без.

Это не самая хорошая теория, да и доводы «за» слабоваты.
Желательно, что бы код был достаточно очевидным (имена функций, переменных, использование циклов, иф/елсов)

Не бывает слишком понятного и слишком очевидного кода. Бывает достаточно понятный. Для остальных случаев есть комментарии.

Комментарии периодически устаревают.

А еще — о ужас — периодически устаревает сам код. По логике «комментарии устаревают, поэтому давайте не будем их писать» код программы, который тоже устаревает, надо не писать. Зачем писать программу, если она гарантированно устареет? И ее придется — представляете — править!
UFO just landed and posted this here
В большинстве своем код достаточно тривиален и конвенций хватает для того, что бы его не комментировать.

В этом случае и не нужно комментировать. Концепция «наличие комментариев в коде скорее минус» об этом не говорит. Если предполагать, что код обязан быть тривиальным, то это попросту не всегда возможно.

Ирония хороша, когда она по делу.

Дельнее некуда: аргумент «придется править» ни о чем и по сути не отличается от «код придется править». Предполагая, что комментарии не являются частью кода.

Но если по сути, то, помимо кода, Вам придется потратить время и поправить еще и комментарии

И на форматирование, и разбивку по блокам и вообще рефакторинг, документирование интерфейсов. А еще написание тестов.

А если код живой, то правиться он будет много раз. И одна правка комментариев превратиться в десяток.

Мне сложно представить комментарий такого вида, который не является избыточным, но при этом настолько привязан к коду, что его придется не просто удалить, а подгонять каждый раз.
UFO just landed and posted this here
Собственно о том и речь — есть, где уместно, есть, где нет.
В чистом виде ваше
Есть неплохая теория о том, что наличие комментариев в коде скорее минус…
Так что здесь скорее стоит уточнить, что комментирование кода это скорее конвенция на Вашем проекте, чем требование к продакшн коду.

неверно.
> Если предполагать, что код обязан быть тривиальным, то это попросту не всегда возможно.

Бездоказательный вброс

> Дельнее некуда: аргумент «придется править» ни о чем и по сути не отличается от «код придется править».

Да, ни чем не отличается. Придётся править 2 раза вместо одного.
Бездоказательный вброс

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

Да, ни чем не отличается. Придётся править 2 раза вместо одного.

Как и тесты, где-то заголовочные файлы, форматирование и все остальное. n+1 раз вместо n.
> Отнюдь

бездоказательный вброс

> Как и тесты, где-то заголовочные файлы, форматирование и все остальное. n+1 раз вместо n.

Мне про заголовочные файлы особенно понравилось, модно, молодежно.
То есть вам что n, что n+1, что n^2? Оплата повременная?
бездоказательный вброс

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


Мне про заголовочные файлы особенно понравилось, модно, молодежно.

Модно-не модно, но заголовочные файлы в том числе — отдельный объект возможной правки.

То есть вам что n, что n+1, что n^2? Оплата повременная?

Переход от n+1 к n^2 очень веселый — математическая обертка обычной демагогии.
Ну, не пишите тесты и/или документацию — оплата-то не повременная. Раз-раз и в продакшн, да?
Разница в том, что я могу аргументировать зачем мне тесты чем-то, кроме «было n, будет n+1»

Код должен быть самокомментирующимся в том смысле, что читая его, должно быть понятно, что он делает.


А вот комментарии предназначены для того, чтобы объяснять, зачем код это делает.

Нет, наличие комментариев это плюс
Просто приведенный пример «хорошего кода» — это просто образец того, как не надо писать комментарии.
Комментарий
// throw if we didn't get a string
перед тем как мы делаем throw только захламляет код

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

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

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

Когда я прочитал эту фразу — я задумался о совершенно других ограничениях, а именно:

1) Какого размера эта строка? Может ли размер этой строки превосходить размер доступной оперативной памяти (например, при чтении с диска)
2) Может ли её отдавать, к примеру, устройство блочного вывода без возможности поиска конкретного смещения?
3) Знаем ли мы заранее размер строки?
4) Если мы разрабатываем хэш-функцию — каков допустимый уровень коллизий, какое максимальное время выполнения, и какой результат мы можем получить в случае досрочного прерывания выполнения (ложноположительный, ложноотрицательный, исключение?)
5) Имеет ли каждый символ строки одинаковый размер (в байтах)?
6) В случае нечетного количества байт в строке — как обрабатывать «средний» символ (безусловно не палиндром, безусловно палиндром, побитовое сравнение). Если побитовое сравнение — как быть с многобайтовыми кодировками на BE\LE архитектурах?

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

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

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

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

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


Все вопросы по строкам относительно этой задачи можно запихнуть в один: в каком формате строка? (предполагая, что она будет в стандартной для данного ЯП)


Остальные вопросы (на мой взгляд) надо задавать в другую сторону:


  • Достаточно ли мне ascii набора?
  • Это нормально, если я выброшу исключение для строк, не кратных 2?
  • Можно я не будут писать комментарии в стиле Капитана Очевидность?

Главное качество программиста (на мой взгляд) — это лень. Меньше кода — меньше проблем. Меньше кода — меньше писать, меньше читать, меньше рефакторить, меньше легаси через N-лет, меньше багов, меньше тестов, меньше оптимизаций. При этом количество проблем кода растёт быстрее, чем линейно от количества этого самого кода. При этом минимум определяется довольно просто: код всё ещё должен соответствовать сегодняшним требованиям. Минимум не означает минимум количества строк. Минимум это минимальное количество когнитивной нагрузки, которую создаёт код. К этому следует стремиться, но без фанатизма конечно. Такие дела.

Это нормально, если я выброшу исключение для строк, не кратных 2?

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

В случае нечетного количества байт в строке — как обрабатывать «средний» символ
В задании фактически есть тест- на строку “race car”, должно возвращать true. Палиндром это не побитовое зеркалирование, такой вариант исключен, тем более непонятно почему бы к среднему символу должно было примениться какое то отличное от других символов правило, если это в задании никак не оговорено.

Автор явно ищет js программиста, а вы пишете явно на Си. Так что и вы и он по своему правы.
Какое, извините, техзадание на такие тривиальные вещи? Или для вас на работе для каждой элементарной задачи специальный человек пишет «техзадание»?
«Ваша функция должна принимать строку как параметр и возвращать булево значение (true, если строка является палиндромом, и false, если не является).»

Cтрока в JavaScript имеет фиксированную длинну. Даже при чтении из файла. Поправьте меня, если я ошибся.
Не понимаю необходимости в такого рода комментариях:
// make sure we have a string.
if (typeof stringToTest !== "string")

Если имена функциям/переменным заданы адекватно, то код легко читается. Комментарии ради комментариев.

Один вид этого "хорошего кода" убеждает меня в том, что я не хочу программировать на джаваскрипте, особенно в этой компании.


  1. Шесть строк кода, чтобы проверить тип аргумента.


  2. Тьма тьмущая комментариев на абсолютно тривиальном коде.


  3. Запихивание регулярок во все дыры, со всякими дублированиями данных в памяти, когда тривиально обойтись без них.


  4. Замедление функции на порядки на тривиальных вырожденных случаях из-за костыльного логирования со всякими стеками.


  5. Жёсткие костыли с прототипами, чтобы получить имя типа.

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

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

Самая эффективная реализация же!

Интересно, какая реализация считается неэффективной тогда...

Полагаю, дело в «перегретости» профессии разработчика ПО. Столько раз перечитывал Сэджвика перед собеседованиями, и столько раз забывал. В итоге, работу получал в тех компаниях, где можно было по-человечески поговорить с менеджером / техническим спецом.

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

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


Как-то так:


var isPalindrome = function(){
    var invalidCharsRgx = /^[a-z0-9]/ig;
    return function(){ /* ... */ };
}();
Они и так кешируются браузером при парсе кода, если не создали ее через new RegExp

Лично я бы сделал (псевдокод):


........

start++;
while (!isCharater(str[start])) start++;
end--;
while (!isCharater(str[start])) end--;

Не нужны ни регулярки, ни перевыделение памяти при .replace

Немного некорректный код у вас — регулярка чистила от всех неинтересных символов по всей строке, вы — только с концов.
На самом деле думал о подобном коде, но только не для чистки, а для проверки «палиндромности».

Например, вариант — если пустая строка тоже является палиндромом:

var start = 0,
end = str.length;

function isPalindrome() {
while(isNotSymbol(str, start)) {
start++;
}
while(isNotSymbol(str, end)) {
end--;
}
if (end <= start) {
return true;
}
if (charAt(str, start) === charAt(str, end)) {
return isPalindrome();
} else {
return false;
}
}
регулярка чистила от всех неинтересных символов по всей строке, вы — только с концов.

Хотел только дифф запостить, думал — у народа мозги есть, поймут, но вижу — нет… Вот Вам полный код:


 while (start < end) {
        if (stringToTest[start] !== stringToTest[end]) {
            return false;
        } else {
          start++;
          while (!isCharater(str[start])) start++;
          end--;
          while (!isCharater(str[start])) end--;        }
    }

(Долбаный таймер хабраредактирования.) В вышеприведённом коде вместо str следует читать stringToTest, при этом предварительная очистка stringToTest регекспом не нужна. Функция isCharater(c) должна возвращать true, если символ c является алфавитным (то есть НЕ пробелом или знаком препинания) — это можно реализовать сравнением ASCII кодов без всяких регекспов.

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

Конечно, неполный код показываю — я же не на интервью! — а в пару строчек даю общую идею, как малой кровью обойтись без регекспа и перевыделения памяти. Кому сильно надо — допилит напильником, там совсем несложно (при наличии мозгов, конечно).

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

А ваш пример, без дополнительной фразы (о том, что до первой проверки! надо! сдвинуть указатели) даст ошибку. Просто потому, что первый и последний символ — не всегда в списке допустимых. А про тримминг данных вы явно не сказали:
«В вышеприведённом коде вместо str следует читать stringToTest, при этом предварительная очистка stringToTest регекспом не нужна. » — тут надо гадать, почистили вы всё-таки строку или нет. Ну т.е. вы ни кодом, ни словами в явном виде не указали на это действие.

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

Язвительность же комментариев («думал — у народа мозги есть», «при наличии мозгов, конечно»), заставляют усомниться в вашей компетентности и адекватности.

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

Имеющий уши — да слышит, имеющий мозги — да додумает, а у меня в данный момент есть несколько более важное занятие, чем c точностью до запятой расписывать решение детской задачи. Для достижения удовлетворения лично мне достаточно увидеть, что решение существует (и каким путём его достигнуть), а тратить время на расписывание запятых я буду после получения подписанного контракта.


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

Регулярные выражения при работе со строками практически всегда быстрее простого кода в некомпилируемых языках (коим и является клиентский JavaScript).
Сделал небольшой тест: https://jsfiddle.net/yq9gh6mm/1/
Тестируется очистка строки от лишних символов регулярными выражениями /[^a-z0-9]/ig, /[^a-z0-9]+/ig и реализацией на чистом JS.
Реализация без регулярных выражений проигрывает почти в 4 раза по скорости второму регулярному выражению.
Использование регулярных выражений весьма оправдано, как минимум на стороне клиента.
Компиляция NodeJs немного исправит ситуацию и реализация на чистом JS почти догонит регулярные выражения, но не обгонит. Тот же самый тест на NodeJS: http://ideone.com/juoJQr

Хочу извиниться- функция в тесте не оптимальна.
Тест с оптимальной реализацией: https://jsfiddle.net/yq9gh6mm/2/
В нем "чистая" реализация проигрывает уже всего в 2 раза.
А после компиляции NodeJS "чистая" реализация на 13% быстрее регулярки /[^a-z0-9]+/ig
http://ideone.com/juoJQr

Немного поигрался с вашими примерами (https://jsfiddle.net/4x5v6yk7/), в итоге коэффициент разницы в половине случаев меньше 1.5:
Test started
test 1 4948
test 2 4675
test 3 6762

Но вообще неожиданная подстава от транслируемых языков… Интересно, что произойдёт в Nashorn.
PS но думаю я ещё не оптимально написал… есть пара мест, где можно ещё что-нибудь попытаться сделать… но даст ли это прирост производительности — не понятно.

У меня в Chrome крайней версии от 1.7 до 2 колеблется отношении времени теста 3 к тесту 2.
В этом нет ничего удивительного и неожиданного- такие результаты будут практически в любом языке, который не компилирует код или не имеет JIT-компиляции.
Конечно, все зависит от конкретных примеров регулярных выражений, но скорее всего большинство их будет быстрее их "чистой" реализации ввиду того, что обработка строки регулярным выражением в таких языках — всего один вызов нативной функции, который быстрее множества инструкций байт-кода.

Специально вывел коэффициент (чтобы вручную не считать) — разброс получается достаточно значимый (в абсолютных цифрах тоже), при этом от чего зависит — понимания нет.
Версия хрома — 51.0.2704.63 m
Попробовал в ФФ (45.0.1) — коэффициент болтается около единицы. При сравнимом времени работы теста 1 и меньшем времени работы теста 2

Test started
test 1 4411
test 2 2513
test 3 2524
test 3 to test 1: 0.5722058490138291
test 3 to test 2: 1.0043772383605252
Test started
test 1 4394
test 2 2545
test 3 2420
test 3 to test 1: 0.5507510241238052
test 3 to test 2: 0.9508840864440079

Посмотрите этот тест: https://jsfiddle.net/4x5v6yk7/4/
Решил исключить возможность кэширования регулярных выражений (ведь все-таки к одной строке всегда применяли) и получил интересный результат- теперь даже в FF 47.0 тест 2 в 1,5 раза быстрее теста 3, в хроме в 2,5 раза
Чем больше длина строки тем сильнее регулярные выражения будут обгонять "чистую" реализацию
https://jsfiddle.net/4x5v6yk7/5/
Еще один плюс в пользу регулярных выражений.

http://ideone.com/Yo5iDE
Добавляем поддержку русского алфавита и забываем про то, что NodeJS обгонял по скорости регулярное выражение.


Test started
test 1 649
test 2 584
test 3 1237
Так вы ведь собираете новую строку. Конечно, вырезать лишние символы лучше регекспом. А вот пройтись с двух сторон и вернуть false, когда встретится с неравенством — уже будет быстрее без регулярки.
Пример. Тут регулярка просто не нужна:

function isValidChar ( str, index ) {
  c = str.charCodeAt( index );
  return ( c > 47 && c < 58 ) || ( c > 64 && c < 91 ) || ( c > 96 && c < 123 );
};

function isPalindrome (str) {
  var left = -1, right = str.length;
  
  str = str.toLowerCase();

  while (true) {
    right--;
    left++;

    // search next valid char from the right
    while (right > left && !isValidChar(str, right)) {
      right--;
    }

    // search next valid char from the left
    while (right > left && !isValidChar(str, left)) {
      left++;
    }
    
    if (str[left] != str[right]) {
      return false
    }

    
    if (left > right) {
      break;
    }
  }

  return true;
}
Вот сколько раз был в критических ситуациях, когда надо было быстро решать проблему, и вот ни разу не пригодилась доска и не стоял какой то чувак за спиной. Такие собеседования нужны только для удовлетворения собеседующих.
В каких коммандах вы работали? Или даже так: вы проблемы один решали или вместе с коммандой?
UFO just landed and posted this here
Тут комментарии, ради комментариев, хорошо что не началось с «сейчас я начинаю писать код».
Я видел много индуского кода в котором коментарии используются так же, читать его просто ад!

// make sure we have a string.
if (typeof stringToTest !== «string») {
// throw if we didn't get a string
throw new TypeError(«isPalindrome() expected a string, but got » +
Object.prototype.toString.call(stringToTest) + " instead!");
}
UFO just landed and posted this here
Вот в очередной раз убеждаюсь, что здесь нет правильного или универсального подхода. Например, насчет задачи на доске: у меня в работе были такие ситуации, когда срочно, с давлением, коллеги вокруг, но волнения не было. А на собеседовании не соображаю. Наверное, потому что в рабочем коллективе все в одной лодке, и у меня не стоит задача доказать всем вокруг свою незаменимость, нужно просто решить проблему. Ну и со знакомыми людьми всегда проще.
А вы попробуйте переключиться и представить, что люди вокруг вас — это ваши коллеги (если вас возьмут так и будет). И дальше решайте вопрос как с коллегами. В конце концов если они адекватные, то цель у них понять — могут они с вами работать или нет, а если не адекватные — то уж нервничать из-за них не стоит совершенно точно.
Как-нибудь попробую такой трюк, пока что я представляю интервьюеров без одежды и это не помогает
Может быть дело в том, что вы их без одежды представляете.
я представляю интервьюеров без одежды

Господи, зачем я это представил? Как мне с этим кошмаром теперь жить?

Вот пример хорошего кода
уточнить — пример «не очень» хорошего кода.
1. Комментарии мусорные, например этот // make sure we have a string.
2. У метода слишком много ответственности. Он и за входные данные отвечает и строку фильтрует и палиндром вычисляет.
2а. Я наоборот падавана отучал в каждом методе проверять раз за разом одни и те же входные данные. Если прям хочется поставить проверку или функция «библиотечная» (тоже кстати допущение), то проверку надо вынести в отдельный метод.
2б Как и остальные две ответственности.
Таким образом основной метод должен выглядеть вот так:
function isPalindrome(stringToTest) {
    ensureInputIsString(stringToTest);
    var filtered = filterInput(stringToTest);
    return isPalindromeInternal(filtered);
}

ensure в данном случае — naming convention для методов, которые делают if{throw}

3. Раз уж требования к производительности не предъявляются, судя по тому что решение с регексом считается «хорошим», то isPalindromeInternal пишется в одну строку, не считая проверки на пустую строчку, конечно.
return input === reverseString(input);
reverseString в проекте, работающем со строками, скорее всего уже должен быть.

4. Автор пишет о том, что не должно быть повторяющихся тестов, но в примере несколько повторов, вот эти два например как с точки зрения ТЗ, так и с точки зрения реализации тестируют одно и то же.
console.log(isPalindrome(" ") + " = true + warn");
console.log(isPalindrome("~~!~!~") + " = true + warn");

5. Мелкие замечания
а. не стоило объявлять переменные до мусорного(нефункционального) кода, тем более с инициализацией, ведь при чтении такого захочется поскролить туда-сюда, а этого можно избежать.
б. else после if{return} режет глаз
в. я слишком придирчив

isPalindromeInternal пишется в одну строку, не считая проверки на пустую строчку, конечно. return input === reverseString(input);

reverseString("No 'x' in Nixon!") = "!noxiN ni 'x' oN". Намёк понятен?

var filtered = filterInput(stringToTest);
  1. Это уже две строки, а не одна.
  2. Создание новой (очищенной) строки = выделение дополнительной памяти под неё (а если строка в 32 Мб размером?) = замедление работы, а нас просили код сделать оптимальным насколько возможно.
Таким образом основной метод должен выглядеть вот так:
isPalindromeInternal пишется в одну строку
Так-то строк даже больше чем 2.
А про память, так там reverseString тоже выделяет память под всю строку. И что? Это оптимально насколько возможно для тестового задания.
Не очень. filterInput подразумевает очистку от всех незначащих символов.
function isPalindrome(stringToTest) {
ensureInputIsString(stringToTest);
var filtered = filterInput(stringToTest);
return isPalindromeInternal(filtered);
}
Как же тяжело, наверное, быть веб-разработчиком. Уже на собеседовании заставляют писать код, как для продакшена… с комментариями и тестами. Даже страшно представить, что приходится делать, когда начинается настоящая работа…
А потом на настоящей работе приходится говнокодить в древнем легаси без комментариев и тестов
Прикольно. Получается, что собеседование — это как мальчишник перед свадьбой. Последняя возможность почувствовать себя человеком…
Хотя мне не нужен программист, который пишет красивый код на доске, но мне нужен тот, кто способен быстро думать на ходу, под давлением, в одной комнате с другими.

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

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

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

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

>кто способен быстро думать на ходу, под давлением,

Под давлением это как? Чем на меня можно надавить? Угрозой увольнения? Так я могу легко найти работу взамен. Разве что крик раздражает, ибо работает в обход сознания на эмоциональном уровне — тут хочется в ответ наорать.

>… в одной комнате с другими.

Как будто другие люди — это что-то страшное. Прямо вспоминаются всякие анекдоты про интровертов.
Спасибо за статью. А нельзя список выложить в нормальном кликабельном виде где-то?
Огромное спасибо!
function isPalindrome(stringToTest) из примера — жесть. В питоне решается одной строчкой return stringToTest == stringToTest[::-1]
И такое?
isPalindrome("race car")
Нет, только не такое. На первый взгляд, это «джуниорский» баг, косяк и вакханалия.
И я хочу об этом поговорить (с)

Есть два варианта:
1. следовать Single responsibility principle имени Мартина (увы, его понимание у всех разное до сих пор) и возложить обязанность проверки и нормализации строки на вызывающего. Граничных случаев может быть много. Пробелы, в т.ч. два пробела подряд, знаки препинания в конце, и прочее и прочее.

2. до неприличия упороться в спорах о допущениях «что такое палиндром» и сделать функцию очень-очень умной. А потом всё равно много раз дорабатывать, потому что предположить всё невозможно. Функция из примера, допустим, уверенно считает палиндромом всякий трэш, но не считает палиндромом вот это:

console.log(isPalindrome("Аргентина манит негра"));

No valid characters to test, treated as empty string
Stack: 
Error
    at isPalindrome (<anonymous>:26:29)
    at <anonymous>:46:13


… а чтобы понять, почему, нужно просмотреть чуть больше, чем одну строчку кода, чтобы найти причину:

    // normalize string by lowercasing and removing non-word characters
    stringToTest = stringToTest
        .toLowerCase()
        .replace(/[^a-z0–9]/ig, '');


А в будущем, в мифическом продакшене, который нагревает воздух, переворачивая палиндромы, эта функция может расрастись проверками и логированием раз в десять. Не нужно давать этому повод, я считаю :)
В JavaScript она тоже решается одной строчкой:
function isPalindrome(str) {return str.split('').reverse().join('') == str;}

Но почему то мне кажется, что с таким кодом не пройду я собеседование…
Я имел в виду, что тогда уж лучше так:

function isPalindrome(str) {let s = str.toLowerCase().replace(/\W/g, ''); return s.split('').reverse().join('') == s;}
Кстати, для таких тестов есть console.assert
Комментарии в коде на собеседовании? Серьёзно?
Если тебе нужно быстро решить задачу, то ты будешь её решать в режиме «прототип». А потом усложнять функциональность.
То, что программист не уточняет некоторые детали на собеседовании, ничего не говорит о его компетенции, потому что это может обозначать как низкую квалификацию, так и высокую. Если вы хотие посмотерть, какие именно он будет задавать вопросы, то такое задание ему и давайте.
ИМХО, это отличный пример, как *не* надо проводить технические собеседования.
На 7 строк кода, который, собственно, решает задачу, еще 20 разных оберток и проверок. За то же время, какое ушло бы на это интервью, лучше задать еще 3 вопроса, но попросить написать именно «мясо», а не «а не пустая ли строка?», «а не стреляем мы в ногу?».
Разумеется, все проверки понадобятся в боевом коде, но тут жеж вопрос приоритетов, правильно? Человек нанимается не для того, чтобы работать компилятором или набором тестов — то, что можно автоматизировать, должно быть автоматизировано.
Коментарии? Тесты? Вы серьезно? Проблема коментариев решается на этапе code review, покрытие тестами должно вычисляться автоматически.
Не говоря уже о том, что вопрос уровня телефонного интервью.
В общем, такое ощущение, что нанимается дрессированная обезьянка, а не инженер, чья основная задача — решать проблемы.
>Пожалуй, самое важное для успешного собеседования по программированию — хорошая подготовка. Лучше всего практиковаться со стандартными вопросами снова и снова, пока вы не выучите их назубок.

Самое важное для успешного собеседования по программированию:
1. Вовремя распознать на интервью куда вы попали. Туда где вы будете работать или распозновать полиндромы. Если человек не прошерстил ваш профиль в linkedin, не задавал подробных вопросов, что делали на прошлых работах, и если из вышесказанного интервьюер не понимает, насколько вы компетентны, а продолжает вас звать к доске решать полиндромы — бегите оттуда со всех ног.
2. Покинуть страну, где в 90% компаний верстают сайты, аутсорсят на запад за гроши, и при этом требуют знания профессора математики, а платят копейки, заставляют стоять у доски в 8 часов вечера ибо дедлайн «аутсорса за гроши». В общем покиньте Африку и переезжайте к белым людям. В ту же Чехию из статьи выше.
2.
Мммгм. Если компания нанимает человека на конкретный проект — может быть и да.
А если у компании X открытых позиций без ограничения времени, и поток кандидатов хотя бы больше 10 в день? Прошестить профили затруднительно, а спрашивать кандидата о прошедшем опыте, бывает, не имеет смысла.
Был случай, когда брали человека чтоб писать Джаву, так его 10+ лет опыта был совсем в другой области, и работал он совсем не с тем.
Не говоря уже о том, что если имеется хорошо подвешеный язык, то прикрываясь NDA и «самописный фреймворк», кандидат имеет возможность пудрить мозг.

Задача интервью — проверить, соображает ли человек и способен ли программировать. Всему остальному можно (и как правило нужно) учить, потому как ни одна работа на другую не похожа.
>Когда я предлагаю такую задачу на собеседовании, первым делом я смотрю, зададите вы мне дополнительные вопросы или нет

Да, единственный — *сколько вы мне заплатите за потраченное время на эту %хотелку%? Я пришел не благотворительностью и доказыванием чего-то заниматься*

Адекватные или хихикают и все понимают(или довольно часто предлагают $, но только не в СНГ :) ) или *вы нам не подходите*
Особо одаренные умудряются пытаться спорить давя на *ЭТОЖЕ СОБЕСЕДОВАНИЕ!!111ё*

Вообще, кстати, заметил странную особенность: таким очень любят страдать именно стартапы, причем чем хипстерее моднее и прорывнее тем более дебильнейшие задания
Напишите самую эффективную функцию, какую сможете найти, чтобы определить, является ли данная строка палиндромом.
boolean isPalindrome(String s) {
for (int i = 0, j = s.length() — 1; i
Заголовок звучит:… Несколько крайне полезных советов для разработчиков.
Извиняюсь, но мне показалось, что советы совсем не полезные, они узко специализированы (субъективны, заточены на авторе), и что у другого собеседующего могут прозвучать совсем иной субъективной направленности вопросы.
Вообще-то пример не оптимальный данные в цикле проверяются два раза, лучше так:

var checkLength = Math.floor(stringToTest.length / 2);
for ( var i = 0; i < checkLength; i++) {
if ( stringToTest[i] !== stringToTest[checkLength — 1] ) {
return false;
}
}

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

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

Такой кусок кода снабжен излишним комментарием, который никакой пользы в себе не несет:
// make sure we have a string.
if (typeof stringToTest !== «string») {

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

Тоже очень спорно. Про скорость уже сказали, скажу про удобство. Регулярные выражения очень удобны, если вам через полгода не нужно будет вносить какие-то изменения в огромную регулярку, которая выглядит как арабская вязь.

Но это, конечно, мое субъективное мнение.
Sign up to leave a comment.