Как научиться задавать вопросы, проектировать системы и выявлять ошибки?

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


1. Знайте, где найти ответ

Просите, и дано будет вам; ищите, и найдете”.  —  Библия

Лучше всего человек учится во время столкновения с проблемами, особенно, когда успешно их решает  —  тезис справедлив и по части разработки программного обеспечения.

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

Быстро узнать ответ на вопрос может показаться несложным заданием: просто спросить у кого-нибудь? Но… Кого спросить? Как спросить? Когда спросить? Откуда вы знаете, что конкретный человек знает ответ? Достаточно ли у вас хорошие отношения с человеком, чтобы внезапно подойти к нему с вопросом  —  не покажется ли ему такое поведение некультурным с вашей стороны? Всё это  —  важные факторы, их нужно учесть перед тем, как задавать вопросы коллегам.
 
Может статься, что прямой разговор с коллегой  —  это не ваш стиль, зато вы мастер поиска ответа в Google или Яндекс. Как именно вы составляете поисковый запрос? Вы пользуетесь Stack Overflow? А Quora? Как найти именно то, что вам нужно? Какой совет, среди сотен других, заслуживает вашего доверия?
 
Что делать, если вы не можете решить проблему даже после дотошного поиска в сети Интернет? Пора сдаваться? Знаете ли вы, где разместить свой вопрос? 

Когда спрашивать на Stack Overflow, а когда  —  на Reddit? А как насчет Twitter, LinkedIn, Facebook

Ниже приведены несколько рекомендаций по этому поводу:

  • На Stack Overflow задавайте вопрос так, чтобы на него существовал полностью объективный ответ, не подлежащий обсуждению. Многие знают, что Stack Overflow  —  один из хороших источников, но используем ли мы его чаще всего?
  • Reddit больше подходит для обсуждения чего-то субъективного по своей природе, но готовьтесь к относительно грубым ответам.
  • Twitter, LinkedIn, Facebook  —  только если с вами дружат разработчики, способные помочь, в противном случае задавать там вопросы практически бесполезно.

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

2. Делите проблему на простые части

“Простое может оказаться самым сложным. Вам придется потрудиться, очищая свое мышление, чтобы сделать его простым”.  —  Стив Джобс

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

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

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

Существует два этапа отладки программного обеспечения:

  1. Определите шаги воспроизведения: если ошибка всегда контролируемо воспроизводима  —  отлично, переходите ко второму шагу. Если нет, то медленно изменяйте каждую переменную, чтобы выяснить, связаны ли они с проблемой.
  2. Определите первопричину: по одному за раз устраняйте несвязанные (не вызывающие проблему) компоненты в системе, таким образом медленно сокращается область внимания для отладки, что помогает быстрее определить корень проблемы.

Системная архитектура

Чтобы сконструировать автомобиль, нужно представить его как набор частей и мысленно собрать каждую из них, например, двигатель, колеса и так далее; затем каждая деталь двигателя тоже представляется в виде её частей  —  столько раз, сколько необходимо для проектирования оптимальной конструкции автомобиля как единой системы.
 
Точно так же и при разработке программного обеспечения: проект разбивается на более мелкие, но значимые части. Представлять систему в виде её составляющих  —  очень важный, необходимый навык со множеством преимуществ, например: он позволяет избежать беспорядочного спагетти-кода, облегчает сопровождаемость и масштабируемость программ.
 
К счастью, навык разделения системы на составляющие называется “системная архитектура”: представлены различные паттерны системной архитектуры, например, MVP, MVC, MVVM, Clean Architecture и многие другие. Отличные паттерны, им стоит следовать, однако часто и они  —  не оптимальное решение, ведь проблемы не следуют никаким шаблонам.

Используя паттерны в качестве ориентиров, следует модифицировать их под конкретные потребности.


3. Пишите сценарий, выбирая пути для развития

“В один пункт назначения ведёт множество дорог”.  —  Дебасиш Мридха

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

Варианты планирования разработки программного обеспечения

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

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

Откажитесь от предположений и уточните требования

Построение сценариев уточняет требования ещё до начала планирования; критичность мышления устраняет большинство неверных предположений.

Простой пример  —  вас попросили написать функцию, принимающую два заданных значения. Можно их просуммировать, с непосредственным предположением чего-то вроде 1 + 2 = 3, то есть на вход подаются два числа, а на выходе  —  одно целое число. Если заранее построить сценарий, то сразу придут в голову следующие вопросы:

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

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

Надежные сценарии тестирования

Еще одним преимуществом сценариев можно назвать возможность задать вопросы “что?” и “если?” в отношении конкретной функции, задумываясь о других, нетипичных возможностях:

  1. Что, если пользователи начнут применять функцию неожиданным, нестандартным образом?
  2. Могут ли входные данные оказаться нулевыми?
  3. А вдруг сервер не работает?

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


4. Выявляйте ошибки, отклонения от нормы

“Исключения делают правило сильнее”.  —  Венгерская пословица

Если бы все события на свете происходили так, как от них ожидается, то мир бы стал идеальным. Нет никаких неожиданностей, всё предсказуемо, нет ошибок или сбоев. Одни называют такой порядок идеалом, другие  —  наивностью.

Подумайте об исключении…

Знаете ли вы, что 99% ошибок в программных продуктах связаны с неожиданным срабатыванием потоков? Все ожидаемые срабатывания уже протестированы, они показали свою работоспособность: если ожидаемые действия потока генерируют ошибки, то за них ответственен конкретный сотрудник.
 
