Это постоянная серия статей о решении проблем, созданная на основе материалов The Rithm Blog.

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

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

Стратегия № 2: Изучите конкретные примеры

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

Пример

Представьте, что вы на собеседовании и вас просят сделать следующее:

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

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

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

charCount(“aaaa”); // {a: 4}
charCount(“hello”); // {h: 1, e: 1, l: 2, o: 1}

Даже в этих простых примерах возникают уточняющие вопросы. Например, должно ли возвращаемое значение включать ключи для _каждого_ символа с нулевым количеством символов, которые не отображаются? Или он должен включать только счетчики, строго превышающие 1? В приведенном выше примере предполагается последнее, но это важная часть вывода.
2. Перейдите к более сложным примерам. Изучив несколько простых конкретных примеров, усложните задачу и посмотрите, сможет ли ваше понимание идти в ногу со временем. Этот процесс часто выявляет другие вопросы. Например, в приведенной выше задаче вы можете спросить, каким должен быть вывод для такого выражения, как

charCount(“Your PIN number is 1234!”)

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

charCount('')

Должен ли вывод быть пустым объектом? нулевой? Ошибка?
4. Изучите примеры с недопустимыми входными данными. Другой полезный класс пограничных случаев связан с рассмотрением того, что произойдет, если вы передадите неверные данные в проблему. Например, что произойдет, если вы поместите в charCount что-то, что не является строкой?

charCount(null) // what should this be?
charCount({key: “value”}) // what should this be?

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

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