Перевод статьи «The Top Five Developer Skills That’ll Make You a Hero (Hint: Involves LEGOs)».

Программирование похоже на постройку чего-нибудь из блоков LEGO. Взять новенький набор LEGO и построить модель по инструкциям может любой разработчик. Это просто. По уровню необходимых навыков это напоминает порог вхождения в индустрию разработки: чтобы его перешагнуть, достаточно курсов программирования.
Но настоящие проекты разработки программ отличаются, здесь другой сценарий. Это скорее похоже на постройку огромного замка. Только вот его уже когда-то построили без вас. А потом кто-то его пнул, и замок развалился. Куски побольше вроде как держатся, но более мелкие части распались, некоторые и вовсе исчезли.
Вам дают коробку, где собраны все выпавшие части, только вот там намешаны также тысячи кусочков из других наборов. И инструкций, конечно же, больше нет. Чтобы представить, как должен выглядеть замок, можно полагаться только на картинку.
Вот теперь задача становится интересной! Давайте посмотрим, как можно повысить эффективность работы в таких условиях.
1. Смиритесь с неизвестностью

Первый шаг в каждой задаче разработчика — понять, что нужно сделать. Это кажется очевидным. Но чем больше задача, тем больше в ней неизвестных переменных. Так что это подходящий момент, чтобы прояснить ожидания.
Если вы даже понятия не имеете, с чего начать, нет смысла слишком долго раздумывать. Начните с определения ключевых элементов, которые вам нужны. Затем обдумайте все снова. Если кто-то на этом этапе просит назвать сроки работы, честно скажите, что вы не знаете некоторых частей системы или не понимаете их. Это нормально.
Подумайте о таких платформах, как Facebook, Netflix или Oracle. Или о любом другом крупном коммерческом ПО. Довольно мало людей понимают их полностью. И эти люди либо сами их создавали, либо проработали над этими системами несколько лет. Так что, для начала, не вините себя за то, что чего-то не знаете. И, что даже более важно, просто смиритесь с тем фактом, что всего вы и не будете знать.
Опытные и продуктивные разработчики не обязательно лучшие кодеры. Но они лучше других справляются с определением того, что нужно делать. А также лучше других выбирают правильные стратегии работы с неизвестными.
Аналогия с LEGO
Представьте, что вам нужно отстроить замок. Скажем, кто-то дает вам картинку замка и коробку с элементами и спрашивает, сколько времени у вас уйдет на постройку. На такой вопрос нет лучшего ответа, чем «Я пока не знаю. Давай я начну и посмотрю, что смогу сделать за день или два».
Элементарный подход к такой задаче в стиле боязни неизвестных состоит в раскладывании всех элементов из коробки на полу. Вы распределяете их на кучки по цвету и форме, а затем смотрите на картинку и пытаетесь составить в уме схему сборки.
Этот подход не слишком эффективен. Во-первых, если замок слишком велик, вы можете никогда не закончить процесс разборки элементов. Во-вторых (и это главное), так вы не сможете оценить свой прогресс. Может, вы на правильном пути, а может, и нет. У вас нет никакой обратной связи.
Другой подход состоит в том, чтобы начать строить замок. По мере продвижения вы узнаете, легко ли находить нужные кусочки. Также вы поймете, показаны ли на картинке все детали, или конструкция куда более сложная, чем кажется.
Исходя из всей этой информации, вы сможете более обоснованно делать предположения в отношении времени и усилий, необходимых для завершения работ. И в отношении того, стоит ли вообще этим заниматься.
Если вам нужно собрать замок к завтрашнему утру, может, будет лучшим решением сходить в магазин и купить новый набор с инструкциями. Возможно, принимать подобные решения вне вашей компетенции, но проблемы не всегда решаются при помощи кода.
2. Смиритесь с компромиссами

