Некоторое время назад у меня состоялся интересный разговор, коллега активно защищал Angular, говорил, что тот ускоряет веб-разработку. Я более десяти лет разрабатываю сложные web-сервисы, работал в Microsoft, в Spotware Systems на Кипре, сейчас создаю приложение для стартапа из Кремниевой долины, и в общем то слежу за трендами. Однако почувствовал себя динозавром, потому что не видел смысла использовать фронтэнд-фреймворки до того момента, а оказалось, что это уже мейнстрим. Шёл 2014-й год, я погрузился в мир Angular, Knockout и Backbone, что из этого вышло, почему я от них в итоге отказался и рекомендую коллегам сделать то же самое – под катом.
Все мы знаем, что Angular имеет много проблем, и одна из основных – отладка. При появлении недокументированных ошибок спасает только stackoverflow, и то приходится поискать что же конкретно случилось, и главное в каком месте. Backbone и Knockout тоже имеют свои недостатки, но многие продолжают ими пользоваться, потому, что достоинства их перечёркивают. А если честнее – потому что не видят альтернативы. А альтернатива есть, просто о ней забыли.
Помните старый программистский принцип – каждый модуль должен выполнять одну функцию. Если он выполняет две или более – его нужно разбить на части. Почему так и зачем этого придерживаться желающие могут прочитать сами в огромном количестве открытых источников. Так вот все существующие фреймворки нарушают этот принцип. Скажу больше, сам подход “фреймворк” нарушает его. Фреймворк загоняет нас в рамки, заставляя нас следовать “лучшим практикам”, только лучшие практики постоянно развиваются и небольшая группа создателей просто не в состоянии знать, какие практики универсально подходят и для небольшой промо-страницы с анимацией, и для менеджмент-панели со сложной логикой администрирования данных и для медиа-сайта с высокими требованиями к производительности. Лучшие практики оттуда можно почерпнуть только если вы совсем новичок в программировании, тогда фреймворк дисциплинирует. Но я дам вам другой совет – берите лучшие практики, но оставляйте фреймворк в стороне от работы. Объясню, что я имею в виду.
Кажется, что фреймворк – это нечто большое, что невероятно сложно воспроизвести. На самом деле это просто набор стандартных паттернов. Например паттерн Наблюдатель, он используется в моделях Backbone, в дата-биндинге Angular и Knockout, и производит довольно большое “Вау!”. Но это всего лишь известный давным-давно паттерн, который можно реализовать на JavaScript за 30 строк кода или скачать один из тысяч готовых вариантов (к слову сказать они все одинаковые, отличаются только названием методов, так как принцип паттерна один). Другие компоненты фреймворков устроены похожим образом. Часто понимая принцип можно вообще написать лишь ноль строчек кода, например реализуя MVP в рамках небольшого компонента просто мысленно разделять, что эти методы – это контроллер, эти свойства – модель и т.д…
Пример из практики: как-то раз я проходил собеседование в одну фирму в Испании. Нужно было сделать тестовое задание, за час в режиме live-coding создать одностраничное приложение по документации, сколько успею. Я успел полностью, на JavaScript с одними лишь модульными библиотеками. Даже осталось немного времени написать тесты. Люди не понимали, как можно реализовать роутинг с переключением страниц, сложные интеактивные элементы и другое за такое время без фреймворков. Это ребята, которые, как и я, 10 лет в отрасли, но они изучали конкретные решения, а не принципы.
Когда вы изучаете фреймворки – вам нужно переучиваться переходя на новое решение, а они появляются постоянно, и большая часть вашего опыта стирается. Когда вы изучаете принципы – они остаются. Я использую библиотеку для создания классов, написанную 5 лет назад. Ижектор модулей, реализация наблюдателя, написанные примерно в это же время. Каждый из них выполняет ровно одну функцию и выполняет её хорошо. Ни разу у меня не возникало желания менять один компонент на другой, как бывает с фреймворками, потому что “наблюдатель” есть “наблюдатель”, это паттерн, а не код. Паттерны могут комбинироваться в зависимости от задачи, но они не изменяются. Ещё один старый принцип – код может дополняться, но не изменяться. Его обоснование тоже без труда можно найти в google или в книгах банды четырёх. Следуя этой логике, если у фреймворка или библиотеки появляется вторая версия, третья, десятая, какие-то функции удаляются, какие-то изменяются – это изначально порочный продукт. Единственная уважительная причина для изменения кода – адаптация под новые браузеры, но публичные методы при этом не должны никак меняться.
Программирование становится жертвой маркетинга. Нам обещают волшебную кнопку, которая решит все наши проблемы. Только плата за это, что многие подсаживаются на это и больше не способны раскладывать сложное на компоненты, отделять зёрна от плевел. Использую ли я фреймворки? Да, когда нужно создать продукт, который не нужно будет потом поддерживать. Но полное самоубийство использовать их в сервисе, который будет жить и развиваться хотя бы 1-2 года. За это время вы напишите кода гораздо больше, чем включает в себя весь фреймворк, и многократно столкнётесь с его ограничениями. То время, которое вы потратите на написание костылей и исправление универсальных вещей под себя, вам с лихвой хватило бы на то, чтобы внедрить набор только нужных компонентов вместо неповоротливого фреймворка. Это не велосипедостроение, вы используете библиотеки, но комбинируете их по ситуации, а не единым предустановленным способом. В фреймворках тоже можно подключать расширения, но что если я хочу фетчить модели Backbone по своему API. Или вообще не фетчить. Или забирать из localStorage. А если там есть ещё сложная логика апдейтов в зависимости от даты и флагов. И после фетча нужно отправлять пул той же модели на другой сервер. Никогда не знаешь, какие могут возникнуть особенности. И в таких ситуациях использовать Backbone? Там будет 5% его функциональности, остальное — костыли и кастомная логика. В то же время, понимая архитектурные принципы, не сложно создать решение, которое максимально хорошо работает конкретно для этой задачи. И сделать его устойчивым к изменению требований, гибким.
Известно, что большую часть времени программист не печатает, а думает. А думать паттернами проектирования полезно для эффективности. Обычно я читаю публичные методы новых библиотек в поисках интересных архитектурных решений. Если реализация чего-то не понятна – могу посмотреть код, но как правило важны сами идеи. Например promises, реализуются за 10 минут, но каков эффект. Поэтому не учите фреймворки, учите архитектуру.
P.S.: Статья намеренно провокационная, есть во фреймворках и хорошее, но они культивируют невежество. Обидно, когда человек не может решить задачу без фреймворка и застревает в работе на дни и недели. На самом деле это просто, если обращать внимание на правильные вещи, на архитектурные решения, именно эту мысль хотелось донести. Надеюсь статья будет полезна, прежде всего начинающим, и описанный здесь подход сделает их гораздо более крутыми профессионалами в перспективе.