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

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

Проблемы в сфере IT — они ведь такие же как и во всех остальных) Иногда достаточно одеть купальник, работая врачом — и ты уже модель :) А иногда врач-профессионал со стажем за копейки будет сидеть и горбатится до конца жизни… пытаясь научить молодых специалистов, как делать операции (а им может это и не надо — а надо стать моделями).

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

Кто его знает, чем они руководствовались. Может теперь сядут и будут внимательно изучать ваш код и перенимать ваш опыт. Может рынок исследуют. Может у фронтэндера жена в это время рожает… а ему там ваш код дали;)

Вообще, мой совет — не заморачиваться на этот счёт. Выше нос!
гораздо сложнее, чем могло бы быть

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

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

Может имело смысл рассмотреть уже существующие на рынке решения, подобные этому варианту Game: Axiom Development Kit (были и статьи по этому решению на Хабр) и уже дальше изобретать вариант своего «велосипеда»?
Спасибо за статью. По-моему тестовое задание более чем хорошее. Возникает резонный вопрос — стоит ли оно того, тратить столько времени на тестовое задание, подходя к нему ответственно и творчески? Чтобы потом какой то джун сказал что твой код «слишком сложный»
Считаю тестовые задания с оценкой кодстайла злом, так как чтобы соответствовать принятому в компании — нужно в ней работать. Не, конечно бывает говнокод, но и с другой стороны — стоит ли тратить драгоценное время на решение того, что не будет оплачено?
Золотые слова!
Я конечно совсем не ява программист, и не знаю, как у вас принято, но мне кажется странным назвать папки и файлы именами паттернов. controller, view, domain… Искать нужный класс, да и вообще разобраться в структуре программы в таком случае, имхо, довольно сложно
Обожаю комментарии «Я не %язык% программист, но дам-ка оценку, основываясь на том как принято в моем языке». Это все равно, что я посмотрю на C# и скажу «Фу, да вы переменные называете с большой буквы, имхо довольно сложно мне код понимать». Все нормально там со структурой и программист, пишущий с использованием Spring/Boot, сразу поймет в какой папке что лежит, по крайней мере, за 5 минут разберется. У меня на разных проектах по-разному обзывали эти папки внутри проекта, но суть и содержимое каждой папки было понятно через пару минут просмотра.
Почему бы и не поделиться хорошими практиками из других ЯП? Успешная коллаборация дала нам например лямбды в большинстве популярных языков программирования.

Заодно можно узнать особенности чужой платформы. Неужели Spring/Boot не допускает другой структуры проекта?
НЛО прилетело, и не знаю зачем, но оставило это здесь.
Я не знал, что мы тут советы по развитию ЯПов собираем.
Не советы по развитию ЯП, а советы по стилю кода
Да зачем? стиль кода закладывается при создании языка и не меняется на протяжении всей жизни этого языка. Потому что это помогает программистам, пришедшим с одного проекта на другой не тратить время на выяснение, как тут именуются перменные, классы, методы и т.д. Тут уж точно советы не нужны
Меняется. Посмотрите кодстайлы различных компаний. Да, в основном они боле-менее похожи, но в чем-то различия всеже есть (иначе не было бы всеэ этих кодстайлов).
Да, не нужно менять кодстайл каждый вторник, но что-то приятное или полезное со временем утянуть может быть стоило бы?
Собственные кодстайлы в различных компаниях, в основном сущетсвуют, потому что есть СиТиО или Лиды, которые прыгнули в ЯП из другого и/или тащут с собой багаж, либо «я умнее всех», и начинают выдумавыть что-то своё, тем самым оправдывая легаси, который написал этот же разраб, (1-2-3) годами ранее.

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

В, как минимум, JS/TS и PHP есть конкурирующие общеизвестные кодстайлы.

