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

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

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

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

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

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

Проблема

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

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

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

Проверка одного параметра в одном фильтре не изменила связанные с ним результаты, но изменила результаты в других фильтрах. Это заставило меня осознать, что критерии каждого фильтра работают по схеме И, а между фильтрами — по схеме ИЛИ.

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

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

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

Что делать, если пользователь выбирает флажок-1 в фильтре-A, который имеет более 0 связанных результатов, затем он выбирает флажок-2 в фильтре-B, который снижает выбранные результаты флажка-1 до 0, поскольку последний теперь отключен, как пользователь снимет галочку?

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

Поверьте, я мог бы продолжать часами.

Список встряхивания

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

Вот как это выглядело:

  1. Вложенные флажки
  2. Глубоко вложенные флажки
  3. Производительность манипулирования данными
  4. Полные проверки
  5. Сохранить поиск
  6. Частичные проверки

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

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

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

Вот что я придумал:

  1. Вложенные чекбоксы -> Массив массивов ИЛИ матрица ИЛИ дерево
  2. Глубоко вложенные флажки –> Быстрая или отложенная загрузка узлов
  3. Производительность манипулирования данными - › Одно и то же представление для манипулирования данными и пользовательского интерфейса ИЛИ два разных представления
  4. Полные проверки -> Логический флаг в каждом узле
  5. Сохранить поиск -> Извлечь все полные проверки и сохранить их ИЛИ сохранить выбранные идентификаторы отдельно от структуры данных, представляющей флажки, чтобы их можно было легко сохранить.
  6. Частичные проверки → Дополнительный логический флаг ИЛИ использовать перечисление с тремя значениями

Пришло время снять шляпу дизайнера и взять шляпу инженера. Я встряхнул возможные решения по списку встряхивания. Прежде всего, я отбросил все недопустимые решения (например, не решил проблему, уступал альтернативе). Затем я отметил возможные решения, которые либо решают более одной проблемы, либо дополняют друг друга.

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

Вот список возможных решений после встряхивания:

  1. Вложенные чекбоксы -> Дерево. Наши флажки явно представляют собой деревья узлов. Информатика разработала массу алгоритмов и литературы, когда дело доходит до этой структуры данных. Я собираюсь получить массу вещей бесплатно, полагаясь на него.
  2. Глубоко вложенные флажки -> Узлы нетерпеливой или ленивой загрузки. Трудно сказать, давая размер набора данных. С одной стороны, активная загрузка облегчит задачу, но создаст дополнительную нагрузку на память. Нужно исследовать больше.
  3. Производительность манипулирования данными - › Два разных представления. Отделение представления данных от представления пользовательского интерфейса означает возможность оптимизировать и то, и другое при небольших затратах на добавление промежуточного шага преобразования.
  4. Полные проверки -> Логический флаг в каждом узле.
  5. Сохранить поиск -> Сохранить массив выбранных идентификаторов отдельно от дерева флажков. У них разные жизненные циклы, и, разделяя их, мы чтим это. Это позволяет использовать некоторые интересные приемы, учитывая шаг консолидации, упомянутый в 3. Например, снятие флажка означает удаление одного идентификатора из массива, очистка всех выбранных элементов означает очистку массива.
  6. Частичные проверки -> Enum с тремя значениями. Это делает невозможные состояния невозможными. С двумя логическими флагами у меня было бы четыре комбинации, хотя на самом деле допустимы только три: «проверено», «частично проверено», «непроверено».

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

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

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

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

Outro

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

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

Получайте последний контент по электронной почте лично от меня. Ответьте своими мыслями. Давайте учиться друг у друга. Подписывайтесь на мое PinkLetter!