Разработчиков часто хвалят за внимание к деталям. Подобные требования в том или ином виде встречаются в во всех объявлениях о вакансиях. И это, конечно, хорошо. Но не стоит путать внимание к деталям с упрямством и перфекционизмом.
В начале работ над большой задачей нужно определить две ее версии. Первая это самый минимум, необходимый, чтобы убедиться: все будет работать именно так, как вы задумали.
Я называю это «горизонтальной» работой. Каждая часть вашей большой задачи это вертикаль. Чтобы получить первые результаты, не обязательно углубляться. Сначала сфокусируйтесь на основном сценарии или use case, а дальше пляшите уже от него.
В первой версии можно отказаться от следующих вещей:
- обработки ошибок,
- edge cases,
- чистого кода,
- конфигурации.
Не думайте обо всем этом. Просто пишите код в том виде, в каком он вылетает из-под кончиков пальцев. Таким образом вы довольно быстро разработаете нужный функционал. Но на переход от этой первой упрощенной версии к финальной, безусловно, уйдет много времени. Так в чем же смысл?
Дело в том, что это более безопасный способ достичь прогресса. Вам нужно проверить ваши допущения. А делая это на практике, вы узнаете больше, чем путем долгих раздумываний.
Это тот же принцип, который применяется при создании минимально жизнеспособных продуктов в бизнесе. Дополнительный плюс этого подхода — вы сможете показать свою первую версию и получить фидбэк. Или задать вопросы. Кроме того, когда перед глазами есть уже существующий код, а не схема или основная идея, куда проще устраивать мозговые штурмы.
Аналогия с LEGO
Вы строите башню замка. На картинке стены башни сделаны из перемежающихся белых и серых кирпичей. В башне заперта принцесса, а на крыше сидит дракон.
Принцессу и дракона в коробке с элементами вы нашли, но на поиск серых и белых кирпичей уйдет вечность. Правильный подход — построить башню из кирпичей любого цвета, какие подвернутся под руку, и разместить принцессу с драконом. И добавить TODO: «Улучшить подбор блоков для стен».
Суть в идентификации проблемы: построить идеальную стену будет сложно. Давайте смиримся с этим фактом и двинемся дальше, чтобы обнаружить все прочие обстоятельства, о которых мы еще не знаем. Умение идти на компромисс защищает вас от ситуаций застревания.
И даже если вы так и не доберетесь до вашего TODO, вы всегда сможете сказать заказчику: «Вот замок. Мы знаем, что надо бы исправить стену башни, но в принципе все готово». Это куда лучше, чем «Мы сильно опаздываем, потому что понадобилась вечность на поиск подходящих кирпичей для башни. Но, как видите, башня превосходна и точно соответствует той картинке, которую вы нам прислали. А теперь мы возьмемся за остальной замок».
Важно: не путайте компромисс с неряшливостью.
Ключевые элементы башни это принцесса и дракон. Не суйте фермера в башню и кота на крышу. Это не компромисс. Это не сработает:)
3. Начинайте со внешнего мира