Благо ни разу не встречал проекты, где кодстайлы отличались хотя бы на 10% от предыдущих. Обычно хватало беглого ознакомления с документом по кодостайлу и забыть о нем навсегда. Да и был он не на всех проектах, тогда просто кодовой базы хватало. Я, честно, не знаю как в других языках, но что мне нравится в JVM языках — тут всё строго внутри комьюнити. И эти гайды по кодостайлу просто не нужны. Репозиторий из статьи тому подтверждение. Без всяких гайдов я открыл код и уже скомпилировал у себя в голове.
Во-первых, то что в одном языке — «хорошая практика», в другом языке не поймут. Я сам когда-то пришел в Java из С++ и называл переменные и методы через snake_case. Сейчас открываю свой первый код и кровь из глаз. Во-вторых, Spring/Boot конечно же позволяет задавать практически любую структуру, но зачем? Пришел один программист, создал флэт каталог и положил все файлы туда, пришел другой программист, начал строить безумные деревья из каталогов. К чему этот зоопарк, Я вот открыл проект и сразу понял что к чему. И в моем понимании — это вот «лучшая практика», а кто-то поспорит.

И не понимаю фразы «искать нужный класс». Навигация IDE мне помогает в 100% случаях поиска, если знать что искать.

И колаборация с чем/кем нам дала лямбды? Это не колаборация дала, а просто на волне хайпа разработчики языков добавляют то, что пошло в других языках, та же самая функциональщина например. Но симбиоз негибкого и устоявшегося ООП языка, на подобие джава, с функциональным стилем лично у меня оставляет некоторый осадок после использования. Я сам любитель функционального программирования, но в джава реализация мне не понравилась. То ли дело котлин/скала. Поэтому не нужна колаборация в том, что уже испытано и привычно, я считаю
> Я сам когда-то пришел в Java из С++ и называл переменные и методы через snake_case

А я наоборот, пришел из явы и называл (и до сих пор называю) в C++ переменные через camelCase (или как он там называется). Вот и пример удачной коллаборации.

> Это не колаборация дала, а просто на волне хайпа разработчики языков добавляют то, что пошло в других языках

Окей, почему бы не поднять хайп на более человечское именование сущностей?
более человечское именование

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

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

И в чем же моя лексика размыта и эмоционально заряжена?

Ну вот например Роберт Мартин в книге «чистая архитектура» говорит
> А что кричит архитектура вашего приложения? Увидев высокоуровневую структуру каталогов и пакетов с исходным кодом, услышите ли вы, как она кричит: «Это медицинская система», или «Это система учета», или «Это система управления складским хозяйством»? Или вы услышите: «Rails», или «Spring/Hibernate», или «ASP»?

Плюс неоднократно слышал похожие мысли по разным углам.
Соглашусь, открыл проект — как в свой попал. Все понятно и ясно.
нормально все. это не паттерны, это роли\зоны ответственности.
Это +- дефолтная структура проекта на джаве и Asp.NET (хотя я сам против такого разделения, но на небольших проектах оно себя хорошо показывает)
Спасибо за комментарии.

Мне показалось, что здесь — именно проблема некачественной обратной связи, в первую очередь. Было странно получать такой фидбек от подобной компании. Хотя, kinall, ваш комментарий заставил задуматься — А что если это часть поведенческого интервью? Но какой-то жёсткий стиль интервью получается :) Всё-таки черным по белому написали, что решили не продолжать, и я принял это за вердикт.

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

Вряд ли. Слишком круто) Вопрос про сложность я бы задал исключительно из любопытства, а переписать задание предложил бы только в том случае, если вакансия/компания очень уж «вкусная». Потому что, как тут уже не раз сказали, в целом ответ интервьюера не очень корректный.

Лично я призываю либо делать платное тестовое, либо получить фитбек в ходе очного собеседования: Холивар. Тестовые в разработке: нужны ли, какие и когда?. Кстати там дальше по ходу видео участники упоминают, что в некоторых HR методичках написано всеми силами не давать фитбек.

