Представьте это. Вы идете в хозяйственный магазин, чтобы купить молоток. Не супермолот. Конечно, ничего подобного Тору не было бы. Клерк выслушивает ваш вопрос, некоторое время роется в задней части, затем возвращается с большим четырехфунтовым швейцарским армейским ножом с 27 различными возможностями. Среди прочего, он оснащен иглой для заправки нити, подъемником для зубов и щипцами для завивки ресниц. Молоток, который вы ожидали получить, стоит 10 долларов, швейцарский армейский нож стоит 270 долларов. Я посчитаю за тебя. Это в 27 раз дороже ожидаемого молотка. Продавец с большим энтузиазмом пытается оправдать стоимость, говоря: "Его также удобно забивать молотком, потому что он тяжелый и достаточно прочный для большинства гвоздей". Но ты хотел молоток всего за 10 баксов!

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

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

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

Теперь, прежде чем вы преждевременно перейдете в раздел комментариев, обвиняя меня во всех викингах или называя меня пуристом, который ненавидит плагины и хочет изобретать велосипед весь день, каждый день — придержите своих лошадей. Я абсолютно не против плагинов. Slick.js по сей день является одним из моих любимых.

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

Противоречит принципу KISS

Уму непостижимо, что каждый раз, когда упоминается принцип программирования, это почти всегда СУХОЙ принцип (не повторяйтесь). И знаешь, что? Конечно, я понимаю. Написание одного и того же материала снова и снова, копирование и вставка материала отсюда в другое место порождает много технического долга. Тем не менее, о чем, кажется, говорят намного меньше, так это о KISS (будьте глупее и проще), которую придумала Lockheed, и которую я хочу выделить здесь.

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

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

Запутанная собственность

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

Когда компонент создается изначально, становится очевидным, кто им владеет, но по мере его роста вероятность того, что другие команды будут его расширять, очень высока, и именно тогда он начинает запутываться. Если команда Б вносит изменения, можно утверждать, что право собственности неявно переходит от команды А к команде Б, но так ли это на самом деле? Команде А может показаться, что ей не совсем нравится то, как команда Б расширила компонент, и им также нужна пара дополнительных возможностей, поэтому они вносят изменения как в свой код, так и в код команды Б. Команда C приходит пару месяцев спустя и понимает, что компонент как есть удовлетворяет 90% их потребностей, поэтому они вносят некоторые свои собственные изменения, чтобы заполнить пробел в 10%, однако они будут претендовать на право собственности только на два дополнительных реквизита. они добавили. Представьте, что это будет продолжаться еще много месяцев с большим количеством команд.

Каждое изменение становится все более и более сложным в применении, компонент становится все более и более хрупким, и команды хотят все меньше и меньше владеть им. Менеджеры могут предложить использовать git fault для отслеживания владельцев, но оказывается, что половина людей, которые работали над кодом, с тех пор ушли или присоединились к другим командам. И вот оно. Компонент, который используется всеми, но никому не нужен. Ублюдочный компонент, в буквальном смысле!

Плохая новость для КИ

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

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

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

Головная боль при тестировании с высоким риском

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

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

  • модульные тесты терпят неудачу в неожиданных местах
  • модульные тесты не терпят неудачу в ожидаемых местах
  • интеграционные тесты терпят неудачу в неожиданных местах
  • интеграционные тесты не дают сбоев в ожидаемых местах
  • E2E-тесты терпят неудачу в неожиданных местах
  • E2E-тесты не дают сбоев в ожидаемых местах
  • неожиданные визуальные последствия остаются незамеченными

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

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

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

Кошмар обслуживания

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

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

Но что, если вам придется?

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

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

Я оставлю вас с одной мыслью. Мы установили, что в разработке программного обеспечения не существует такого понятия, как «идеал», так зачем же нам намеренно усложнять себе и всем остальным жизнь?

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

Если вам понравилась эта история, я выбрал еще несколько, которые могут вам понравиться! 😉









Знаете ли вы, что всякий раз, когда вы подписываетесь, чтобы стать участником Medium, мы, писатели, получаем свою долю? Вы получаете массу отличных статей, мы получаем кофе. Мне кажется, это честная сделка…

Аттила Вагоинженер-программист, редактор, писатель и иногда музыкальный критик. Прагматичный деятель, фанат Лего, пользователь Mac, крутой ботаник. Энтузиаст JS и Flutter. Сторонник доступности. Следуйте за мной в Twitter или присоединяйтесь к LinkedIn!