Читать книгу Код. Культура, скомпилированная в байты - - Страница 15
ЧАСТЬ I: ФИЛОСОФИИ
Глава 3. Имена и метафоры
ОглавлениеПрограммист пишет код для машины, но читает его человек. И первое, с чем сталкивается читающий – имена. Имена переменных, функций, классов, модулей. За каждым именем стоит решение, за каждым решением – философия.
Выбор ключевого слова для объявления функции может показаться мелочью. Какая разница – def, func, fn или function? Машине действительно всё равно. Но человеку – нет. Имена формируют то, как мы думаем о коде. А конвенции именования – тот невидимый каркас, который держит программы читаемыми десятилетия спустя после их написания.
Выбирая имена, программист совершает акт классификации. Он решает, к какой категории принадлежит сущность, какие её свойства существенны, какие – нет. Имя переменной temp говорит: это временное, не обращай внимания. Имя customerLifetimeValue говорит: это важно, это центральная концепция бизнеса. Между этими полюсами – бесконечный спектр решений, каждое из которых отражает понимание программистом задачи.
3.1. Ключевые слова как концептуальный выбор
В 1967 году в Норвежском вычислительном центре Оле-Йохан Даль и Кристен Нюгор работали над языком для симуляции дискретных событий. Им нужно было слово для обозначения шаблона, по которому создаются объекты симуляции. Они выбрали class. Позже Даль вспоминал: «Мы выбрали термины class и objects of classes для нашей новой Simula. Понятие подкласса было особенно привлекательным для нас».
Это был не просто технический выбор. Слово «класс» несёт в себе идею классификации, таксономии, иерархии. Классы предполагают, что мир можно разделить на категории, что объекты принадлежат к определённым типам, что есть родовые понятия и видовые различия. Когда программист объявляет class Animal, он невольно начинает думать категориями Аристотеля.
Влияние этого выбора оказалось колоссальным. Simula повлияла на Smalltalk, Smalltalk – на C++, C++ – на Java, Java – на C#, C# – на всё остальное. Термин «класс» стал настолько привычным, что программисты перестали замечать метафору, которую он несёт. Но метафора продолжает работать. Иерархии наследования, которые программисты строят в объектно-ориентированных языках, отражают таксономическое мышление, заложенное в самом слове.
Альтернатива – struct. В языке Си структура – это просто способ группировки данных. Никакой иерархии, никакого наследования, никакого поведения. Данные и только данные. Когда Деннис Ритчи в 1972 году выбирал это слово, он думал о памяти, о байтах, о том, как данные расположены физически. Структура – это карта участка памяти, не более того.
Си создавался для написания операционных систем. Ритчи и Томпсон переписывали Unix, им нужен был язык, который позволял бы контролировать железо так же точно, как ассемблер, но был бы более выразительным. Структуры в Си – это не абстракции, скрывающие реализацию. Это способ сказать компилятору: вот здесь лежат эти байты, а вот здесь – эти. Программист, работающий со структурами Си, думает о памяти, не о таксономиях.
Go, созданный спустя почти сорок лет, сознательно отказался от классов в пользу структур. Роб Пайк и его коллеги не хотели, чтобы программисты мыслили иерархиями наследования. В Go нет слова class, есть только struct и interface. Это не ограничение языка – это философское заявление. Композиция вместо наследования. Поведение определяется тем, что объект делает, а не тем, от какого предка он происходит.
Пайк неоднократно объяснял это решение. Иерархии наследования в больших проектах становятся хрупкими и сложными для понимания. Изменение базового класса может сломать десятки наследников непредсказуемым образом. Go предлагает альтернативу: встраивание одних структур в другие и интерфейсы, которые определяются поведением, а не наследованием. Утиная типизация: если объект ходит как утка и крякает как утка – для Go он утка, независимо от того, кто его родители.
Ключевые слова для объявления функций демонстрируют тот же спектр философий. Python использует def – сокращение от define, определить. Нейтральное, техническое слово. Вы определяете функцию, как определяете переменную. Никакой особой церемонии. Это соответствует общей философии Python: минимум синтаксического шума, максимум ясности.
Гвидо ван Россум выбрал def под влиянием ABC – образовательного языка, созданного в том же голландском исследовательском центре CWI, где он работал. ABC был спроектирован для обучения программированию, и каждое его решение оптимизировалось для понятности новичкам. Python унаследовал эту заботу о читаемости, и def – часть этого наследия.
Go пишет func – то же сокращение, та же нейтральность, но ещё лаконичнее. Четыре символа вместо пяти. В языке, где простота возведена в принцип, каждый символ на счету. Go избегает сокращений ради сокращений, но func оправдан частотой использования. Функции в Go пишутся постоянно, и экономия одного символа на каждой из них складывается в заметное уменьшение визуального шума.
Rust идёт ещё дальше: fn. Два символа. Минимум возможного. Это не небрежность – это сознательный выбор для языка, где функции пишутся постоянно и везде. Когда пользователи спрашивали, почему не полное слово function, разработчики отвечали ссылками на традицию системного программирования, где краткость ценится выше явности. Rust наследует культуру Си и Unix, где имена короткие и ёмкие.