Если это еще и часть поведенческого интервью — я бы подумал 10 раз, хочу ли я работать в подобной компании. Неадекватное тестовое задание с неадекватным ревью — отдельная история
НЛО прилетело и опубликовало эту надпись здесь
Мне нравится вот этот текст:
Видимо задание сделано на тех технологиях, которые знал кандидат, хотя мы никакого redux и redux-saga

А ожидалось что видимо напишет на чём то неизвестном ему что ли? Такое чувство что человек не осилил код, с учетом потраченного времени кандидата это просто обычное хамство.
Видимо ожидали от вас что-то вроде такого github.com/intech/TicTacToe, а вы им кровавый энтерпрайз, испугали ихнего синьёра.

А есть архитектура на UML, а то для не Java программистов действительно трудно что то понять. Я бы взглянул, как вы смоделировали игру и тогда было бы ясно, просто это или сложно.

Посмотрел бегло ваш код, обе части: фронт и бэк, не нашёл никаких явных проблем. Вполне стандартный для индустрии набор архитектурных решений. Да, есть моменты из разряда «я бы тут сделал по другому», но ни одного «за такое по рукам нужно бить». В разных местах видно умение работать с различными техниками, типа streams в джаве, генераторы в js, понимание CI. Видно стремление делать правильно. Уж точно никакого оверинжиниринга.


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

или как минимум, сениоры боятся, что они нифига не сениоры…
Посмотрел код.
Ну явно лапша, дальше лезть не захотелось.
Ну вы хотя бы логику объясните вот этих кусков связанного кода:
```
this.threshold = Math.min(threshold, BOARD_DIMENSION);

this.threshold = threshold;

public void setThreshold(final int threshold) {
this.threshold = threshold;
}

public boolean isInRange(int x, int y) {
return x >= 0 && x < BOARD_DIMENSION && y >= 0 && y < BOARD_DIMENSION;
}
```

Вот как минимум за это это я бы Вас развернул.
Вы весьма резко зашли. Но я понял о чем Вы. Принимается. Для этого и нужны Code Review.
Да, сори.
Ответ конечно хамский, но я бы не сказал что в этом коде нет проблем, например:
github.com/itallix/noughts-crosses/tree/master/server/src/main/java/io/karniushin/tictactoe/core/service/handler/rule/condition
6 файлов, с иерархией классов и вложенными классами чтобы проверять условие Х в ряд, по моему это оверкилл, особенно что тестов я на это не нашёл (может искал не там, я не джавист).
Ещё например мне кажется что проверяется только ownerId, а значит можно ходить за других игроков.
Ой. Путь из полутора десятков вложенных папок сам по себе впечатляет (для тестового).
А разве в джаве бывает по другому?

Настоящих папок только пять (или шесть, как посмотреть): /core/service/handler/rule/condition

TLDR: Не парьтесь, Вы просто не поняли друг друга.

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

Еще не дойдя до финала статьи поймал себя на мысли:
«О господи, зачем так сложно».
Редакс с сагами для крестиков-ноликов это что-то похожее на шутки про java enterprise hello world" — несоответствие масштаба задач и масштаба применяемых инструментов.
Сами инструменты при этом нормальные.

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

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

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

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

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

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

Если кто-то вас в подобном начинает упрекать — говорите ему, пусть в ТЗ пишет нужную простоту, или нужную расширяемость в дальнейшем. Иначе можно быть всегда виноватым.
Все нормально написано, энтерпрайзненько так, по взрослому, но есть косяки с синхронизацией. Думаю потенциальный работодатель просто не осилил современный реакт. Я их за это не виню, современный реакт + redux это такое… на любителя почитать boilerplate. Но они не правы, что вас завернули, по коду видно, что с вами есть о чем поговорить.

public GameSession newGame(String username, String gameName, Integer threshold, boolean isX) {
        //тут гонка, два потока могут добавить игру с одинаковым именем
        validateGameName(gameName)
        //тут аналогичная проблема
        Player initiator = playerRegistry.registerPlayer(username);
...
        return session;
}