Есть много вещей, которые вы можете контролировать. И есть вещи, которые просто вне вашей власти. Я это усвоил путем набивания шишек в ходе работ над своими первыми задачами в качестве разработчика десять лет назад. Моим заданием была интеграция внешнего API и обработка данных. Времени была дана неделя. Собственно, времени должно было хватить даже такому неопытному парню, каким я был.
Вот что я сделал (не повторяйте моих ошибок!).
Утро понедельника. Я почитал документацию API, на это ушло 10 минут. Кажется, все просто. Я создаю тестовый набор данных и перехожу к написанию кода для их обработки. Когда сделаю, протестирую с реальным API.
Утро среды. Я почти закончил. Думаю, мой код чист и хорошо спроектирован (на самом деле нет). Теперь мне нужно только интегрировать API и я, вероятно, закончу работу даже раньше срока. Меня не оставляет ощущение, что я просто молодец.
Я быстро перехожу к части с API. Но что-то не так. У меня уходит целый день на повторную проверку всего. Я использую разные клиенты API. Никакого прогресса. День пролетел, и уже вечер среды.
Я застрял и чувствую, что я совсем не молодец.
Выхожу на работу в четверг и прошу коллегу помочь. Он говорит, что доступ к API может быть ограничен по IP и мне нужно связаться с компанией, чтобы наши IP добавили в белый список. Хорошо, направление есть.
Я отсылаю письмо в компанию, которой принадлежит API (примерно в 8 утра). Во мне живет дурацкая надежда на быстрый ответ и решение проблемы за несколько минут. В полдень я звоню в поддержку. Я объясняю свою проблему и пытаюсь как можно лучше донести, что это срочно (на самом деле нет).
Парень на другом конце провода поясняет, что помещение адреса в белый список занимает 1-2 дня. А вот теперь я в депрессии. 1-2 дня? Как это возможно? Моя задача самая важная в мире (только для меня, конечно), а они говорят мне 1-2 дня?!
Внезапно оказывается, что я уже не опережаю график, а отстаю. Я провалился. Я иду к боссу и говорю, что все запорол. Мне нужно было проверить API в понедельник утром и еще тогда запросить доступ, а уж затем писать код. Босс усмехнулся и сказал, что да, так и нужно было поступить.
Наконец, в пятницу я получаю доступ и мне приходится работать допоздна. Я дорабатываю свой код, адаптируя его ко многим сюрпризам, связанным с данными API. Прощай, хорошо спроектированный, чистый код. Позже я буду оправдываться тем, что на приведение кода в надлежащий вид не было времени (на самом деле его должно было хватить).
Тогда, по своей наивности, я думал, что мне просто не повезло со всей этой ерундой с доступом, да и документация была плохая. Теперь я могу с уверенностью сказать, что это не было невезением. Это было обычным делом.
Урок заключается в том, что начинать надо с вещей, которые вы не можете контролировать. Делая какие-то допущения относительно окружения, проверяйте каждое. Проверка должна быть как можно более ранней (проверяйте вручную и используйте недорогие методы).
Аналогия с LEGO
Представьте, что вы строите замок и все идет гладко. Вы уже сто раз перекопали свою коробку с деталями в поисках нужных блоков. И вас не покидает мысль, что вот огромного оранжевого дракона, который должен сидеть на крыше башни, в коробке как раз и нет.
Но вы игнорируете этот факт, стараясь сосредоточиться на имеющемся прогрессе. Это так по-человечески! Движение вперед более увлекательно, чем решение проблем. Но в итоге приходится признать, что дракона-то нет. Вам приходится сообщить заказчику, что в наборе не хватает существенной детали, причем сообщаете вы об этом довольно поздно. Это не хорошо.
Вместо этого следует сразу хвататься за мысль насчет дракона. Проверьте и убедитесь окончательно, что его нет. Поднимите этот вопрос, не откладывая в долгий ящик. Скажите заказчику: «В коробке нет дракона. Я не могу сделать дракона из кирпичей. Что будем делать?»
Люди просто на удивление нормально воспринимают информацию о проблемах, если сообщать о них достаточно рано. Информирование о проблемах на ранних стадиях открывает много путей для решения. «Можем ли мы продолжать работать, зная, что дракона нет?» «Можем ли мы купить дракона отдельно?» «В коробке есть динозавр, может, он заменит дракона?»

