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

***

Я расскажу историю одного тестового задания. Немного длинную, но, надеюсь, интересную.

У нас в Ecwid все тестовые задания для инженеров выложены открыто на GitHub вот тут — github.com/Ecwid/new-job. Можно просто начать делать любую понравившуюся задачу, никого не предупреждая, а потом, когда сами будете довольны результатом, поделиться им со мной.

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

Качальщик нужно сделать действительно очень примитивный. Судите сами — ты ему список ссылок в текстовом файле, а он скачивает эти файлы и кладет в указанную папку на локальном диске. Должен уметь качать несколько файлов одновременно (в несколько потоков, например, 3 потока) и выдерживать указанное ограничение на скорость загрузки, например, 500 килобайт в секунду. Всё.

Для работы с HTTP не нужно ничего изобретать, можно взять любую библиотеку. Для ограничения скорости — библиотеку. Для загрузки в нескольких потоков даже библиотеку не надо — все есть в стандартной библиотеке Java. Можно, конечно, все это изобрести и написать самостоятельно на коленке, но не обязательно. Фактически, надо взять несколько «кубиков» и аккуратно сложить их в правильную фигуру, применив немного программизма.

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

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

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

— Часть присланных работ просто не будет компилироваться. Да, работы будут на компилируемых языках Java/Kotlin, но компилироваться не будут. Локальная IT-разновидность корпускулярно-волнового дуализма, я так понимаю этот феномен. Я, конечно, немного знаком с языками на которых прошу сделать тестовое и безо всякой гордыни лично дописываю те куски, что кандидат имел в виду, но не написал, оставив мне возможность для творчества. Обычно это самые интересные работы. Приятно, что кандидат серьезно относится к будущему месту работы и не только дает возможность вам проверить его знания, но и, в свою очередь, проверяет ваши.

— Часть присланных работ будет выдерживать скорость скачки с очень широким разбросом от желаемого. Например, вы хотите скачивать со скоростью 300KB/s, а программа скачивает около 2MB/s. Разница всего в шесть раз, но зато строго 2 мегабайта в секунду и не больше. Как сказал один кандидат — «скорость выдерживается в некотором интервале туда-сюда». Мне очень понравилось и про «некоторый интервал» и про «туда-сюда». Теперь и сам стараюсь использовать этот оборот как можно чаще — «Мы сделаем эту фичу за двадцать дней, пять дней туда-сюда».

— Параллельная закачка. С одной стороны, я часто думаю убрать это требование, потому что по нему можно угадывать возраст кандидата, а я этого делать не люблю. Если вам приходит письмо с вопросом «В несколько потоков это как ReGet?», то ты сразу понимаешь, что кандидат вряд ли сильно моложе тебя и помнит времена модемов. Я вот тоже помню все эти бесконечные ReGet, FlashGet, Download Master и остальные милые сердцу интернет-приблуды конца девяностых-начала двухтысячных. Нет, качать надо не один файл в несколько потоков, а тупо несколько файлов одновременно.

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

* Например, я хочу качать в 3 потока, а программа качает в 4. Я задаю 5 потоков — программа качает в 6. WTF? Как тут можно сделать баг? Иду в исходники и нахожу комментарий «Увеличим запрошенное пользователем количество потоков на один, чтобы качалось ещё быстрее». Хрен поспоришь.

* Другой пример — кандидат пишет «Программа умеет скачивать файлы в N потоков, однако случаи N больше одного пока не поддерживаются». Фраза прекрасна вся до последней точки. Читая утирал пот ушанкой, дивился человеческой ловкости, вспоминал анекдот про математика и камерный оркестр.

Бесконечное количество просто интересных решений от неординарных людей:

* Как вам, например, такое решение — задание просто выясняло файлы какого размера с какой скоростью надо скачать, делило размер на скорость и засыпало на полученное количество секунд. Я даже, где-то глубоко в душе, нахожу это решение логичным — программа должна работать NN секунд, она и работает, что вы докопались?! Видимо, кандидат не ожидал, что проверяющий просто возьмет и посмотрит (какое коварство!), что же программа по факту накачала. Очень хитрое решение, очень.

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

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

