Кандидат: Черкасов Евгений Александрович hh.ru
Задание: гугл-документы
Код основного компонента можно посмотреть тут:
1/src/stories/Breadcrumbs.js
Для удобства я положил компонент в storybook. Чтобы открыть витрину в браузере нужно выполнить следующие шаги:
$ cd ./1
$ yarn
$ yarn storybook
Код в файле 2/index.js
Тесты в файле 2/index.test.js
Тесты можно запустить следующим образом
$ cd ./2
$ yarn
$ yarn test
Код в файле 3/index.js
Тесты в файле 3/index.test.js
Тесты можно запустить следующим образом
$ cd ./3
$ yarn
$ yarn test
Самый важный принцип для меня - это KISS, что значит "не усложняй", когда можно не усложнять. Довольно часто я отстаиваю именно эту позицию при принятии решений и при ревью кода. Если я вижу что код написан сложно и нужно потратить время, чтобы разобраться в нем, то я скорее верну реквест на доработку.
Принцип DRY мне тоже близок, но на этапе разработки я склонен часто его нарушать, чтобы в будущем исправить. Пример: Бывает, что команда делает несколько родственных, но разных компонентов и гораздо проще и эффективнее реализовать эти компоненты изолированно, а потом выделить общий код и вынести в родительский компонент или ХОК, чем на старте обсудить все нюансы и заблокировать работу команды пока один сделает общий код, от которого придется наследоваться.
Принцип YAGNI очень близок к KISS и его тоже стараюсь активно продвигать. Думаю нет программиста, которому нравится делать ненужную работу.
С SOLID сложнее - это 5 независимых принципов, каждый из которых довольно хорош. Могу отметить что стараюсь придерживаться принципа разделения интерфейса, и принципу единственной ответственности. Вероятно, другие принципы я тоже практикую, но скорее неосознанно :)
Так же хочу отметить близкие методологии. В своей работе я пробую разные методологии, ведь для разных частей приложения подходят разные методологии.
Для UI мне нравится использовать Component Driven Development — сначала создаем все компоненты изолированно, а потом собираем из них, как из лего, более сложные компоненты или страницы. Очень хорошо на эту методологию ложится Atomic Design, когда UI делится на атомы, молекулы и организмы. На этом подходе я построил около 10 приложений.
С приходом TypeScript я стал использовать Type Driven Development — сначала пишем интерфейсы и типы, а затем делаем реализацию. Это позволяет на берегу качественно продумать все связи в разрабатываемой фиче, а затем очень легко и быстро набрать основной код, так как IDE практически 80% пишет за тебя.
К сожалению, я довольно редко пишу тесты, но TDD для некоторых моментов очень выручает. Например, в текущем своем проекте я использую TDD для реализации сложных адаптеров, которые покрывают сразу несколько кейсов. Так же я использовал TDD для реализации 2 и 3 задания. Это позволило не беспокоиться, что я не учту "особые" случаи, а так же сэкономило время на ручной проверке всех вариантов входных данных.
Основные паттерны, которые я использую осознанно:
Фабрика - по заданным параметрам возвращает нам нужный объект. В Реакте можно использовать для генерации разнотипных элементов списка типа list.map(item => factory(item))
Адаптер - в последнем проекте использую на 100%. От бекенда приходят грязные данные, поэтому с помощью адаптеров преобразую их в необходимый вид и кладу в стор: fetchData().then(adapter).then(saveToStore)
Декоратор - по сути ХОКи в реакте. Например: withBorder(Card)
Фасад - бывает что нужно взять какую-то сложную, часто универсальную, либу для использования в конкретном кейсе. Фасад нужен, чтобы упростить интерфейс либы. Например на вход будет приниматься 1-2 бизнес параметра вместо 10 технических.
Про Состояние и Наблюдателя я думаю даже не имеет смысла что-то уточнять. Все мы где-то храним состояние и подписываемся на его изменение.