@Override
public GameSession connect(UUID gameId, String username) {
    //тут еще одна гонка, игру могли удалить уже после checkGameExists
    //в текущем варианте вроде такого быть не может, но как только появятся 
    //таймауты, то будет
    checkGameExists(gameId);
    ReentrantLock lock = locks.get(gameId);
    ...
}


TurnHandler + GameRule это попытка выдать желаемое за действительное. Судя по коду, есть идея, что «широкий класс игр можно моделировать в виде chain or responsibility». Эта неверное предположение ведет к слишком сложному коду, который не оправдан для такой простой игры как крестики-нолики. Становиться тяжело судить о том, верно ли вообще закодированы правила игры. Перепутай местами два Rule и все посыпется. Печаль в том, что более сложные игры в chain of responsibility не впишутся, в итоге вся эта сложность не нужна.
Думаю, вы точно ничего не потеряли.
Я бывал в вашей ситуации, когда делал тестовое задание для Revolut. Мне тоже отказали, и даже фидбека не дали, но знания и навыки, которые я получил, пригодились на собеседовании в Яндекс.Маркет.
P.S. Я в тестовых заданиях обычно использую незнакомые мне технологии, чтобы поковырять что-то новое. + оставляю много комментариев для потенциальных ревьюверов.
В общем-то, со многими вещами согласен, в условиях высокой конкуренции, отмеченные проблемы, действительно, могли сыграть ключевую роль. Вполне возможно, что это и был такой случай. Но отразить в фидбеке, конечно, было бы неплохо.

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

Всем спасибо за конструктивные фидбеки! Я не получил их в процессе интервью с этими ребятами, но, я получил их с Вами! А именно этого мне и хотелось после проделанной работы :)

Вы реально сложно написали. Ожидалось что-то сделанное просто. По заданию. А не энтерпрайзный монстр.
Да еще и набажили в единственном интересном месте бека. Стейт и мультипоточность. Точнее даже не набажили, а просто забыли про это почти везде. В проде будет взрываться красиво и внезапно.

Кусочек с локами выглядит как проба интересных для вас вещей, а не что-то нужное в этом месте. Там обычных syncronized(gameId) блоков с головой хватает.

Пиши только тот код который нужен сейчас (с) Гугл
Повезло, пару раз у меня даже мельком смотреть не стали.
Ну, очередной Enterprise FizzBuzz.

Касательно конкретно фронта — сложно всерьез воспринимать человека, который говорит, что redux+saga — это взросло, энтерпрайзненько, и поддерживаемо. Вообще, если человек применял редакс на больших проектах и при этом не плюется на редакс — что-то с ним не так. Самое безобидное — не применял в жизни ничего кроме редакса.

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

PS: А еще попробуйте погонять сагу на ИЕ11. Узнаете много чудного.
PPS: А еще я бы очень сильно не доверял человеку, который на тестовое задание пишет монструозный enterprise-grade код, но который при этом не взял на фронт typescript. Это то ли мазохизм, то ли просто ненависть к себе. Даже не смотря на то, что из-за саги там ни о каких серьезных статических гарантиях типов в бизнес-логике говорить будет нельзя (зато в остальных местах всё-таки что-то будет).
Как писать enterprise, чтобы всем было хорошо и удобно — это уже, наверное, отдельная и интересная тема для разговора. Конкретно, в данном случае, enterprise подход был выбран намеренно и есть понимание, что зря :) Про TypeScript я с вами согласен. Что касается, redux и saga — вероятно, вы правы и даёте хороший повод задуматься, а зачем оно вообще надо? И, вероятно, это уже следующая ступень осмысления. В наших проектах это живет, и все пока счастливы.
заоверрайжены

Любопытства ради — из какого языка это слово?

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

Ынтырпрайзненько...


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

Один метод с пачкой циклов читать было бы проще.

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

