Осталось совсем немного до окончания набора в третью Школу разработчиков интерфейсов, которая в этот раз пройдёт в Москве. Упор в ней будет сделан на практику в формате виде мини-хакатонов. Его мы уже опробовали в прошлом году в Минске и Екатеринбурге. Студенты будут делиться на команды, и уже командно реализовывать проект. Кроме написания самого кода, нужно будет уметь принимать решения, разбираться с возникшими спорными вопросами, разбивать весь процесс разработки на логические итерации. Помогать в этом будут ребята из Яндекса, которые будут работать индивидуально с каждой командой. Занятия начнутся 7 сентября.

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

Вступительное испытание в Школу тоже очень практическое. Мы закончим принимать заявки 16 августа в 23:59. Пока есть еще время справиться с заданиями, мы попросили наших преподавателей немного помочь будущим студентам и на примере прошлогодней анкеты объяснить, какой логикой стоит руководствоваться, решая предложенные задачи, и рассказать, чему они уделяют внимание при их проверке.

image

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

Задание 1


Автор задания и разбора — Олег Olegbl4 Мохов. В Яндексе руководит разработкой интерфейсов нескольких сервисов, а вне Яндекса организует конференции FrontTalks, EkbJS и ChellyJS и читает спецкурс по разработке интерфесов в УрФу.

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

Решение


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

Конечно, решения данного задания можно найти в просторах интернета за условные пять минут. И оно, например, может быть таким: css-tricks.com/centering-css-complete-guide. Поэтому при реализации было немаловажно кроме количества решений привести ещё и пояснения, где какое стоит использовать. Например, мы намеренно не стали писать, что размеры элемента можно задавать, и в некоторых решениях это приемлемо. Также мы уделяли внимание таким вещам, как CodeStyle, именование классов или id'шников элементов, использование семантических тегов и вообще культуру оформления вёрстки (сборка, разбиение на файлы).

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

  1. margin-left и margin-right в auto. Это, пожалуй, самое распостранённое использование отступной математики блочных элементов.
  2. В ту же копилку решение с заданием position: absolute; left: 50%; margin-left: <-половина ширины>. И это второй по популярности способо справиться с ним.
  3. Модификация первого варианта для position: absolute блоков. В этом решении важно задать не только автоматические margin'ы, но и left: 0; right: 0;

Решения центровать элемент по вертикали с заданной высотой рассматривать не очень интересно, так как это, скорее всего, вариация решений по горизонтали. Поэтому далее решения для элементов с неизвестными шириной и высотой:
  1. Положить элемент внутрь ячейки таблицы, для которой заданы выравнивания по середине. Пожалуй раньше, когда был IE6, это был самый пуленепробиваемый способ.
  2. Воспользоваться JavaScript. А что, тоже вполне себе решение.
  3. Более современное решение. Задать элементу inline-block display и родителю выравнивание текста по центру (text-align: center). А для центрования по вертикали псевдоэлементу ::before задать высоту 100%, ширину 0, line-height 100% и vertical-align: middle.
  4. Более современные решения – это использование CSS-функции calc.
  5. Или особенности того, что transform, заданный в процентах, считается от размеров элемента.
  6. И, наконец, флексбоксы, причем ими тоже можно по-разному центровать, потому что есть align-items, есть justify-content, а ещё можно менять направление вывода флексовых блоков через flex-direction.

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

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

Ещё два решения мне подкинули студенты первой ШРИ в Екатеринбурге.

Способ Юли Горшковой. Она придумала следующее: положить элемент в среднюю ячейку таблицы с тремя ячейками и растянутой на 100%, а правой и левой колонкам задать ширину 50%. Зная о том, что таблицы всегда пытаются максимально заполнить свободное пространство, можно сделать так, что элемент будет распирать среднюю ячейку до нужных себе размеров.

Способ Леонида Соломеина. Это мой самый любимый вариант — нужно просто положить элемент в <button></button>.

Но есть самый прогрессивный способ, который, к сожалению, пока не поддерживается ни одним браузером. Как только это изменится, все 12 перечисленных решений канут в Лету. Это использование position: center.


Задание 2


Автор задания и разбора — Максим KidsKilla Гришаев. В Яндексе занимается разработкой Элементов для Firefox.

Есть страница с «эквалайзерами» — контейнеры произвольных размеров (квадраты 100px, 200px и 300px) заполняются столбцами шириной по 2px (задаётся параметром).

Каждую секунду столбцам задаётся случайная высота в пределах размеров контейнера. Далее при помощи анимации высота столбцов возвращается к середине контейнера. Реализация находится в файле: github.com/yandex-shri-minsk-2014/jade-task. Исходный код работает медленно и приводит к зависанию браузера. Нужно улучшить его так, чтобы анимация стала плавной. Изменять вёрстку необязательно, однако вы можете это сделать, если это поможет решить задачу. Работоспособность в IE ниже 8 не требуется. Желательно добавить помимо анимации «спада» ещё и анимацию «роста». По возможности оформите в качестве jQuery-плагина или напишите без jQuery.