* Помню прекрасного человека, который написал, что скачивание файлов по HTTP это совершенно простое задание и можно ли ему его не делать? Я ответил в том духе, что, конечно, можно не делать и мы расстались друзьями. Больше я его не слышал и не видел. Человек просто спросил меня письмом, можно ли ему чего-то не делать, я, со своей стороны, не нашел в себе сил запретить ему этого. Всё. Надеюсь, мой ответ помог человеку достичь нирваны и он ничего не делает до сих пор.

* Замечательный кандидат, сказавший, что Java он не знает и можно ли сделать задание на Go? Я сказал в том смысле что «хрен с ним, давайте на Go», на что получил ответ — «отлично, Go я тоже не знаю, вот выучу и сделаю»! Скажу честно — я горжусь знакомством (пусть и шапочным) с таким упорным человеком.

Самый интересный случай произошел со мной в Пензе (SECON, привет!) ночью на улице после after-party. Ночь, улица, людей почти нет, я стою и жду такси, чтобы уехать в гостиницу. Внезапно откуда-то из темноты ко мне подходит человек и говорит: «Василий, я пытался устроиться в Ecwid, вы мне отказали и с тех пор я очень хочу с вами встретиться лично!!».

Затрудняюсь пересказать, какие мысли пронеслись у меня в голове за эти секунды. Чувак, если ты читаешь эти строки — спасибо за опыт, ко мне никто ещё не подбегал в ночи с такими двусмысленными формулировками.

Я, собственно, хотел сказать этой несерьезной историей две серьезные вещи:

1) Уважаемые кандидаты. Вас губит нежелание выбросить сделанную работу и начать сначала. Например, вы начали делать задание, а в конце вдруг выяснили, что забыли прикрутить многопоточность. Вы в панике начинаете вставлять concurrency-костыли в ваш код, не предназначенный для этого. Не надо так делать. Самый правильный способ — выбросить все написанное и написать с нуля с учетом пропущенных требований. Серьезно. Это не production-код, здесь не место костылям.

2) Могло сложиться впечатление, что я как-то несерьезно отношусь к кандидатам и их тестовым заданиям. Это совершенно не так. Я с огромным любопытством и удовольствием проверяю каждую присланную работу. Практически каждое просмотренное задание дает новый опыт, я узнаю что-то, чего не знал раньше. Делайте тестовые таски больше, делайте чаще и присылайте мне.

Ecwid всегда в поиске разработчиков. Прямо сейчас тоже. У нас большой НЕ-legacy проект, географически распределенные кластера, серьезные нагрузки, умная команда и высокая ответственность. В общем, непросто, но интересно. Основной стек — Java/Kotlin, но так же очень нужны специалисты по ReactNative.

Ищем разработчиков практически любого уровня от junior и выше (Ульяновск, Самара). Не надо стесняться, не надо думать «подойду ли я?», надо просто делать тестовое задание или если хочется, сначала поговорить со мной, а уже потом делать тестовое. А может делать тестовое и не придется, это смотря как поговорить.

Наш стек в виде непонятных слов и аббревиатур — Java, Kotlin, PostgreSQL, Cassandra, Redis, AWS, Consul, Docker, microservices. Ну и еще полно всякого.

По всем вопросам пишите в комментариях или на join@ecwid.com
Поделиться с друзьями
-->