На техническом собесе было два тимлида разных проектов, они спросили о моем опыте, я рассказал. Других вопросов от них не последовало, только сразу высказали пожелание сделать тестовое. Я отказался со словами, что итак можно посмотреть мой гитхаб, я специально его обновил, сделал несколько маленьких проектов, где можно посмотреть мой стиль и сделать какие-то выводы, ведь и тестовое будет примерно в похожем духе. Они обещали посмотреть, а я обещал все же посмотреть их тестовое, которое они мне пришлют. На том и разошлись, все интарвью заняло минут 10, где 3/4 времени я рассказывал о себе, блестящая скорость оценки кандидатов у них.

После собеседования посмотрел на тестовое задание. Оно мне пришлось по душе, короткое и интересное, не должно занять более 4 часов. Надо было сделать простой клон Redis c get/set данных через очередь. Нужно реализовать «Storage и Log persistence». Я это понял как сохранение в storage файл каждые n секунд и запись какого-то лога запросов, который при падении процесса может потом применится к этому storage файлу при повторном запуске приложения, чтобы не потерялись никакие данные. По моему разумению примерно так работает Redis. Реализовал это дело на Typescript, на Node.js-фреймворке NestJS c RabbitMQ в качестве очереди, упаковав в Docker-контейнер. Короче, все стандартно. Потратил в районе 6 часов, как раз чуть больше запланированного. Можно потратить еще два раза по столько же, сделав полноценную документацию и тесты, но я остановился на минимально-достаточном варианте.

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

Тут можно посмотреть код, если кому интересно Даже если это недостойное внимания убожество и отвергли в ноунейм конторе, я все равно его не стыжусь =)

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

С другой стороны очень даже неплохо:
— задача довольно интересная и в меру быстрая, сильно я не пострадал по времени
— кода не стыжусь, убожество и другой мой код потом смотрели в других компаниях и работу я нашел успешно, выбирая из нескольких офферов
— любой опыт полезен, опять же =)
какой раз обещаю себе соглашаться только на оплаченное тестовое
Что машет сделать интересное тестовое в стол или гитхаб? Агитирую только за платные тестовые: https://youtu.be/sptmCVTCyzU. Отпишите и вы комментарием свою историю.
Писал ниже, но отвечу и здесь — вот что сами HR пишут о тестовых:

Если вы претендуете на опытных экспертов, постарайтесь обойтись без тестового (особенно при найме опытных кандидатов senior уровня). Мотивация делать тестовое есть только у junior или тех, кто мечтает о работе в вашей компании.

По этому, если вы не ждут (а по вашему github вы не джун) — лесом эти тестовые! Уважайте себя и свое время, и будут уважать вас.
Сталкивался с подобными заданиями — написать игру или сервис для игры, задания интересные, творческие, широкого профиля. Однако этот «широкий профиль» зачастую и подводит. Выполняя такие задания неясно какие аспекты будут оценены ревьюверами с предвзятой строгостью, а на какие посмотрят по диагонали. Ну правда, ведь тут может быть всё: выбор технологии, проектирование, алгоритмы, AI, паттерны, сети, потоки, кодстайл, UI, тесты, документация, а ещё — ограниченное время выполнения — согласно этому требованию разработчик самостоятельно выбирает наиболее важные части, которые ПО ЕГО МНЕНИЮ будут иметь значимый вес для ревьювера. Однако сложиться может иначе.
В этом плане выгоднее смотрятся задачи с явным акцентом на конкретный навык/навыки — реализовать алгоритм, написать сервис (без UI), — либо когда интервьювер явно указывает на второстепенность каких то аспектов.
Или я столкнулся с технической незрелостью интервьюеров?

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

Во первых, вот что говорят сами HR о тестовых:

Если вы претендуете на опытных экспертов, постарайтесь обойтись без тестового (особенно при найме опытных кандидатов senior уровня). Мотивация делать тестовое есть только у junior или тех, кто мечтает о работе в вашей компании.

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

Второй момент, о котором они прямо написали:

сложнее, чем могло бы быть

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

Как там говорят:

Не бросайте жемчуга перед свиньями

