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

Сила ошибок

Когда вы впервые начинаете программировать, наблюдение за ошибками или ошибками может показаться кошмаром, заставляя вас чувствовать, что у вас ничего не получается. Но поверьте мне, ошибки — неотъемлемая часть обучения. Каждое всплывающее сообщение об ошибке — это новый шанс учиться. Это подталкивает вас копнуть глубже, чтобы понять, как все устроено на самом деле. И когда вы так научитесь, вы запомните это надолго. Мы склонны вспоминать свои ошибки… поэтому я предлагаю вам соединить это угрызение совести (которое застревает в вашей памяти, потому что оно связано с чувством) с уроком, который запомнится надолго.

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

Все изменить

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

Изменение имен переменных

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

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

Чтобы пролить свет на этот подход, давайте рассмотрим фрагмент кода Python из гипотетического руководства:

В учебнике вы можете встретить такую ​​функцию:

def greeting(name):
  return f"Hello, {name}!"

В этой функции «имя» является описательным, но может быть неясным. Является ли «имя» именем, фамилией или полным именем? Если позже вы увидите переменную имени в другой части кода, вы можете не сразу понять, что она представляет и как с ней обращаться (например, если это фамилия, возможно, вы захотите добавить «мистер/миссис»).

Переименовав переменную во что-то более явное, вы можете избежать этой путаницы:

def greeting(full_name):
  return f"Hello, {full_name}!"

Теперь full_name ясно указывает, что мы ожидаем приветствовать полное имя человека. Это делает код более читаемым и понятным для ваших товарищей по команде и даже для вашего будущего разработчика (что может произойти позже в тот же день). Это небольшое изменение, но практика продуманного именования может значительно повысить ясность кода.

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

Изменение названий функций и их разделение

Вот пример неопределенной функции, которую я видел в учебнике:

function calculate(num1, num2) {
    let total = num1 + num2;
    let finalTotal = total + (total * 0.15);
    return finalTotal;
}

Как и в предыдущем примере, название функции «вычислить» не очень описательно и заставляет нас догадываться о ее назначении. Когда вы увидите в другой части проекта вычисление имени функции, вы не поймете, что она делает, пока не просмотрите ее. Выполняет ли он сложение, вычитание, сложные вычисления? Кроме того, не сразу понятно, что он также рассчитывает налог помимо суммирования двух чисел.

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

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

сначала нам нужна функция добавления чисел, поэтому подходящее имя будет:

function addNumbers(num1, num2) {
  return num1 + num2;
}

вторая функция добавляет налог, поэтому вполне понятно, что можно написать так:

function addTax(total) {
  return total + (total * 0.15); // Adding a 15% tax
}

Использование обеих функций вместе

let total = addNumbers(5, 10);
let finalTotal = addTax(total);

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

На мой взгляд, ясность всегда должна быть важнее краткости. Речь идет не о создании максимально короткого кода, а о написании кода, который легко понимать, отлаживать и поддерживать. Забавный факт об этих умных фрагментах кода Python/JavaScript, которые вы видите повсюду, обычно они не только нечитаемы, но и медленнее.

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

Я был в гуще разработки веб-приложения, все шло гладко, каждая функция работала так, как ожидалось. С довольным видом я решил, что пришло время аккуратно подстричь мой код, привести в порядок ненужные элементы и улучшить общую структуру. Именно во время этого сеанса подготовки я наткнулся на переменную с именем grid (знаю, очень изобретательно). Неожиданный гость, так как я не помнил, чтобы представлял его на вечеринке. Но вот он уже не просто потягивает пунш в углу, а активно участвует в танце, главный участник работы компонента.

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

В моей голове вдруг погасла лампочка. Мне интересно, может ли быть странным совпадением то, что переменная ‘grid’ и идентификатор элемента div имеют одно и то же имя? Я погуглил что-то вроде этого «имя идентификатора javascript такое же, как имя переменной». И о чудо, результаты поиска открыли область знаний, которую мне еще предстояло исследовать.

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

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

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

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

Для иллюстрации рассмотрим пример Python:

x = 10 # outer (global) variable
def some_function():
  x = 5 # inner (local) variable
  print(x) # will print 5

some_function()
print(x) # will print 10

В этом фрагменте x внутри some_function затеняет глобальный x. Таким образом, когда x печатается внутри функции, она выводит 5 благодаря тому, что локальная переменная затмевает глобальную. Но когда x печатается вне функции, она выводит 10, так как глобальный x доступен здесь.

Моя встреча с переменной сетки в JavaScript — это уникальный пример затенения переменных, когда глобальные переменные, созданные браузером для представления HTML-элементов с идентификаторами, могут быть затенены переменными JavaScript. Однако эта общая концепция затенения переменных широко распространена в языках программирования. Это показывает важность выбора четких и описательных имен для ваших переменных. Если бы я выбрал более подходящее имя, такое как mainGrid или containerGrid, я бы увидел проблему в том, что переменная нигде не определена, но я бы упустил прекрасную возможность узнать.

Другой? конечно. Вы когда-нибудь подвергались яростному гневу консоли, сталкиваясь с наводящим ужас малиновым заявлением: «______ — это не функция»? О, какая паника возникает во время первой встречи! Такое ощущение, что вы случайно взорвали кодовую бомбу, вызвав хаос.

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

Вы можете подумать: «Ничего страшного, я просто использовал не ту переменную, отсюда и ошибка». Верно, но из этой ситуации есть что почерпнуть. Вы должны спросить себя, почему вы не знали, с каким типом переменной вы работали. Если вы ожидали строку, как вы пришли к числовому типу? Или неопределенный? Или ноль?

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

Давайте посмотрим на простой пример:

let myVariable = 1234;
try {
  console.log(myVariable.toLowerCase());
} catch (error) {
  console.log(error); 
// logs: TypeError: myVariable.toLowerCase is not a function
}

В этом примере вы попытались использовать toLowerCase() для числа, что привело к ошибке TypeError. Эта ошибка может привести вас к изучению обработки типов JavaScript и пониманию того, как правильно проверять или утверждать типы перед попыткой выполнения операций. Таким образом, небольшая ошибка прокладывает путь к большой возможности обучения. Возможно, вы выбрали по ошибке номер телефона пользователя вместо адреса пользователя, такие вещи случаются постоянно. Есть много вещей, которые вы можете сделать, чтобы справиться с такими ситуациями, например, обработка ошибок и проверка, прежде чем пытаться что-либо сделать со строкой.

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

Последние мысли

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

Думайте об этом, как об игре в RPG. За каждое испытание, которое вы преодолеваете, каждую тайну, которую вы разгадываете, и каждую ошибку, которую вы исправляете, вы получаете очки опыта. Это все равно, что выполнить множество побочных квестов, прежде чем сразиться с финальным боссом (и в нашем случае с привередливым клиентом — шучу). Чем больше очков опыта вы наберете, тем более способным вы станете, готовым идти по извилистым дорогам программирования. Итак, в следующий раз, когда на вашем экране появится сообщение об ошибке, не уклоняйтесь. Примите это, анализируйте, извлекайте из этого уроки и выходите с другой стороны сильнее, мудрее и опытнее. Именно через эти удары и препятствия вы действительно становитесь опытным программистом.

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

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 💰 Бесплатный курс собеседования по программированию ⇒ Просмотреть курс
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу