Разбираем тестовое задание на должность фронтенд-разработчика на Vue.js

    Первое правило тестовых заданий - никогда не делайте тестовые задания!

    Об этом уже было множество споров на Хабре, и тут мне выпал случай выучить этот урок на собственной шкуре. Решение я отправил, но ответа так и не дождался. Даже отрицательного. Ничего. Конечно все можно списать на кризис, что вакансию внезапно заморозили(такое я слышу часто в последнее время, но эти же вакансии продолжают висеть). Но все же банальной вежливости было бы более чем достаточно. Вывод однозначен: нужно тщательнее проверять надежность собеседника прежде, чем вгрызаться в тз.

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

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

    Для ознакомления с заданием, которое я получил, прошу под спойлер:

    Техническое задание:

    Средствами Vue.js реализуйте небольшое SPA приложение для заметок.

    Каждая заметка имеет название и список задач (todo list), далее - Todo. Каждый пункт Todo состоит из чекбокса и относящейся к нему текстовой подписи.

    Приложение состоит всего из 2х страниц.

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

    • перейти к созданию новой заметки

    • перейти к изменению

    • удалить (необходимо подтверждение)

    Страница изменения заметки позволяет определенную заметку отредактировать, отметить пункты Todo, а после сохранить изменения. Действия с заметкой:

    • сохранить изменения

    • отменить редактирование (необходимо подтверждение)

    • удалить (необходимо подтверждение)

    • отменить внесенное изменение

    • повторить отмененное изменение Действия с пунктами Todo:

    • добавить

    • удалить

    • отредактировать текст

    • отметить как выполненный

    Требования к функционалу:

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

    • Подтверждение действий (удалить заметку) выполняется с помощью диалогового окна.

    • Интерфейс должен отвечать требованиям usability.

    • После перезагрузки страницы состояние списка заметок должно сохраняться.

    • Можно пренебречь несоответствием редактирования текста с помощью кнопок отменить/повторить и аналогичным действиям с помощью комбинацияй клавиш (Ctrl+Z, Command+Z, etc.).

    Технические требования:

    • Диалоговые окна должны быть реализованы без использования "alert", "prompt" и "confirm".

    • В качестве языка разработки допускается использовать JavaScript или TypeScript.

    • В качестве сборщика, если это необходимо, используйте Webpack.

    • Верстка должна быть выполнена без использования UI библиотек (например Vuetify).

    • Адаптивность не обязательна, но приветствуется.

    • Логика приложения должна быть разбита на разумное количество самодостаточных Vue-компонентов.

    Особое внимание стоит обратить на следующие моменты:

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

    • Читабельность и наличие элементарной архитектуры.

    • Чистота и оформление кода — не менее важный фактор. Код должен быть написан в едином стиле (желательно в рекомендуемом для конкретного языка). Также к чистоте относятся отсутствие копипаста и дублирования логики.

    Тестовое задание должно быть предоставлено в следующем виде:

    • Ссылка на публичный репозиторий (GitHub, BitBucket, GitLab) с исходным кодом.

    • Ссылка на сайт для тестирования функционала. Или Dockerfile и docker-compose.yaml, позволяющие развернуть локально командой docker-compose up работоспособную копию сайта.ехническое заданиеехническое заданиеехническое задание

    Вот что у меня в итоге получилось.

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

    Разберем по пунктам задание и возможные способы его решения:

    Средствами Vue.js реализуйте небольшое SPA приложение для заметок. Тут все просто: используем Vue CLI для создания проекта.

    Каждая заметка имеет название и список задач todo list, (далее - Todo). Каждый пункт Todo состоит из чекбокса и относящейся к нему текстовой подписи. - А вот и первая сложность, у нас будет два уровня абстракции: множество заметок и множество дел, которые составляют заметку.

    Приложение состоит всего из 2х страниц. Тут возник вопрос - использовать ли Vue Router? Это же всего две страницы. Дальше из задания мы узнаем, что первая страница используется для отображения списка заметок, а вторая - для редактирования отдельной заметки. Конечно, можно переключать компоненты условным оператором, но раутер даст возможность перехода на сгенерированные страницы для каждой заметки. Но это уже больше двух страниц, или сгенерированные страницы считаются за одну, так как они по одному шаблону сделаны? После недолгих колебаний я решил все-таки его использовать.

    Дальше следуют подробности по каждой странице, обратим внимание на два пункта:

    • отменить внесенное изменение

    • повторить отмененное изменение

    Это про редактирование заметки. Решение тут же пришло мне в голову: создать массив, который запоминал бы историю изменений заметки, каждый элемент массива содержал бы состояние заметки до следующего изменения. С помощью кнопок можно было бы "скакать" по истории, и реактивность Vue нам очень в этом помогает.

    Do и Redo
    Do и Redo
    • Все действия на сайте должны происходить без перезагрузки страницы. Это означает стандартное SPA, мы и так используем Vue CLI.

    • Подтверждение действий (удалить заметку) выполняется с помощью диалогового окна.

    • Диалоговые окна должны быть реализованы без использования "alert", "prompt" и "confirm".

      Диалоговое окно должно создавать Promise, который зависит от решения юзера. Желательно, чтобы решение было переиспользуемым для всех наших случаев. Помучавшись над решением, я пришел к выводу, что лучше использовать готовое решение, к тому же запретов на пакеты не было. Я использовал vue-modal-dialogs - очень удобная библиотека, рекомендую. Надеюсь её перепишут для Vue 3.

    • Интерфейс должен отвечать требованиям usability. Другими словами, он должен быть удобным. Лучше бы написали конкретные требования, так не очень понятно.

    • После перезагрузки страницы состояние списка заметок должно сохраняться. - Так как серверной части у нашего приложения не планируется, заметки следует сохранять на стороне клиента, для этого есть два решения Cookie и localStorage. Выбираем кому что ближе, так как в тз нет четких ограничений. Я выбрал localStorage. К тому же я решил не использовать Vuex, а вместо него использовать локальное хранилище, как единый источник истины. Для небольшого приложения без бэка это выглядит разумным решением, экономящем время, в других случаях я не рекомендовал бы так делать.

    • В качестве языка разработки допускается использовать JavaScript или TypeScript. - а разве есть еще варианты? Честно говоря, ТЗ оставляет ощущение, что тот кто его составлял плохо знаком с Vue. TypeScript на Vue 2 спорно применять, слабая поддержка. Посмотрим, что будет на Vue 3.

      Важное замечание для тех, кто захочет воссоздать его с нуля на новой версии! Мой проект написан на Vue 2, обещали, что старый синтаксис будет работать, но все же.

    • В качестве сборщика, если это необходимо, используйте Webpack. Vue CLI это и есть Webpack, настроенный для удобства создания SPA на Vue.js

    • Верстка должна быть выполнена без использования UI библиотек (например Vuetify) - это минус. Для того чтобы "оживить" приложение, я использовал Material Icons от Гугла, вместо кнопок. Не знаю, оценил ли заказчик, он так и не ответил.

    • Адаптивность не обязательна, но приветствуется. - flexbox в помощь.

    • Логика приложения должна быть разбита на разумное количество самодостаточных Vue-компонентов. - у меня вышло семь: 2 на страницы, еще заметка, тудушка, заголовок заметки, кнопка-иконка и диалоговое окно.

      Остальные пункты менее важны.

    Еще из вкусностей:

    Я использовал пакет v-click-outside. Название говорит само за себя. Он добавляет директиву, которая срабатывает при клике вне элемента. Можно было написать самому, но я решил не изобретать велосипед. Использовал для отмены редактирования тудушки, если пользователь кликнул где-то еще. Это в задании не было, включим это в юзабилити.

    Еще мне пришла в голову такая мысль: а что делать, если юзер захочет покинуть страницу редактирования заметки? Куда повесить вызов диалогового окна: на историю браузера, на кнопки меню? Есть элегантное решение. Vue-Router добавляет хуки жизненного цикла в компонент. Хук beforeRouteLeave поможет нам во всех ситуациях когда пользователь пытается покинуть страницу. Пусть наш хук вызывает модальное окно. Только не забыть сделать его асинхронным, ведь окно возвращает промис. Например, вот так:

      async beforeRouteLeave (to, from, next) {
        if (await confirm('Do you realy want to leave this page?',
           'All unsaved changes will be lost.')) {
            this.clearNote()
            next()
          } else{
            next(from)
          }
      }

    Вот и все. Я описал свой процесс решения тех задания по Vue.js. Код проекта получился довольно длинный, поэтому дотошное описание его потянуло бы на несколько статей. Полный код проекта доступен здесь.

    Если возникли вопросы и замечания, прошу в комментарии или личку.

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +1

      Так собеседование прошёл или нет? ;)

        0
        До собеседования не дошло(
        +4
        Ох уж эти тестовые задания, я на них свой навык vuejs прокачал до уровня, чтобы можно было нырнуть в уютный пет-проект и вылезать из него только чтобы поработать.
        До этого я неоднократно начинал его делать, но сталкивался с тем, что без нормального фронтэнда приложение вообще не вдохновляло.
          +1

          Такое ощущение, что я его делал, но в менее подробном варианте и на react. Да ещё и на позицию senior/tech lead.


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


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

            +1
            Первое правило тестовых заданий — никогда не делайте тестовые задания!


            Ну не знаю, на свою первую работу по фронтенду я устроился, написав тестовое задание. (3 дня писал, дважды переписывал), зато сразу на позицию миддла. Без тестового задания со мной даже разговаривать бы не стали.
              +3
              На самом деле все зависит от адекватности компании и тестового задания. Однажды мне предложили сделать полноценную CRM для фитнес клуба с красивым дизайном, регистрацией, лендингом, откуда будут падать заявки и интерфейсом для работы персонала с кучей функционала (на вакансию backend). Конечно, от таких предложений я отказывался. Тестовое должно быть объемом максимум на пару часов, а ни как не на недельку — другую. Я сам, когда провожу собеседования в первую очередь общаюсь с людьми о их опыте и навыках, задаю элементарные вопросы, только если он подходит выдаю простое тестовое задание, в результате которого, я жду лишь подтверждения указанного самим человеком опыта.
                0

                Вы не смотрите их репозиторий? Не просите примеры написанного ими кода?

                  0
                  Конечно, если кандидату есть что показать из готового кода, я на это смотрю.
                    0
                    Мне просто интересно в предверии поиска работы, на что делается акцент и что может сыграть(хотя видимо индивидуально)
                    1) Опыт из резюме, который теоретически можно написать вообще любой
                    2) Репозиторий, куда можно положить теоретически не свои задачи
                    3) Ссылки на тостер и stackoverflow с хорошим рейтингом и множеством отвеченных вопросов (тут уже не придраться, показатель относительно объективный)
                    4) Live собеседование (но оно может не дать ясной картины, так как кандидат может волноваться и задачи можно дать лишь простые)

                    И получается что тестовое на пару часов наиболее объективный показатель
                      0
                      1) Опыт уж точно лучше писать реальный, максимально объективно, без переоценок. Адекватные компании ищут инженеров, которые решают нужные задачи, хорошему работнику прокачать опыт еще в одном стеке нужно немного времени.
                      2) Если я смотрю репозитории, то задаю вопросы, почему были приняты те или иные решения. Если кандидат скопирует чужие задачи, то быстро спалиться, хотя такого я не встречал, мне интересно как человек принимает решения.
                      4) На live собеседованиях, мне главное проверить не блефует ли человек, задаю вопросы от простейших и постепенно перехожу к коротким, не сложным задачам. Мне здесь важно оценить способность инженерно мыслить. По моему опыту хождения на собеседованиях, встречал разное, от абсурдного и смешного до профессионального, продуктивного общения. Встреча работодателя и кандидата — это наверное самое важное, здесь сразу можно понять с кем и как предстоит работать, решить нужно ли оно обоим.
                        0
                        Согласен.
                    0

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

                      +1
                      Часто в вакансиях, я вижу, что просят прислать примеры работ и без них даже лучше не обращаться. Все зависит от работодателя/HR. Если у человека уже есть примеры работ, это просто ускоряет собеседование. Я стараюсь всегда подготовить вопросы и задачи, которые непосредственно связанны с тем, над чем предстоит работать. И вообще, собеседование это двухсторонний процесс, где оба должны понять, получиться сработаться или нет. Посещая собеседования, я часто сталкивался, что либо собеседующий совсем не компетентный или ищет работников похуже себя и задают странные вопросы, иногда даже не связанные с разработкой. Часто встречал, что дают задачи из своего пула задач, особенно этим любят промышлять студии. Задачи из пула, это конечно интересно, но такие задания, должны быть уже оплачиваемые. Вот адекватные собеседования, это редкость, в основном бывают в крупных продуктовых компаниях.
                        0
                        Подготовка к собеседованию означает, что таки придётся потратить месяц-другой, чтобы написать в публичный доступ хоть что-то, лишь бы красиво и достаточно сложно для себя?
                  0
                  А я — пришёл на квартирник, выпивал с будущим шефом.
                  0

                  Может кому то, будет интересно. Делал такое же тестовое. Кстати дальше прошел. https://github.com/dDenysS/vue-todo

                    0
                    Видимо это популярное тестовое
                      +1

                      Задания совпадают на 100%, то я даже знаю на какую вакансию вы подавали. Скажу так что вы много не потеряли, условия работы немного строгие.

                      0
                      Можно подскажу? В твоем компоненте Button можно избежать повторения кода, если использовать this.$router.push(path)
                        0
                        Да, можно. Спасибо. Я там оставлял комментарий в начале файла. Да, можно сделать как вы говорите, но я уже точно не помню что меня толкнуло разделить на button и router-link. Может для большей семантики кода.
                      0
                      UPD: дополнил вступление для лучшего объяснения цели статьи
                        +1

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


                        Мне больше нужно было проверять такие, чем выполнять, и каждый раз возникает вопрос "и на что смотреть? Все как везде, что оно проверяет?"


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

                          0
                          TypeScript на Vue 2 спорно применять, слабая поддержка.
                          Для поддержки TypeScript есть сторонние библиотеки и они вполне хорошо работают.
                            0
                            Странно, что для тайм тревела изобрели свой велосипед с массивом, vuex тут вполне подошел бы. Кстати, это был бы дополнительный бонус, показывающий, что вы умеете работать с vuex.
                              0
                              А как еще создать эту фичу без массива? Велосипеды тоже иногда полезно писать. Про Vuex согласен, с другой стороны они не хотят лишнего кода. Чужие мысли не прочитаешь
                              +1
                              Увы, сейчас 90% вакансий, требующих выполнения тестового задания, вообще не отвечают после его выполнения, либо, в редких случаях, отписываются явно шаблонным сообщением «Вы нам не подходите, но мы занесем ваш контакт в нашу базу на всякий случай».
                              А самое печальное — половина ТЗ требует как минимум 1 дня на выполнение (Т.к. требуется писать с нуля, иногда без использования фреймворков).

                              Отдельный маразм: Потребовали написать одностраничник с формой обратной связи. Без фреймворков. Вообще всё ТЗ было так составлено, что проще всего его выполнять «в старом стиле», через функциональный подход, двумя файлами (вывод страницы и обработчик формы).
                              А в итоге выяснилось, что они ожидали чутьли не полноценный аналог Laravel…
                                0
                                Суровые времена настали
                                0
                                А посмотри еще NUXT ru.nuxtjs.org. Если сделать тестовое задания с использованием верхнеуровневого фреймворка, можно показать, что не просто что-то умеешь, а готов делать комплексные проекты.
                                  0
                                  Nuxt это круто, но в данном случае просили SPA. Я знаю, что в NUXT тоже есть режим SPA, но NUXT это про SSR в первую очередь.
                                  0
                                  Выполнить тестовое задание или показать в нем навыки — разные вещи.

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

                                  В задании запретили использовать сторонние библиотеки — ну покажите, что можете без них.
                                  Если в тексте формулировки ИЛИ, то нужно выбирать более ценное решение из предложенных. Согласитесь, если бы приложение было обернуто в docker, написаны какие-нибудь jest тесты, в коде использовались разные приемы организации css: scope / modules / бэм, подключен vuex, реализована асинхронная подгрузка, js'ки заменить на ts'ки с внятным описанием типов (или вообще собрать на vue3), добавить I18n, нормально оформить конфиг, т.д.; то результат работы выглядел бы куда интереснее, чем простое выполнение.

                                  PS: На месте фаундера не ответить было некрасиво.
                                  +1
                                  Это уже не тестовое задание на пару дней, а полноценный проект.
                                    0
                                    сайта.ехническое заданиеехническое заданиеехническое задание

                                    поправьте
                                      0
                                      Делал такое же кста
                                      github.com/vadimLuzyanin/vue-todo-list
                                      Дошел до собеседования, но фидбека по нему так и не получил)
                                        0
                                        я когда работу искал, делал кучу тестовых заданий. В итоге попал на ту, в которой вообще его не было. Больше не буду этим заниматься. Если надо, покажу им что-то из своего гитхаба)
                                        0
                                        Имеет смысл определять для себя целесообразность выполнения задания, исходя из всех факторов.
                                        * Поможет ли выполнение собственному развитию,
                                        * хорошо ли оно будет смотреться в собственном портфолио,
                                        * приложил ли работодатель усилия, чтобы познакомиться с вами.

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

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

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

                                        Детали: habr.com/en/post/213913 (от 2014 года).

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

                                        Самое читаемое