В текущем случае можно сказать: «Не бросайте жемчуга перед теми, кто его не ждет»

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


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


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

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

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

        players.values().stream()
            .filter(p -> p.getUsername().equalsIgnoreCase(name))
            .findAny()
            .ifPresent(p -> { throw new IllegalArgumentException(String.format(PLAYER_EXISTS, p.getUsername())); });

Это ужас. Ну и как правильно уже написали выше, использование класса ConcurrentHashMap не делает ваш код автоматически безопасным, есть проблемы с многозадачностью.
Билдеры смешанные с конструкторами, статические методы просто вызывающие конструктор, геттеры которые не делают ничего кроме разрушения инкапсуляции. Ну и конечно типичны случай константы которые меняются чуть чаще чем никогда
public static final String PLAYER_UNKNOWN = "UNKNOWN";

Мне кажется, научитесь сначала программировать на Java понятно и без ошибок, не лезьте в spring. Написать программу на spring сложнее чем на Java, потому что надо хорошо знать как работает spring в дополнение к тому как работает Java. Учите Java, не spring
1. Структура файлов на фронте довольно странная
import {gameConnect, gameStatus} from "../ducks/actions";
, и подобное

2. Css действительно хромает, формально он работает, но внося изменения легко что-то сломать,
position: absolute;
и
right: ...
не есть хорошо, выдаёт что опыта со стилями/вёрсткой нет.

3. Местами выглядит сложно, есть впечатление что код надёрган откуда-то, но и лапшой вроде не назвать.

Если UI работает шустро и хорошо (лень запускать), то можно простить некоторую переусложнённость из-за вебсокетов и асинхроньшины.
UI before API


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

Вижу много интересных комментариев. Кто-то даже советует учить Java (pin2t), что несомненно, всегда полезно. Безусловно, я не претендую на звание Java-гуру, и мне есть чему учиться. Я не ставил себе цели вылизать по максимуму этот код. Где-то поторопился, где-то что-то написал тяп-ляп с мыслями вернуться и забыл это сделать. Я действительно торопился :) Для этого и существует Code Review в нашей профессии.

Процесс обучения в нашем ремесле — процесс постоянный. А будучи фулстеком, надо успевать и тут и там — и это уже двойная работа. Но, работая в команде, я всегда могу расчитывать на поддержку коллег-профессионалов. Жонглировать 5 яблоками явно сложнее чем 3. Возможно, сделав ставку на 3 яблока, к тому же огненных — ваше шоу будет более эффектным и вы выиграете больше :). Очередной повод задуматься, может быть лучше сфокусироваться на чём-то одном? Всегда должно быть место для сомнений и переосмыслений.

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

В одном из комментариев (Undiabler) подметили, что в условиях недостаточного времени получается вот так брезгливо отвечать кандидатам и нет времени ничего объяснять. Мне кажется, что это очень плохо и не даёт возможности кандидатам делать правильные выводы, оставляя неприятное впечатление о компании. Мне кажется, что компаниям с достаточным бюджетом, к тому же претендующим на звание Developer Friendly, просто необходимо должным образом выстраивать процесс собеседования. Даже когда её имя уже работает на неё. Этот культурный аспект очень важен и не принесёт большого финансового ущерба самой компании, но при этом сделает жизнь соискателя проще и увеличит степень уважения к имени компании.

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


Во-вторых, именно поэтому я не люблю тестовые задания. И не выполняю их (исключение — если задание мне понравилось и я его делаю "для себя", не ставя трудоустройство как основную цель)
Выдача объемных заданий на дом — это неуважение к времени кандидата. И, если компания — не условный "Гугл", может не стоит тратить на нее столько усилий? За это время вы успеете очно пообщаться с 2-3 другими компаниями.

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


P.S. Речь шла о PHP, который позволяет как выстраивать "ентерпрайзных монстров", мало отличающихся от джавных, так и писать километровые скрипты в "баш-стиле" с рельсоподобной магией посередине.

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

Публикации

Истории