Решение


Тема оптимизации кода очень широка. Есть множество критериев, на которые стоит обращать внимание при оценке качества кода, но можно выделить несколько важных:

  • наличие ошибок в поведении;
  • удобство чтения, единообразность кода;
  • легкость понимания взаимосвязей;
  • скорость работы;
  • наличие «велосипедов», когда можно воспользоваться уже готовыми рабочими решениями.

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

Но были и другие способы улучшить код и произвести впечатление на судей.
  • Привести именование переменных к единому стилю. Очень сложно читать код, где нет единых правил оформления.
  • Разбить код на более мелкие методы. Куда проще прочитать маленький, логически цельный метод, длиною в 5-10 строк, чем «спагетти-код».
  • Сократить кол-во таймеров. Работая с анимаций множества элементов, логично использовать какой-то общий аниматор с единым таймером, который за за одну итерацию обновит сразу всё.
  • Запускать код так рано, как это возможно. В коде использовалось событие window.onload, но куда логичнее было бы использовать событие DOMContentLoaded или просто поставить вызов анимации под блоком.
  • Оптимизировать CSS. В задании анимируется span (display: inline-block). Он привязан к размерам шрифта, строки и прочего окружения и влияет на reflow/repaint всей страницы. Абсолютное анимируемых элементов даст прирост производительности.
  • Оформить код как независимый модуль. Слово модуль в данном контексте можно трактовать довольно широко: это мог быть плагин для jQuery или отдельный «класс». Например, не сразу понятно что значат аргументы при вызове функции: setEqualizer('#eq_1 .equalizer', 1000, 2);. Однако вот так уже гораздо лучше: $('#eq_1 .equalizer').equalizer({itemWidth: 2, animationDuration: 1000}). Или вот так: new Equalizer('#eq_1 .equalizer').setItemWidth(2).setAnimationDuration(1000).start().
  • Применить технологии, более приспособленные для анимации: css, canvas, а то и WebGL.

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


Задача 3*


Автор задания и разбора — Илья Довбан. Илья руководит группой поисковых интерфейсов в минском офисе Яндекса.

*Все больше и больше различных технологий становятся доступны в браузере, тем самым расширяя потенциальный инструментарий фронтедера. Очевидно, что никаких навыков не хватит, чтобы уверенно разбираться в разработке интерфейсов, трехмерной графике, модификации звука, расчетах больших объемов данных. И, разумеется, все и сразу оно в итоге не надо. Но современный фронтенд-разработчик должен уметь разобраться в новой области и освоить непривычный инструментарий, как только придет необходимость. Именно об этом и было третье (на звездочку) вступительное задание.

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

Решение


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

Для начала стоит разобраться с тем, что же это за d3.js. Первый же визит на официальный сайт библиотеки показывает, что это не очередная обертка над WebGL для 3d-графики (на что могло намекать название), а очень большой набор средств для визуализации и анимации различных видов данных. Что ж, принципиально новой тут оказалась не только библиотека, но и вся предметная область. Так что не подойдет вариант быстро просмотреть API-документацию нового, но концептуально такого же MVC-фреймворка. Придется начать с чтения tutorial-ов.

Из ознакомительной части стало понятно, что библиотека оперирует наборами данных. В нашем случае это будет набор точек, о каждой из которых известны ее цвет и координаты. Да, и раз уж мы делаем прототип о «разробраться с библиотекой», лучше сразу начать по максимуму использовать ее возможности. Например, d3.range вместо создания массива точек вручную:

 var dots = d3.range(1000);

d3.select('svg').selectAll('circle')
.enter().append('circle');

Тут же заодно проверим, что наши точки нормально выводятся на svg-холсте.

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

И для того, и для другого в d3.js есть функции-хелперы, ими и воспользуемся.

На что обращают внимание при проверке



Евгений FTDeBUGgeR Шпилевский — руководитель разработки интерфейсов прикладных сервисов поиска в минском офисе Яндекса.

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

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

При проверке JS-кода для меня было важно увидеть качественный код, как с точки зрения структуры, так и алгоритмической стороны. В целом я и исходил из тех же принципов, которыми руководствуюсь на код ревью. Хотел бы я видеть этот код в своем репозитории? Готов ли я его поддержать? В итоге самый беспощадный отбор. Минусом было смешение парадигм и нарушение принципов DRY и KISS, ошибки выявленные WebStorm/jshint, неконсистентность логики и подходов. Грубой ошибкой было наличие ошибок в консоле инструментов разработчика.

Использование методологии БЭМ было плюсом при проверке CSS. Также плюсом были количество и лаконичность найденных решений. Минусы ставил только за использование сложных селекторов и селекторов по идентификатору.

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


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

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

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

Отдельно хотелось бы добавить комментарии к каждому заданию:

Задание на верстку. Многие пытались решать эту задачу только средствами CSS и HTML и даже использовали селекторы на фрагменты страницы (:target), чтобы открывать окна. Однако формулировка задания никак не ограничивает использование JavaScript для открытия и центрирования окна. Я согласен, что использовать JavaScript для решения задач верстки не очень хорошо, но если вы продемонстрируете свои знания и оцените свои решения, то это безусловно плюс.

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

Задание про «неизвестную» технологию: d3.js Оно было объемным и творческим. С одной стороны интересно посмотреть как ребята осваивают новые интрументы, а с другой — кто же все-таки знает, что такое броуновское движение :) К сожалению, задание выполнили не все, и я бы пожелал ребятам не откладывать заполнение анкеты и начать делать это уже сейчас.

Занятия в Школе начнутся 7 сентября в московском офисе Яндекса. Теоретическое изучение и разбор материалов будет проходить в будние дни с 18:00 до 20:00, а по субботам будет практика в форме хакатонов. Обучение бесплатное.

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


  1. damat
    12.08.2015 21:15
    +3

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

    >>> Школа разработки интерфейсов, в рамках которой пытаемся в максимально сжатый срок превратить веб-разработчиков в крутых веб-разработчиков

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


    1. Sullenor
      12.08.2015 23:08
      +1

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

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

      Ну и на правах оффтопа: мне всегда казалось, что понятие «Разработка интерфейсов» подразумевает углубление в какую-то узкую область знаний, нежели «Веб-разработка». Последнее подразумевает более широкий кругозор.


      1. mifki
        13.08.2015 05:07
        +2

        Что значит, сложнее поменять? Заявлена разработка интерфейсов, а на деле — просто верстка. Зачем обманывать?


        1. Sullenor
          13.08.2015 11:36
          +2

          Я имел ввиду, что название Школы устоялось со временем и если его поменять, то, как мне кажется, это вызовет больше вопросов :)

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


          1. mifki
            13.08.2015 11:48
            -2

            Вероятно, у нас разное понимание слова «разработка». Для меня «разработать интерфейс» — это его придумать, то есть дизайн/UX. У вас же это «запрограммировать интерфейс».


            1. dima_smol
              13.08.2015 13:58

              То, что ты вкладываешь в «разработать интерфейс», это его проектирование. Этим как раз заняты дизайнеры.
              Разработка это как раз про то, чтобы сделать этот интерфейс рабочим.


              1. mifki
                13.08.2015 15:24

                Да, видимо, так.


              1. Archon
                13.08.2015 17:04

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

                А на этих курсах под «разработкой интерфейса» подразумевается узкий частный случай третьего пункта — вёрстка интерфейсов под веб.


            1. Teadon
              13.08.2015 16:44

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


  1. menix
    13.08.2015 00:26
    +2

    Первое задание всегда использую на собседованиях в качестве теста на верстку. Народ справляется посредственно, хотя и правда, сложно представить себе того кто не решал эту задачу.
    В статье не указано в чем состоит «метод Студии Лебедева».


    1. Olegbl4
      13.08.2015 13:57

      Ссылка потерялась при публикации, если что речь про этот способ www.artlebedev.ru/tools/technogrette/html/align-center


  1. NeX
    13.08.2015 06:39
    +2

    Для попапа есть еще такая штука — caniuse.com/#feat=dialog + polyfill github.com/GoogleChrome/dialog-polyfill


    1. Olegbl4
      13.08.2015 13:56

      Круто! Спасибо, не знал


      1. lahmatiy
        16.08.2015 23:33

        И еще про Grid Layout забыл упомянуть ;)

        Решения центровать элемент по вертикали с заданной высотой рассматривать не очень интересно, так как это, скорее всего, вариация решений по горизонтали.

        По горизонтали старыми «дедовскими» способами все таки равнять проще, даже зная размеры блока. Только второй способ можно переложить на выравнивание по вертикали.


        1. NeX
          17.08.2015 11:08

          Только с поддержкой пока все очень плохо caniuse.com/#feat=css-grid


        1. Olegbl4
          18.08.2015 09:58

          Все разы что я слышу про grid layout, у меня ощущение что он скорее мёртв чем жив. Вот и товарищ NeX выше подтверждает, что за 5 лет ничего не поменялось


          1. PSDCoder
            18.08.2015 10:07

            Осенью должны перевести в статус кандидата.
            http://www.w3.org/Style/CSS/Planet/#item2


  1. phil_b
    14.08.2015 18:23

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


    1. Olegbl4
      19.08.2015 13:49
      +1

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


  1. geakstr
    19.08.2015 23:42
    +1

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


  1. Night_Coder
    26.08.2015 15:47

    > Также минус ставил, если у меня на ноутбуке начинал работать вентилятор

    Как-то не очень честно. А вдруг он стал из-за других процессов шуметь?


    1. Sullenor
      27.08.2015 12:32

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


    1. FTDeBUGgeR
      28.08.2015 15:13

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