Поэтому, во время разработки приложения жизненно важными становятся навыки нестандартного мышления, для определения теоретически возможных незапланированных ситуаций в программе. Некоторые называют такой подход “защитное программирование”.
 
Рассмотрим несколько примеров:

  • Что делать разработчику игры для мобильных платформ, если игроку позвонят прямо во время увлеченной игры? Реализована ли возможность немедленного сохранения состояния игры?
  • Например, мобильное приложение разрабатывается для загрузки данных пользователями. Клиент едет в поезде: качество Интернет-соединения нестабильно. Как программа справится с таким нестандартным сценарием использования?

Навык выявления подобных потенциальных исключений помогает существенно улучшить качество программы. На самом деле, самая длинная часть любого кода имеет дело именно с граничными случаями (corner cases) и исключениями, так как стандартный бизнес-поток зачастую реализован проще, чем граничные случаи.

Устраните исключительные случаи

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

  1. Если вы работаете над простым игровым приложением, то не стоит разрабатывать программные ограничения игры для устройств с root-правами доступа.
  2. Покрытие старого граничного (крайнего) случая, вызванного некорректной работой Android SDK, касающегося только нескольких пользователей  —  также нерационально.

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


5. Расставляйте приоритеты

“Хорошие вещи случаются, когда вы правильно расставляете приоритеты”.  —  Скотт Каан

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

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

Знайте цель своего обучения и сосредоточьтесь

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

Многие выбирают мобильную разработку, но и в рамках мобильной разработки тоже вариативная специализация, например, iOS, Android кроссплатформенный фреймворк, такой как Flutter или React Native. Опять же, необходимо выбрать что-то одно.

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

Следовательно, программисту нужно понимать, что наиболее важно, что может подождать, а что никогда не понадобится.
 
Например, помимо изучения разработки под Android, можно уделить немного внимания изучению смежных предметов, таких как разработка под iOS, CI Processes и Script. В основную же очередь следует совершенствовать умения в работе с одной основной технологией, постепенно развивая компетенцию до охвата смежных с ней решений.

Разработка проекта и его планирование

Во время работы над проектом, стоит отметить те аспекты, требующие навык расстановки приоритетов, например:

  1. На выбор  —  два проекта: первый проект блокирует объекты из второго, самодостаточного проекта  —  очевидно, что сначала лучше поработать над первым проектом, если только разработка второго не критична по времени.
  2. Иногда, работая над проектом, программист понимает, что “застрял” в технических аспектах, не зная, как же решить проблему. Остановить проект, чтобы найти решение? Хороший пример  — критическая ошибка, требующая немедленного исправления: при отсутствии идеального решения, лучше использовать обходной путь, чем сидеть на месте.
  3. Определена функция с десятью возможными условиями  —  как протестировать все их комбинации? Воспользуемся методом грубого тестирования для полного покрытия, или же с умом выберем одну наилучшую комбинацию, гарантирующую достаточное покрытие?

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


6. Общайтесь и делитесь знаниями

“Учить — значит учиться дважды”.  —  Джозеф Жубер

В техническом обучении  —  два пути:

  1. Выучить то, что необходимо для работы; просто использовать эти знания для продвижения.
  2. Учиться, исследовать и делиться познаниями с другими людьми.

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

  • Когда мы делимся знаниями, то зачастую стремимся упростить идею, улучшая тем самым её понимание окружающими. Упрощение идеи поможет раскрыть её суть.
  • Легко обнаружить, что мы часто разбираемся в теме не так хорошо, как о себе думаем: все мы многое не знаем, и хотелось бы сначала лучше разобраться в технологии, чтобы потом уже обсудить её в коллективе.
  • Предвосхищая вопросы от других специалистов, хочется изучить технологию детальнее, что подталкивает к исследованиям, поискам недостающих знаний.
  • Вопросы читателей лучше раскроют те области, о которых вы не знали; комментарии аудитории дадут вам дополнительные знания, которые вы самостоятельно могли бы и пропустить.

Поговорка “Когда мы учим, то больше всего учимся” весьма актуальна в разработке программного обеспечения.


7. Наблюдайте и сравнивайте

“Всегда смотрите дальше того, что вы можете видеть”. — Марк Купер

“В школе не учат одному очень важному навыку: навыку наблюдения”. Именно через наблюдение человеческие существа учились с самого начала жизни: мы наблюдаем и сравниваем, так как сравнение  —  это еще один базовый аспект обучения.
 
Люди учатся лучше, когда сочетают наблюдение и сравнение.
 
Ниже приведены примеры того, как применить на практике навыки наблюдения и сравнения.

  1. Работая разработчиком приложений, весьма полезно, если мы проанализируем приложения от других разработчиков, сосредотачиваясь на организации пользовательского интерфейса. Наблюдая за доступным, мы понимаем, что осуществимо.
  2. Во время изучения языка программирования прошлый опыт позволяет сравнить плюсы и минусы разных языков, помогая принять лучшее решение по выбору технологического стека для нового приложения.
  3. Иногда функция недоступна на какой-либо платформе, но, наблюдая за тем, как работают другие платформы, можно создать что-то новое. Посмотрите, как за годы работы расширился функционал Android и iOS, с каждым днем они становятся все более похожими друг на друга.

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


Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Elye: 7 Techniques To Sharpen Your Technical Skills as a Developer

Предыдущая статьяХватит использовать Fetch API в JavaScript
Следующая статья5 способов выйти из вложенного цикла в Python