4. Тщательно продумывайте место врезки
Приступая к работе над новым функционалом существующей системы, всегда начинайте с определения того, как этот функционал будет вписываться в уже имеющийся код. Конечно, вы должны стараться следовать принципам SOLID и т. п., но ключевой момент куда проще всех этих принципов. Просто старайтесь делать поверхность соприкосновения как можно ниже.
Простой процесс четкого определения места врезки улучшит ваше решение. Он заставит вас ответить на ключевые вопросы:
- Как пользователи (или система) будут использовать мой код?
- Какие входные данные я буду получать?
- Какие данные я должен произвести?
Все это особенно важно, если вы еще не слишком знакомы с системой, с которой работаете. Это хорошая возможность исследовать неизвестное, прежде чем погрузиться в то, что уже знаете.
Также это облегчает подключение и отключение функционала. Можно использовать булево значение или более сложный механизм переключения.
Аналогия с LEGO
Предположим, вам нужно построить расширение для замка. Требования изложены на довольно высоком уровне, так что есть простор для творчества. Надо только не нарушить существующий замок.
Можно построить отличное расширение, но обнаружить, что нет места, где его можно было бы присоединить. В таком неудачном случае вам придется быстро менять свое расширение, чтобы как-то вписать его в замок.
Правильный подход заключается в том, чтобы сначала продумывать точку соприкосновения. Где должно располагаться это расширение по отношению к замку? Какими блоками его можно присоединить? Какой они формы? Соберите несколько блоков расширения и подсоедините их к замку. Проверьте, что соединение достаточно надежное. Вот теперь можно проявлять фантазию и создавать любое расширение.
5. Не увлекайтесь принципом DRY

«Не повторяйтесь» (Don’t Repeat Yourself, DRY) — это, пожалуй, самое простое из правил. Встретив дублирующиеся строки кода, вы их абстрагируете. Это может быть какой-то базовый класс, вспомогательный метод, да и вообще, все что угодно.
А что потом? Приходит новый человек и ему нужно изменить общий код, чтобы он охватывал большее количество случаев. Чтобы совладать с возрастающей сложностью, он добавляет параметры и условия. И вскоре 5 изначальных простых строк превращаются в 30 строк, и становится сложно понять, что вообще происходит.
Замена повторов кода на плохую читаемость это неудачная сделка.
В таком случае было бы лучше сохранить дублирование строк. В крайнем случае, их можно было бы изменить по отдельности.
В следующий раз, столкнувшись с выбором между абстрагированием и повтором, спросите себя: сколько раз вам случалось видеть, чтобы кто-то двигался в обратном направлении, ОТ абстракции? Например, удалял базовый класс и помещал общий код обратно в наследующие классы? Готов поспорить, что никогда такого не было.
Причина в том, что абстракции и шаблоны проектирования это круто и умно. И если они есть, значит, «для этого, наверное, была достойная причина». Поэтому, как только вы введете абстракцию, она, скорее всего, останется там навсегда.
Означает ли это, что абстракции вообще не следует использовать? Нет. Используйте их, когда это необходимо в связи с требованиями проекта. Например:
- «Мы хотим логировать каждый вызов этого метода с input-ми и output-ми».
- «Мы хотим логировать все HTTP-запросы с данными a, b, c».
- «При каждом создании пользователя нам нужно делать это и это».
Есть много других удачных примеров, когда абстрагирование это хорошо. Но обратите внимание, что это скорее технические требования, чем имеющие отношение к бизнесу (логирование, безопасность, аналитика и т. п.). Требования, побуждающие к абстрагированию, редко лежат в плоскости бизнеса.
Почему? Потому что бизнес ближе к реальному миру. А его мы не контролируем. Предположения, построенные в начале проекта, довольно часто вскоре рассыпаются. Не нужно слишком усложнять код из желания избежать дублирования.
Аналогия с LEGO
Аналогий нет. В LEGO нет концепции DRY.
Итоги
Работать умнее не значит писать лучший код. Это значит понимать, что нужно сделать, и осторожно пробираться к цели.
Масштабные и сложные задачи разработки связаны с неизвестностью. Примите это. Учитесь с этим работать.
Придерживаясь простоты и согласовывая ожидания относительно результатов с командой, боссом, заказчиком (в идеале — со всеми сразу), вы станете куда более продуктивным разработчиком.
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]