Комментарии (53)


  1. impwx
    14.11.2016 15:32
    +50

    Программа умеет скачивать файлы в N потоков, однако случаи N больше одного пока не поддерживаются

    Жму руку неизвестному гению!


    1. car-a-pooh
      15.11.2016 14:14
      +3

      Это же Генри Форд.


      1. ingumsky
        15.11.2016 18:36

        У нас есть на выбор автомобили любого цвета, если этот цвет – чёрный?


  1. Nizametdinov
    14.11.2016 15:43
    +4

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


  1. tangro
    14.11.2016 15:54
    +38

    Это не production-код, здесь не место костылям

    Пф-ф-ф-ф. Зачем же Вам люди, которые не умеют писать production-код?


    1. Flammar
      15.11.2016 14:06

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


      1. tangro
        15.11.2016 20:11
        +6

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


    1. MurzikFreeman
      15.11.2016 14:14

      Но костылизация же происходит по мере изменения ТЗ в процессе разработки без пересмотра сроков, а тут требования не менялись. Зачем просто код превращать в production-код, сразу? )


  1. ApeCoder
    14.11.2016 16:09
    +4

    Самый правильный способ — выбросить все написанное и написать с нуля с учетом пропущенных требований.

    А вот интересненько, неужели такая большая разница, что нельзя добиться своего рефакторингом + изменениями в нужных местах?


    1. knotri
      15.11.2016 14:14

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


      Так вот, к чему я все это. Тут рефакторинг 100% невозможен.


      1. ApeCoder
        16.11.2016 07:39

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


        И еще рефакторинг тоже надо уметь


    1. Hvorovk
      15.11.2016 14:14

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


  1. AzureSeraphim
    14.11.2016 16:48
    -1

    Раз такая пьянка пошла хочу спросить, никто не встречал качальщиков которые с ютуба звуковые дорожки могут качать с очередью? С сайтов качать каждый линк по отдельности долгое и не приятное дело.
    Желательно так что стандартный ютюб HTTP линк(стопкой) и качает в mp3 формате.


    1. miv89
      14.11.2016 17:02
      +6

      Так выдавайте такое тестовое задания для кандидатов.


      1. edogs
        15.11.2016 00:11
        +8

        Типичненько:)
        Ньюфаг:- Мне надо перевести книгу, как бы это сделать подешевле?
        Олдфаг:- Повесь объяву о найме переводчиков, выдай каждому тестовое задание по 10 страниц, профит.


    1. Kondra007
      14.11.2016 17:02
      +1

      Не претендую на правильный ответ, но посмотрите документацию youtube-dl. Программа (ладно, скрипт) точно умеет качать отдельно аудио по ссылкам и точно позволяет создавать очередь, читая из файла.


    1. Shtucer
      14.11.2016 17:17
      +3

      1. dals
        14.11.2016 19:33

        youtube-dl скачать-то скачает, даже с выбором битрейта.
        Но для конвертации в mp3 необходимо поставить ffmpeg с подключением lame


        1. ArisChik
          14.11.2016 20:30
          +2

          Все это настраивается буквально за минут 10.

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


        1. Shtucer
          15.11.2016 11:24

          Да, он скачает что есть, а не то что хочется. Потому что далеко не факт, что звуковая дорожка там в mp3. Поэтому конвертировать придётся любым удобным способом. Ну или продолжать искать программу skacahat-youtube-v-mp3-bez-sms.


          1. AzureSeraphim
            15.11.2016 12:26

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


            1. Shtucer
              15.11.2016 12:32

              youtube-dl не сайт, а программа. Среди прочих возможностей, к ней прилагается такой ключик


              -a, --batch-file FILE File containing URLs to download ('-' for stdin)


    1. rombell
      15.11.2016 14:14

      Поскольку я много слушаю всяких бесед с ютуба, то использую немного другую последовательность: скачиваю Download Master'om от Westbyte, он, кстати, поддерживает плэйлисты и скачивание прямо звука, но звук я ему не доверяю, а использую Pazera Free Audio Extractor, выдирающий списком.
      Как последний шаг, делю получившиеся звуковые файлы на 3-5 минутные куски с помощью mp3splt для упрощения навигации


    1. grieverrr
      15.11.2016 15:06

      youtube-dl же, нет? пардоньте


    1. detouched
      16.11.2016 05:04

      Если хочется с UI, то у Media Human есть неплохой клиент.


  1. ifaustrue
    14.11.2016 17:15
    +15

    Это не production-код, здесь не место костылям.

    Унёс в мемориз =)


  1. n-name
    14.11.2016 19:36

    Спасибо, улыбнуло :-)


  1. Merkat0r
    14.11.2016 19:37

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

    IMHO это был сарказм — типа *вы издеваетесь?*
    было бы весьма клево если бы еще было подписано на какую вакансию эти задания и, если, такое дали сеньору — то я, от части, даже его понимаю


    1. bogolt
      15.11.2016 09:07
      +5

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


    1. avost
      15.11.2016 13:53

      Просто интересно — а какого рода тестовых заданий вы ожидаете увидеть для серьоров?


      1. Merkat0r
        15.11.2016 14:12

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


    1. oddiz
      15.11.2016 14:15

      Это тестовые задания вот на эту вакансию.


    1. vgv
      15.11.2016 14:26
      +3

      Я никогда не прошу сделать что-то конкретное.

      Мы поэтому и выложили задания на GitHub чтобы человек мог выбрать что ему больше нравится. Нравится ему делать консольный качальщик — ну прекрасно. Если пресловутый senior сам выбрал качальщик и сам отказался его делать — я даже не знаю что сказать :)

      Более того, задание можно вообще не делать и так часто бывает. Человек просто приходит, мы с ним разговариваем и я понимаю что нет смысла давать ему задание, а надо сразу предлагать работу :)


      1. Merkat0r
        15.11.2016 14:28

        Ааа, вот теперь все прояснилось и стало на свои места :) Тогда действительно весьма забавный случай :)


  1. mgremlin
    14.11.2016 19:45
    +6

    Вариант «заснуть на n секунд» — лучший!!!
    Прямо даже завидую, что это не я придумал 8-)


  1. olen
    14.11.2016 22:20

    А какой примерно процент подобных решений по отношению к правильно выполненным?


    1. vgv
      15.11.2016 14:15

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

      Оставшаяся половина делится примерно так:

      • 40% — работает с недочетами «средней» тяжести
      • 10% — работает очень хорошо


  1. Saffron
    15.11.2016 03:04

    Первой мыслью было spark/hadoop/amazon lambda. Нулевой, конечно, libcurl


  1. NightmareZ
    15.11.2016 04:53

    Удалёнки, я так понимаю, у вас нет? Велком ту Самара?


    1. HelloLina
      15.11.2016 14:17

      Скорее, вэлком ту Ульяновск! =)


      1. NightmareZ
        15.11.2016 14:28
        -4

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

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


        1. HelloLina
          15.11.2016 16:50
          +8

          Не мигрируйте.


  1. Lamaster
    15.11.2016 07:41
    +2

    Интересно, а решения, которое таскает с собой wget/curl и вызывает его с ключами не встречалось?


    1. bogolt
      15.11.2016 09:07

      Думаю если кто так делал, то их сразу на должность админов приглашали =)


    1. random1st
      15.11.2016 09:35

      У меня был знакомый, который распаковщик так писал, запуская WinRar из своего кода


    1. vgv
      15.11.2016 14:18
      +3

      Нет, такие не встречались.

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

      P.S. Я изначальный автор этого текста и тот, кто проверяет эти тестовые :)


  1. TimsTims
    15.11.2016 11:25

    > * А вот ещё, видимо, очень неглупый человек, который прислал один класс с пустой main-функцией (и больше ничего) и пояснил «Вот как-то в таком стиле я планирую делать это задание. Надеюсь, моя мысль уже ясна?».
    Может там был код в стиле brainfuck с невидимыми utf-символами: пробелы, табуляция итп?)


    1. random1st
      15.11.2016 14:04

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


  1. KotV4
    15.11.2016 14:15

    Могу на C# шатальщик написать.
    Возьмете на удаленку?


  1. DanXai
    15.11.2016 14:56

    Раз такая пьянка идет — никто не подскажет, как закачивать файлы с сайта госзакупок? Сижу и мучаюсь, выбираю каждый по одному. Мало того, более 10-ти потоков скачивания не запускается, приходится ждать. Натравливал на сайт все известные качалки — они не видят ссылок на скачивание.


  1. NeXTs_od
    15.11.2016 21:10

    Здорово написано! С юмором :)


  1. NightSilf
    23.11.2016 02:03
    +1

    Скажите пожалуйста, какой оптимальный способ ограничения скорости скачивания? Просто пауза?


    1. kolipass
      23.11.2016 10:01

      А вариант в лоб: читаем в цикле n байт, пока поток не кончится, но на каждой итерации задерживаемся под заданную скорость, которая рассчитывается как отношение n r затраченному на итерацию времени?