Применение уроков программирования к проблемам реального мира
Мое жизненное путешествие намного длиннее, чем мое путешествие в коде, и все же временами я чувствую, что мое понимание последнего превосходит мое понимание первого. Жизнь обширна, прекрасна и непостижима. Код ограничен по объему и обязательно может быть разложен на отдельные части. Вы можете создать веб-приложение днем, но не существует основы для прототипирования отношений. Написать алгоритм O (log n) для поиска в массиве несложно, но такого алгоритма для поиска счастья не существует. Жизнь не является объектно-ориентированной, функциональной или декларативной - она не поддается классификации. Нет, жизнь и код - это не одно и то же, но это не значит, что мы не можем узнать что-то одно от другого.
За последние несколько лет я потратил огромное количество времени и энергии на создание кода. Я многому научился за это время, но то, что меня волнует больше всего, не имеет ничего общего с единицами и нулями. Теперь я знаю, что уроки кода есть у нас повсюду. Я хотел бы потратить некоторое время, чтобы вместе с вами пройти несколько из них. Если вы программист, возможно, они будут вам знакомы. А если нет, может быть, вы тоже захотите научиться программировать.
Жизнь и код - это не одно и то же, но это не значит, что мы не можем узнать что-то одно от другого.
Структурированное решение проблем
По сути, кодирование - это решение проблем. Некоторые проблемы являются большими, например, разработка нового программного обеспечения снизу вверх, а другие - небольшими, например, сортировка списка имен в алфавитном порядке. Проблемы различаются по масштабу и сложности, а также от того, что дает или не дает «решение», но ко всем из них применим один и тот же базовый подход. Это выглядит примерно так:
1. Develop a thorough understanding of the problem. 2. Identify expected inputs and outputs to the problem. 3. Draft test cases to validate your eventual solution. 4. Model any necessary data. 5. Develop an algorithm to address the problem. 6. Implement your algorithm. 7. Verify that your solution is correct and refactor as needed.
Цель такого структурированного решения проблем - абстрагироваться от специфических для языка деталей, чтобы вы могли сосредоточиться на том, что важно. Каковы фактические параметры проблемы? Какие факторы способствуют? Что представляет собой решение? Вы заметите, что в этот список не входят такие пункты, как «установить фреймворк Magic.js» или «загрузить библиотеку для решения проблем xyz».
Жизненные проблемы различаются по масштабу даже больше, чем проблемы кодирования, но элементы этого подхода по-прежнему поучительны. В качестве простого примера представьте, что лампа в вашей гостиной не включается. Что вы делаете? Ваша первая цель - разобраться в проблеме (есть ли отключение электроэнергии? Перегорел предохранитель? Не горит ли лампочка?). Затем вы разрабатываете тестовые примеры, чтобы проверить свое окончательное решение (включается ли лампа? Работает ли она в нескольких розетки? Работает ли он с несколькими лампочками?) Затем вы разрабатываете алгоритм (замените лампочку ... если это не сработает, попробуйте другую розетку ... если это не сработает, проверьте блок предохранителей ... и т. д.) Наконец, вы реализуете свой подход и проверяете выполнение условий тестирования.
Нашу воображаемую неисправную лампу можно назвать инженерной проблемой, и поэтому кажется естественным применить инженерный подход. Человеческие проблемы сложнее. Как вы определяете многочисленные и разнообразные входы и выходы человеческих эмоций? Как вы разрабатываете и тестируете решения для прочных отношений с супругом? Откуда вы знаете, что данная работа вам подходит? Важно, чтобы мы не делали вид, будто людей можно понять и обращаться с ними как с машинами (а они не могут); тем не менее, наш подход к решению проблем достаточно абстрактен, и мы все же можем кое-чему научиться.
Важно, чтобы мы не делали вид, будто людей можно понять и обращаться с ними как с машинами (а они не могут).
Возьмите вопрос о поиске подходящей работы. Как всегда, первая цель - понять проблему (что для вас «правильно»? Имеет ли значение зарплата? Важна ли поездка на работу?). Затем мы разрабатываем тестовые примеры для применения к кандидатам на вакансии (превышает ли зарплата ваши расходы? Является ли работа интересной? Правильно ли добираться до работы?). Оттуда мы выбираем подход (можете ли вы «протестировать» работу, выполнив ее на контракт на несколько недель? Можете ли вы поговорить с людьми, которые уже выполняют свою работу?) Разработка алгоритма поиска идеальной работы не является интуитивной (или, возможно, даже возможной), но систематическая методология решения проблем, по крайней мере, позволяет вам понять суть параметры проблемы. Только после того, как вы освоитесь со своим пониманием, вы даже попытаетесь реализовать подход.
Изоляция ошибок
Урок, тесно связанный со структурированным решением проблем, заключается в том, как изолировать и устранять ошибки. В коде что-то часто идет не так. Это общепринятая часть жизни программиста, что с первого раза мало что идет хорошо. Вы пишете программу в меру своих возможностей, используя вышеупомянутый подход к решению проблем, а затем проверяете ее на успешные результаты. В большинстве случаев ваши тесты терпят неудачу с первого раза. Отладка - это скорее норма, чем исключение.
Первым шагом к хорошей отладке является изоляция ошибочного фрагмента кода. Чтобы исправить ошибку, вам сначала нужно ее найти. Вы можете сделать это, установив точку останова, чтобы вы могли проверять значения в данной точке выполнения программы. Или, возможно, вы вызовете задействованные функции независимо, чтобы увидеть, не дает ли одна из них неожиданный результат. Это итеративный и экспериментальный процесс, требующий структурированного подхода. Хорошие программисты тратят значительное количество времени на отладку, потому что они знают, что небольшие ошибки, созданные на раннем этапе, но оставленные без внимания, неизбежно порождают более крупные, неприятные и более опасные ошибки позже. Вы подавляете маленьких жуков, чтобы вам не пришлось иметь дело с чудовищными радиоактивными жуками в будущем.
Отладка - важная часть кодирования. Изучая передовые методы отладки, мы признаем, что что-то может пойти и пойдет не так. И это нормально. В некотором смысле отладка - это проявление оптимизма, потому что помимо предположения о том, что что-то может пойти не так, есть уровень, предполагающий, что мы можем и найдем и исправим проблему. Почему мы не можем применить такое же отношение к другим аспектам нашей жизни?
В некотором смысле отладка - это проявление оптимизма, потому что помимо предположения о том, что что-то может пойти не так, есть уровень, предполагающий, что мы можем и найдем и исправим проблему.
В большинстве случаев люди склонны предполагать, что в их жизни все будет (или, по крайней мере, должно) идти хорошо. Это обнадеживающий настрой и один из определяющих аспектов нашего вида. Это неплохая вещь. Это позволяет нам совершать удивительные вещи, потому что мы верим, что они действительно возможны. Но когда что-то идет не так, а это неизбежно, мы часто оказываемся застигнутыми врасплох. Плохие вещи не просто случаются, они случаются с вами. Несчастье кажется очень личным. Но что, если в мире происходят плохие вещи только потому, что они случаются, и это нормально? Они не только случаются, но и у нас есть возможность их исправить. Мы смотрим на код таким образом - никто не говорит, что с произошла ошибка. Баги просто случаются.
Отладка по отношению к реальным жизненным проблемам не всегда может быть реалистичной (в конце концов, мы люди, и наши проблемы кажутся личными, потому что они личные), но это может быть полезной отправной точкой. В конечном счете, это отношение, которое помогает вам глубже понять свои потребности и устранить мешающие факторы (ошибки). Представьте, что вы находитесь в длительных отношениях, но чувствуете себя неудовлетворенным. В чем коренная причина вашего несчастья? Какая ошибка вызывает неожиданные или нежелательные результаты? Возможно, это какое-то фундаментальное разногласие в ценностях, которое вы и ваша вторая половинка не можете разрешить (или вообще никогда не говорили). Возможно, вы чувствуете себя недооцененным, потому что не проводите достаточно времени вместе. Возможно, проблема вовсе не в ваших отношениях, а в том, что несчастье в других сферах вашей жизни просто маскируется под проблему отношений. Возможных причин множество, но если вы не потратите время на выявление ошибок и не попытаетесь их понять, проблема будет только расти.
Абстракция
Работа на соответствующем уровне абстракции означает, что вы сосредотачиваетесь на действительно важных вещах. Когда вы слишком глубоко погружаетесь в механику того, как работает фрагмент кода, особенно на ранних этапах своего пути к программированию, вы рискуете перегружать себя ненужными деталями. И наоборот, когда вы работаете на слишком высоком уровне, вы рискуете не усвоить фундаментальные знания.
Уровень абстракции, который вам нужен, зависит от ситуации. Иногда вам не нужно точно знать, как работает данная функция, вам просто нужно знать, как ее использовать. Ясность - это цель хорошего кода, а ясность означает разные вещи для разных пользователей. Конечному пользователю программы не нужно знать, как она построена. Им просто нужно знать, как достичь своих конкретных целей, используя предоставленные им инструменты. С другой стороны, разработчик должен хорошо знать, как работает программа, которую он создает. Однако ей, вероятно, не нужно глубокое понимание конкретной реализации выбранного ею языка. Попытка заставить людей перейти на неправильный уровень абстракции не приносит им пользы и в конечном итоге приводит к нежелательным результатам.
Современные программы невероятно сложны и в своей работе используют целый ряд технологий. Попытка понять их все одновременно была бы сизифовой задачей. Вот почему мы разбиваем наши программы на легко усваиваемые части, чтобы не задохнуться от слишком большой сложности. Для этого нам сначала нужно найти правильный уровень абстракции, чтобы мы могли сосредоточиться на том, что имеет значение, и игнорировать остальное. Естественно, «правильный уровень» со временем смещается вверх и вниз, но компромисс между нашим желанием знать основы и нашей потребностью избавиться от умственного беспорядка является необходимой частью разработки программного обеспечения.
Какими бы сложными ни были современные программы, они далеко не так сложны, как социальные, философские и физические системы, составляющие «реальную жизнь». Точно так же, как ни один программист не может полностью понять тонкости каждой технологии, которая входит в их программы, ни один человек не может ожидать, что поймет все, что влияет на направление их жизни. Следовательно, абстракция - необходимое упражнение в понимании того, что для нас важно.
Какими бы сложными ни были современные программы, они далеко не так сложны, как социальные, философские и физические системы, составляющие «реальную жизнь».
Что это значит на практике? Это означает, что если у вас есть конкретная цель в жизни, ваш первый шаг - определить уровень абстракции, необходимый для достижения этой цели. Если ваша цель - научиться играть на пианино, вам, вероятно, не нужно знать точную частоту, с которой вибрируют отдельные струны после удара молотком. Однако вам нужно знать, где находится средний C, как читать музыку и какие элементы данного аккорда. Это ваш уровень абстракции. Пытаться изучить все остальное - это просто беспорядок, который наверняка отвлечет вас. Когда вы эксперт, вы можете беспокоиться о том, чтобы научиться настраивать пианино и выяснить, как именно они устроены. (И тогда вы станете лучшим пианистом, но попытки сделать это сейчас вам не помогут.)
Основы
Говоря о среднем C - пару слов об основах. Они имеют значение. Глубоко. Тот факт, что вы абстрагируетесь от умственного беспорядка, не означает, что вам следует искать простые решения. Если вы хотите хорошо изучить свое ремесло, вам нужно начать с основ. Это верно как для кодирования, так и для любого другого начинания, которое вы можете предпринять.
Я ни в коем случае не «эксперт-программист». Я не занимался программированием с тех пор, как вышел из утробы матери. Я по-прежнему многого не знаю (и всегда будет), но то, что я знаю, - это отличное понимание основ. Частично это касается синтаксиса языка, но более важными являются не зависящие от языка основы, такие как решение проблем, структуры данных, область действия и шаблоны проектирования. Вначале такой подход к обучению часто был довольно одиноким и разочаровывающим. Я хотел создавать вещи, а не возиться с кажущимися загадочными деталями того, как работает тот или иной язык. Но чем больше я узнавал, тем больше понимал, что эти детали - необходимый шаг к мастерству.
Теперь, когда я вырос в своем пути кодера, я трачу больше времени на игры с фреймворками и новыми модными библиотеками. Но мог бы я глубоко изучить Rails, если бы не знал, как работает система наследования классов Ruby? Смогу ли я воспользоваться преимуществами React, если бы я не понимал, как this
изменяется в JavaScript или что такое DOM и как ею можно управлять? Ответ на оба вопроса - «нет». Конечно, можно получить практические знания о любом современном фреймворке, не обладая обширной базой знаний, но на этом вы далеко не уйдете. Что еще более важно, понимание основ открывает мир возможностей. Это означает, что вы торгуете на основных принципах, а не на мелких уловках. У хорошего программиста не возникнет проблем с освоением новых языков и фреймворков, но для этого от него требуется применять фундаментальные знания в новых ситуациях (а не постоянно начинать с нуля).
Основы имеют значение в кодировании, и они также имеют значение в жизни.
Основы имеют значение в кодировании, и они также имеют значение в жизни. Если вы хотите научиться играть на фортепиано, не начинайте с Рахманинова. Если вы хотите научиться печь, четырехуровневый свадебный торт, вероятно, не должен быть вашим первым проектом. И если вы хотите иметь успешные отношения, вам сначала нужно научиться основам сочувствия.
Сочувствие
И это подводит нас к последнему уроку: сочувствию. Изучение эмпатии из холодного, бессердечного, механического кода - странная идея, но при более глубоком рассмотрении она кажется странно убедительной. Как мы уже говорили, люди - не машины (и к ним не следует относиться как к таковым), но обращение с ними требует определенного сочувствия. Как программисты, мы уделяем огромное количество времени пониманию того, почему наши программы делают то, что они делают. Вот почему мы изучаем основы. Вот почему мы изучаем решение проблем. Вот почему мы изолируем ошибки. Если вы не понимаете как ваша программа и почему она работает именно так, вам будет трудно предсказать что в конечном итоге произведет.
Компьютеры - нечеловеческие существа, и у них нет чувств, поэтому «сочувствие» может показаться неправильным словом; однако я бы сказал, что наши попытки понять, как работают программы, - это своего рода эмпатия. Это признание того, что если мы хотим предсказать результаты, мы сначала должны понять правила работы. Сочувствие к человеку не так уж и сильно. По своей сути сочувствие - это упражнение в понимании. Если вы хотите узнать причину, по которой человек делает то, что он делает, вам сначала нужно понять его точку зрения и мотивацию. Сочувствие - жизненно важная часть человеческих отношений, точно так же, как понимание того, как данный язык будет выполнять данный фрагмент кода, является жизненно важной частью программирования.
Сочувствие - жизненно важная часть человеческих отношений, точно так же, как понимание того, как данный язык будет выполнять данный фрагмент кода, является жизненно важной частью программирования.
Реальная жизнь дает много возможностей для сильных эмоций. Нас постоянно бомбардируют гнев, страсть и волнение других людей. И мы тоже много бомбардируем. Когда мы сталкиваемся с этим в реальном мире, нашей первой реакцией слишком часто бывает недоумение, особенно если мы не согласны с тем, что говорит или делает другой человек. Как они могли в это поверить ?! спрашиваем мы себя. Но разве не похоже, что они задают себе то же самое, только в другом направлении? В конечном итоге это проблема сочувствия. Мы не нашли времени, чтобы понять фундаментальные убеждения и опыт, которыми руководствуется другой человек, поэтому мы не можем надеяться понять его действия. И все же, как программисты, когда программа дает неожиданный результат, наша первая реакция - углубить наше понимание, чтобы мы могли добиться лучших результатов в будущем. Так должно быть и в реальной жизни.
Кодекс - не идеальная замена жизненной практике. Однако есть поразительное сходство. В программировании мы применяем разумные инженерные методы, потому что знаем, что они дают превосходные результаты. Возможно, нам стоит применить аналогичные методы в жизни. Решение проблем, абстракция, внимание к основам и сочувствие - все это идеи, которые можно и нужно применять в широком смысле. Задача состоит в том, чтобы знать, когда и как их применять, и избежать отвлечения внимания и разочарования, которые приходят с временными неудачами.
Я многое узнал о жизни из кода не потому, что считаю, что можно относиться к жизни как к машине, а потому, что я понимаю, что методы критического мышления при хорошем кодировании могут помочь мне решать проблемы повсюду.