Принято считать, что программирование является каким-то очень сложным занятием, требующим особого склада ума и высокого уровня подготовки в области математики. При беглом взгляде на исходный код среднестатистический человек даже не попытается его понять, а программисты-новички начинают нервничать при мысли, что им предстоит с этим кодом немного поработать.
Уяснить следует одно: код пишут люди, так что природного ограничения интеллектуальных возможностей, необходимых для написания чистого и работающего кода, не существует. Ведь даже на курсы по основам программирования практически все приходят с одинаковым уровнем знаний.
Сложное на вид не так уж сложно на практике
Конечно, встречаются задачи, которые не решить без глубоких знаний математики; речь идет о разработке алгоритмов для игровых движков, драйверов или операционных систем. Но что касается большинства прикладных программ, то, чтобы понять, что и как в них работает, тройки по математике будет достаточно.
Хорошо. Но исходный код все равно продолжает казаться сложным!
В нем много непонятных слов и символов, которые идут в определенном порядке. А есть ли сложность еще? Пожалуй, только структура кода, но об этом позже.
Практически любой язык программирования (ЯП) имеет логические и циклические конструкции, логические и арифметические операторы, а также зарезервированные слова (их обычно немного). Все это составляет основу синтаксиса конкретного ЯП. Встроенные функции расширяют возможности языка, но не являются его синтаксической частью. Имена переменных и пользовательских функций программист придумывает самостоятельно.
Сложность восприятия кода преувеличена. Большинство слов являются именами, которые определяет программист, то есть имена могут быть какими угодно. А в основу синтаксиса входит не так уж и много предопределенных имен.
Простой человек пытается воспринять код целиком, так же, как он привык воспринимать рисунок или фотографию. Потерпев неудачу, тот, кому это понимание не очень-то и нужно, просто закрывает текст программы и переключается на что-то другое. Тот, кому необходимо понять, как работает программа, начинает паниковать (например, так реагируют студенты).
Но компьютер не ставит перед собой непосильной задачи — он считывает код построчно. Так, принято, что одна строка кода — один оператор, выполняющий простейшее действие с данными. После его выполнения считывается следующая строка и т. д. А понять, что делает один оператор, может практически любой адекватный человек.
Получается, изучив синтаксис языка, что несложно, любой человек может понять, какую функцию выполняет любая строчка кода. Если в исходном тексте 10 000 строк, то изучить каждую — вопрос времени. Но код по-прежнему остается непонятным, мозг все равно пытается объять необъятное.
Что общего между деревом и кодом?
Теперь о главном. Любая работающая программа имеет древовидную структуру кода. С технической точки зрения она может и не иметь ее, но тогда это либо совсем маленькая программа, либо написана она в наихудших традициях. Во втором случае не стоит даже тратить время на ее изучение.
Древовидная структура кода предполагает, что есть ряд основных функций, имеющих высокий уровень абстракции, которые делают что-то глобальное. Например, функция регистрации пользователя. Она принимает в качестве параметров какие-то данные и в случае успеха возвращает логическое значение true (истина).
Но чтобы зарегистрировать пользователя, следует выполнить много промежуточных действий, например выяснить, не дублируется ли электронный адрес, все ли данные переданы на сервер, внести запись в базу данных и, наконец, уведомить пользователя об успешной регистрации.
Очевидно, что все промежуточные действия выполняются функциями с более низким уровнем абстракции. Другими словами, одна большая функция вызывает несколько малых. Глубина вызовов не ограничена. Таким образом, структура вызовов похожа на дерево или на ветку.
И конечно же, существует самая главная функция — то место, с которого программа начинает свой путь, своего рода точка входа. Но этой вершины может и не быть, в таком случае интерпретатор руководствуется порядком расположения вызовов функций в коде.
Так или иначе, для понимания кода необходимо искать вершину его структуры, затем двигаться вниз — от общего к частному. Именно так программисты и читают код. И изучать каждую строку вовсе не обязательно.