html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Что можно узнать о кандидате по тестовому заданию

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

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

Предлагаю вашему вниманию тестовое задание, которое я уже довольно давно даю кандидатам в компании, где я работаю:

На экране есть сетка M на N из цветных квадратиков. Нужно реализовать на этой сетке следующий эффект — по клику слева на право со скоростью V пробегает волна, меняя цвет квадратиков на другой (единый для всей волны). Эффект должен работать при любых значениях M, N, V. Волна начинается всегда у левой стенки. Одновременно может идти несколько волн разного цвета.
Анимационный пример: http://dl.dropbox.com/u/3601116/wave.swf (покликать по флэшке).


Я не сомневаюсь, что это задание с легкостью сделают все программисты посетители Хабра.

А у меня получилась следующая статистика:

  1. В итоге, задание взяли чуть больше 20 человек.
  2. Пара человек ничего не сделали.
  3. Половина из оставшихся (по моим критериям) с ним не справились.
  4. Кандидаты четко разделились на весьма интересные группы.

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

Disclaimer


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

Задание


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

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

Группы


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

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

Щаз все будет! Завтра сделаю!

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

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

Всё просто, надо сделать вот так и вот так

К своему удивлению, я наткнулся на людей, которые мне долго (и объёмно) объясняли, как нужно делать это задание, как построить архитектуру, как оптимизировать отрисовку. Сыпались технические термины и на показ выставлялось знание win32 api. В конце концов, я не выдерживал и говорил прямо, мол, отлично, теперь идите и сделайте это задание.

И знаете что?.. У всех у них возникли с ним сложности.

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

Нам в универе преподавали С на втором курсе

На двери этой группы огромными желтыми буквами было написано IMPERATIVE. Как и полагается для решения задачи со второго курса университета, в коде фигурировала матрица, какое-то количество переменных с началами и концами волн, а также переменные i, j, k, m, n и другие в огромных количествах.

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

Так, i от нуля до точки распространения волны, j и k симметрично в обе стороны… а это граничное условие… так, а это что за m пошло теперь обратно до границы текущего цвета… так, а это вообще зачем и каким образом работает??! argh! fuck it!

Диалог с кандидатом затягивался на десяток писем, в котором каждое новое начиналось со слов «всё поправил, теперь работает». Почувствовал себя учителем информатики. Надо ли говорить, что до конца из этой группы проект так никто и не доделал. Вот тебе и Российское образование.

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

Add(new Wave());

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

При этом, тоже умудрялись проявлять чудеса ООП Головного Мозга. Но, все же, большинство с заданием справились.

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

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

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

Я все пишу с нуля

В задании специально не ставились рамки на использование языков, фреймворков и библиотек. Но люди из этой группы упорно выбирали непростой путь решения и сами писали для себя инфраструктуру (например, вывод на экран меша в 3d пространстве). В итоге с заданием справились все.

Вывод: На первый взгляд, кандидаты обладали достаточными знаниями, чтобы с нуля на любимом инструменте реализовать решение задачи и не запутаться в алгоритме. Но сразу же появилось подозрение в «Not Invented Here Mentality» и сомнения в том, что человек сможет эффективно использовать уже существующие наработки и сторонние библиотеки.

Я не ищу простых путей!

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

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

— Почему ты сделал это вот так? Ведь, можно было сделать гораздо проще.
— Зачем? Я же могу так!

Вывод: Стоит задуматься. Человек, скорее всего, специалист в своем деле и обладает обширными знаниями, но сможет ли он решать конкретные задачи быстро, не создавая под каждую фреймворк для решения подобных задач? Есть ли у вас фреймворк, за который его можно посадить?

Я все перерисовываю / я не все перерисовываю

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

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

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

Мне пофиг, как оно выглядит, если оно компилируется

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

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

Вывод: Очень важно, чтобы человек закрывал таск лишь в тот момент, когда уверен, что работа сделана. Передавая на проверку приложение с очевидным косяком (в надежде, что его не заметят?) он тратит не только своё время, но и время проверяющего. А товарищ, который знает как решить проблему, но не будет ее решать, потому что… — будет вести себя так же и на работе.

Мне пофиг как они будут это запускать

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

  • Использовались какие-то библиотеки, которые не понятно где быстро взять.
  • Нужно было ставить IDE, SDK и всё на свете, чтобы лишь скомпилировать апп.
  • У меня были явно не все файлы проекта, а с незнакомым языком возиться его настраивать было не много желания.

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

Да, я сам в начале статьи написал, что мне все равно на чем написан код, но все же стоит ценить моё время и приложить, например, скомпилированный файл, пару строк чем и как лучше открыть… отправлять цельные проекты, а не набор исходных файлов, в конце концов. Если конечно, ваша задача не написать все на Brainfuck и поиздеваться надо мной (как тут внизу предлагали). Но, вы должны понимать, что я могу такой ход не оценить.


Вывод: Тоже какое-то неприятное пофигистическое отношение к проверяющему. В итоге на дополнительную переписку была потрачена еще куча времени.

Резюме


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

  1. Какой у него опыт и в каких проектах.
  2. Насколько он абстрактно мыслит.
  3. Способен ли он реализовать простой алгоритм.
  4. Может ли он сам четко закрывать поставленные задачи.

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

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

Конечно, самым популярным был ООП подход с созданием экземпляров класса Wave, апдейтом его по таймеру и очисткой при достижении некоторого критерия. Но, при этом, люди разным образом подходили к распространению волны и перерисовке сетки.

Я рад, что некоторые исходники позволили мне самому чему-то научиться!

Решение


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

На самом деле, изначально его не было. Лишь к концу второго десятка «проверенных работ» я стал задумываться, а как бы я решил эту задачу… Интересной была одна особенность всех решений — все… абсолютно все смотрели на задачу, следуя буква к букве её описанию в начале поста: сетка, по ней пробегает волна…

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

Действительно, пусть клетка принимает целое положительное значение от 0 до бесконечности. Каждый тик клетка принимает максимальное значение своих четырех соседей. Не трудно увидеть, что устанавливая значение одной из левых граничных клеток в N+1 (где N — максимальное значение клеток на сетке), получится ровно нужный нам эффект распространения волны.

for (var i:uint = 1; i < Width-1; i++) {
	for (var j:uint = 1; j < Height-1; j++) {
		buffer.setPixel(i, j, Math.max(bmp.getPixel(i, j), bmp.getPixel(i-1, j), bmp.getPixel(i, j-1), bmp.getPixel(i, j+1)));
	}
}


Можно было бы так всё и оставить, но проще завести еще один массив с рандомными цветами. В итоге, весь код на флэше выглядит так (https://gist.github.com/valyard/6084814):

Посмотреть код
var Size:uint = 10;
var Width:uint = int(stage.stageWidth/Size);
var Height:uint = int(stage.stageHeight/Size);
 
var bmp:BitmapData = new BitmapData(Width, Height, false, 0x000000);
var buffer:BitmapData = new BitmapData(Width, Height, false, 0x000000);
var display:BitmapData = new BitmapData(Width*Size, Height*Size, false);
var zeroPoint:Point = new Point(0, 0);  
var colors:Array = [0xFFFFFF];
 
addChild(new Bitmap(display));
 
stage.addEventListener(MouseEvent.CLICK, clickHandler);
stage.addEventListener(Event.ENTER_FRAME, frameHandler);
 
function clickHandler(e:MouseEvent):void {
	addWave((e.localY % display.height)/Size);
}
 
function addWave(position:uint):void {
	if (position == 0) position = 1
	else if (position >= Height-1) position = Height-2;
	
	bmp.setPixel(1, position, colors.length);
	colors.push(0xFF000000 + int(Math.random()*0xFFFFFF));
}
 
function frameHandler(e:Event):void {
	for (var i:uint = 1; i < Width-1; i++) {
		for (var j:uint = 1; j < Height-1; j++) {
			buffer.setPixel(i, j, Math.max(bmp.getPixel(i, j), bmp.getPixel(i-1, j), bmp.getPixel(i, j-1), bmp.getPixel(i, j+1)));
		}
	}
	bmp.copyPixels(buffer, buffer.rect, zeroPoint);
	
	var rect:Rectangle = new Rectangle(0, 0, Size, Size);
	for (i = 0; i < Width; i++) {
		for (j = 0; j < Height; j++) {
			rect.x = i*Size;
			rect.y = j*Size;
			display.fillRect(rect, colors[bmp.getPixel(i,j)]);
		}
	}
}


Как видите, код минимальный и совсем простой. Но, ничего подобного никто мне так и не показал.

Эпилог


Все имена выдуманы, все совпадения случайны. Если вы когда-либо выполняли такое же тестовое задание, я об этом ничего не знаю, придумал его не я, и вообще, ничего не происходит… нечего тут смотреть… расходимся, господа!
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

3

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции