КулЛиб - Классная библиотека! Скачать книги бесплатно 

Ум программиста. Как понять и осмыслить любой код [Фелин Херманс] (pdf) читать онлайн

Книга в формате pdf! Изображения и текст могут не отображаться!


 [Настройки текста]  [Cбросить фильтры]
The Programmer’s Brain
FELIENNE HERMANS
Foreword byJon Sheet

11
MANNING
Shelter Island

УМ ПРОГРАММИСТА
КАК ПОНЯТЬ
и осмыслить
ЛЮБОЙ КОД
Фелин Хермане
Предисловие Джона Скита

Санкт-Петербург
«БХВ-Петербург»
2023

УДК 004.4
ББК 32.973.26-02
Х39

Хермане Ф.
Х39

Ум программиста. Как понять и осмыслить любой код: Пер. с англ. —
СПб.: БХВ-Петербург, 2023. — 272 с.: ил.

ISBN 978-5-9775-1176-6
Книга освещает практические основы когнитивистики для программистов.
Основные темы: осмысление и развитие чужого и собственного кода, изучение но­
вых языков программирования, мнемонические приемы для программистов, под­
держка кода в читаемом состоянии. Объяснено, как снижать когнитивную нагрузку
при работе программиста, как делать код логичным и понятным для себя и коллег.
Рассмотрены приемы именования функций, классов и переменных, подходы
к ведению репозиториев, совместной разработке и доработке кода.

Для программистов и других 1Т-специалистов
УДК 004.4
ББК 32.973.26-02

Группа подготовки издания:

Руководитель проекта
Зав редакцией
Перевод с английского
Компьютерная верстка
Оформление обложки

Олег Спеченко
Людмила Гауль
Кристины Черниковой
Ольги Сергиенко
Зои Канторович

Original English language edition published by Manning Publications
Copyright (c) 2021 by Manning Publications
Russian-language edition copyright (c) 2022 by BHV All rights reserved
Оригинальное издание на английском языке опубликовано Manning Publications
©2021 Manning Publications
Издание на русском языке © 2022 ООО «БХВ» Все права защищены

Подписано в печать 02 09 22
Формат 70x1001/i6 Печать офсетная Усл печ л 21,93
Тираж 1000 экз. Заказ № 5329
"БХВ-Петербург", 191036, Санкт-Петербург, Гончарная ул , 20

Отпечатано с готового оригинал-макета
ООО "Принт-М", 142300, М О , г Чехов, ул Полиграфистов, д 1

ISBN 978-1-61729-867-7 (англ.)
ISBN 978-5-9775-1176-6 (рус.)

© Manning Publications, 2021
© Перевод на русский язык, оформление ООО "БХВ-Петербург",
ООО "БХВ", 2023

Оглавление

Предисловие.................................................................................................................... 13

От автора.........................................................................................................................15
Благодарности.................................................................................................................17
О книге.............................................................................................................................19
Структура книги...................................................................................................................................... 19
Дискуссионный форум liveBook.........................................................................................................20

Об авторе......................................................................................................................... 21
Об обложке...................................................................................................................... 23
ЧАСТЬ I. ОБ УЛУЧШЕНИИ НАВЫКОВ ЧТЕНИЯ КОДА................................ 25
Глава 1. Определение вашего типа замешательства при кодировании............ 27
1.1. Разные типы замешательства в коде........................................................................................... 28
1.1.1. Первый тип замешательства — недостаток знаний..................................................... 29
1.1.2. Второй тип замешательства — недостаток информации........................................... 29
1.1.3. Третий тип замешательства — недостаток вычислительной мощности.................30
1.2. Различные когнитивные процессы, влияющие на процесс кодирования........................... 31
1.2.1. Долговременная память и программирование.............................................................. 31
Программа на APL с точки зрения долговременной памяти..................................... 32
1.2.2. Кратковременная память и программирование............................................................32
Программа на Java с точки зрения кратковременной памяти................................... 32
1.2.3. Рабочая память и программирование............................................................................. 33
Программа на BASIC с точки зрения рабочей памяти................................................ 33
1.3. Совместная работа когнитивных процессов............................................................................. 34
1.3.1. Краткое описание того, как когнитивные процессы взаимодействуют
друг с другом.................................................................................................................................. 34
1.3.2. Когнитивные процессы и программирование............................................................... 35
Выводы.................................................................................................................................................... 37

Глава 2. Скорочтение кода.......................................................................................... 39
2.1. Быстрое чтение кода.................................................................................................................... 40
2.1.1. Что только что происходило в вашем мозге................................................................. 41
2.1.2. Перепроверка воспроизведенного кода......................................................................... 42
Вторая попытка воспроизведения кода......................................................................... 43

2.1.3. Перепроверка воспроизведенного................................................................................... 44
2.1.4. Почему читать незнакомый код так сложно..................................................................44
2.2. Преодоление лимитов памяти..................................................................................................... 45
2.2.1. Сила чанков......................................................................................................................... 45
Чанки кода.......................................................................................................................... 48
2.2.2. Опытные программисты запоминают код лучше начинающих программистов...... 48
2.3. Вы видите намного больше кода, чем можете прочитать...................................................... 49
2.3.1. Иконическая память.......................................................................................................... 50
Иконическая память и код................................................................................................ 51
2.3.2. Это не то, что вы помните; это то, как вы запоминаете............................................. 51
Как написать код, который можно разделить на чанки............................................. 52
Используйте паттерны проектирования........................................................................ 53
Пишите комментарии........................................................................................................ 54
Оставляйте «маячки»........................................................................................................ 55
2.3.3. Применяйте чанки..............................................................................................................58
Выводы.................................................................................................................................................... 59

Глава 3. Как быстро выучить синтаксис................................................................. 61
3.1. Советы по запоминанию синтаксиса......................................................................................... 62
3.1.1. Отвлечение снижает производительность..................................................................... 62
3.2. Как быстро выучить синтаксис с использованием карточек................................................ 63
3.2.1. Когда использовать карточки.......................................................................................... 64
3.2.2. Расширяем набор карточек...............................................................................................64
3.2.3. Убираем ненужные карточки........................................................................................... 64
3.3. Как не забывать информацию..................................................................................................... 65
3.3.1. Почему мы забываем......................................................................................................... 65
Иерархия и сеть.................................................................................................................. 66
Кривая забывания............................................................................................................... 66
3.3.2. Интервальное повторение................................................................................................. 67
3.4. Как запомнить синтаксис надолго...............................................................................................69
3.4.1. Два способа запоминания информации......................................................................... 69
Уровень хранения............................................................................................................... 69
Уровень воспроизведения................................................................................................ 69
3.4.2. Просто увидеть недостаточно.......................................................................................... 70
3.4.3. Воспоминания укрепляют память................................................................................... 70
3.4.4. Укрепление памяти путем активного мышления......................................................... 71
Схемы................................................................................................................................... 72
Проработка для запоминания концепций программирования..................................73
Выводы.................................................................................................................................................... 74

Глава 4. Как читать сложный код............................................................................. 75
4.1. Почему так тяжело понимать сложный код..............................................................................76
4.1.1. Чем друг от друга отличаются рабочая память и кратковременная память........... 77
4.1.2. Типы когнитивной нагрузки и как они связаны с программированием..................78
Внутренняя когнитивная нагрузка при чтении кода...................................................78
Внешняя когнитивная нагрузка при чтении кода........................................................ 79
4.2. Способы снижения когнитивной нагрузки................................................................................ 80
4.2.1. Рефакторинг........................................................................................................................ 80

4.2.2. Замена незнакомых языковых конструкций.................................................................. 82
Лямбда-функции................................................................................................................. 82
Генератор списков.............................................................................................................. 83
Тернарные операторы........................................................................................................ 84
4.2.3. Синонимизация — отличное дополнение к дидактическим карточкам................... 85
4.3. Вспомогательные средства при перегрузке рабочей памяти.............................................. 85
4.3.1. Создание графа зависимостей.......................................................................................... 86
4.3.2. Использование таблицы состояний................................................................................. 88
4.3.3. Сочетание графов зависимостей и таблиц состояний................................................. 91
Выводы.....................................................................................................................................................93

ЧАСТЬ II. ПРОДОЛЖАЕМ ДУМАТЬ О КОДЕ..................................................... 95
Глава 5. Совершенствуем навыки углубленного понимания кода.................... 97
5.1. Роли переменных............................................................................................................................ 98
5.1.1. Разные переменные выполняют разные действия...................................................... 98
5.1.2. Одиннадцать ролей, охватывающие почти все переменные...................................... 99
5.2. Роли и принципы.......................................................................................................................... 101
5.2.1. Польза ролей...................................................................................................................... 102
Практические советы по работе с ролями переменных............................................ 103
5.2.2. Венгерская нотация.......................................................................................................... 104
Системная и прикладная венгерские нотации............................................................ 104
5.3. Углубленное понимание программ........................................................................................... 106
5.3.1. Понимание текста и понимание плана.......................................................................... 106
5.3.2. Этапы понимания программы........................................................................................ 106
Применение этапов углубленного понимания............................................................ 107
5.4. Чтение кода как обычного текста...............................................................................................109
5.4.1. Что происходит в мозге при чтении кода....................................................................110
Поля Бродмана................................................................................................................... 110
Показания фМРТ...............................................................................................................111
5.4.2. Если вы можете выучить французский, то сможете выучить и Python................. 111
Как люди читают код....................................................................................................... 113
Перед тем как читать код, программисты сканируют его........................................ 114
Начинающие и опытные программисты читают код по-разному........................... 114
5.5. Стратегии понимания текста, которые можно применить к коду.......................................115
5.5.1. Активация пассивных знаний......................................................................................... 116
5.5.2. Наблюдение........................................................................................................................ 116
5.5.3. Определение важности разных строк кода...................................................................117
5.5.4. Предположения о значении имен переменных........................................................... 118
5.5.5. Визуализация...................................................................................................................... 119
Таблица операций............................................................................................................. 119
5.5.6. Постановка вопросов........................................................................................................ 120
5.5.7. Резюмирование кода......................................................................................................... 121
Выводы................................................................................................................................................... 122

Глава 6. Совершенствуем навыки решения задач программирования......... 123
6.1. Использование моделей для размышлений о коде............................................................... 124
6.1.1. Преимущества использования моделей........................................................................ 124
Не все модели одинаково полезны............................................................................... 125

6.2. Ментальные модели.................................................................................................................... 126
6.2.1. Подробное исследование ментальных моделей..........................................................128
6.2.2. Изучение новых ментальных моделей..........................................................................129
6.2.3. Как эффективно использовать ментальные модели во время размышлений
о коде............................................................................................................................................. 130
Ментальные модели в рабочей памяти.........................................................................130
Точные модели работают лучше................................................................................... 131
Создание ментальных моделей исходной программы в рабочей памяти.............. 131
Ментальные модели в долговременной памяти........................................................ 132
Создание ментальных моделей исходной программы в долговременной
памяти................................................................................................................................. 133
Ментальные модели, одновременно хранящиеся в долговременной
и рабочей памяти.............................................................................................................. 134
6.3. Условные машины........................................................................................................................ 135
6.3.1. Что такое условная машина............................................................................................ 135
6.3.2. Примеры условных машин............................................................................................. 136
6.3.3. Разные уровни условных машин................................................................................... 137
6.4. Условные машины и язык........................................................................................................... 138
6.4.1. Расширяем набор условных машин.............................................................................. 139
6.4.2. Разные условные машины могут создать взаимно конфликтующие
ментальные модели...................................................................................................................... 140
6.5. Условные машины и схемы........................................................................................................ 141
6.5.1. Почему схема важна......................................................................................................... 141
6.5.2. Являются ли условные машины семантическими..................................................... 142
Выводы...................................................................................................................................................142

Глава 7. Заблуждения................................................................................................. 143
7.1. Почему второй язык программирования выучить намного проще, чем первый............. 144
7.1.1. Как увеличить шанс воспользоваться знаниями по программированию............... 146
7.1.2. Разные виды трансференции........................................................................................... 147
Осознанная и неосознанная трансференция............................................................... 147
Близкая и дальняя трансференция................................................................................ 147
7.1.3. Знания: добро или зло?.....................................................................................................148
7.1.4. Сложности трансференции............................................................................................. 149
7.2. Заблуждения. Ошибки в мышлении.......................................................................................... 150
7.2.1. Исправление заблуждений путем концептуальных замен........................................ 152
7.2.2. Подавление заблуждений................................................................................................ 152
7.2.3. Заблуждения о языках программирования.................................................................. 153
7.2.4. Предотвращение заблуждений при изучении нового языка
программирования....................................................................................................................... 155
7.2.5. Выявление заблуждений в новой базе кода................................................................. 156
Выводы...................................................................................................................................................157

ЧАСТЬ III. О ХОРОШЕМ КОДЕ............................................................................ 159
Глава 8. Совершенствуем навыки присваивания имен...................................... 161
8.1. Почему присваивание имен так важно................................................................................... 162
8.1.1. Почему присваивание имени так важно...................................................................... 162
Имена составляют существенную часть кодовой базы............................................. 163

Имена играют роль в обзорах кода............................................................................... 163
Имена — это самая удобная форма документации................................................... 163
Имена могут служить маячками...................................................................................163
8.1.2. Разные точки зрения на присваивание имен............................................................... 163
Хорошее имя можно определить синтаксически......................................................164
Имена во всей базе кода должны быть единообразны.............................................. 165
8.1.3. Важно грамотно подбирать имена.................................................................................166
Заключения о практике присваивания имен............................................................... 167
8.2. Когнитивные аспекты присваивания имен.............................................................................. 167
8.2.1. Форматирование имен поддерживает кратковременную память............................ 168
8.2.2. Понятные имена лучше закрепляются в долговременной памяти.......................... 169
8.2.3. Полезная информация в именах переменных............................................................. 170
8.2.4. Когда стоит оценивать качество имен.......................................................................... 171
8.3. Какие типы имен проще всего понимать..................................................................................172
8.3.1. Использовать аббревиатуры или нет?........................................................................... 172
Однобуквенные имена переменных.............................................................................. 173
8.3.2. Змеиный или верблюжий регистры?............................................................................. 176
8.4. Влияние имен на ошибки кода................................................................................................... 177
8.4.1. В коде с некачественными именами больше ошибок................................................ 177
8.5. Как выбирать хорошие имена..................................................................................................... 178
8.5.1. Шаблоны имен................................................................................................................... 178
8.5.2. Трехступенчатая модель Фейтельсона для хороших имен переменных................ 180
Трехступенчатая модель во всех деталях..................................................................... 181
Успех трехступенчатой модели Фейтельсона............................................................. 181
Выводы................................................................................................................................................... 182

Глава 9. Боремся с плохим кодом и когнитивной нагрузкой.
Две концепции..............................................................................................................183
9.1. Почему код с запахами кода создает большую когнитивную нагрузку............................. 184
9.1.1. Краткая информации о запахах кода.............................................................................. 184
Запахи кода на уровне метода........................................................................................ 186
Запахи кода на уровне класса......................................................................................... 186
Запахи кода на уровне базы кода...................................................................................187
Влияние запахов кода...................................................................................................... 187
9.1.2. Как запахи кода вредят мышлению.............................................................................. 188
«Длинный список параметров», сложные «Операторы переключения» —
перегрузка рабочей памяти............................................................................................. 188
«Всемогущий класс», «Длинный метод» — невозможно эффективно разбить
код на чанки....................................................................................................................... 189
«Клоны кода» — невозможно правильно разбить код на чанки............................. 189
9.2. Зависимость когнитивной нагрузки от плохих имен............................................................. 190
9.2.1. Лингвистические антипаттерны проектирования.......................................................190
9.2.2. Измерение когнитивной нагрузки................................................................................. 191
Шкала Пааса для когнитивной нагрузки...................................................................... 192
Измерение нагрузки по глазам....................................................................................... 193
Измерение нагрузки по коже.......................................................................................... 193
Измерение нагрузки по мозгу........................................................................................ 194
Запись биотоков мозга..................................................................................................... 194
Функциональная fNlRS-томография и программирование..................................... 195

9.2.3. Лингвистические антипаттерны и когнитивная нагрузка......................................... 195
9.2.4. Почему лингвистические антипаттерны вызывают замешательство..................... 196
Выводы...................................................................................................................................................197

Глава 10. Совершенствуем навыки решения сложных задач............................ 199
10.1. Что такое решение задач.......................................................................................................... 200
10.1.1. Элементы решения задач.............................................................................................200
10.1.2. Пространство состояний..............................................................................................200
10.2. Какую роль при решении задач программирования играет
долговременная память.............................................................................................................201
10.2.1. Решение задачи — это отдельный когнитивный процесс?...................................201
При решении задач вы используете долговременную память............................ 202
Вашему мозгу проще решить знакомые задачи..................................................... 202
10.2.2. Как научить долговременную память решать задачи............................................ 203
10.2.3. Два вида памяти, наиболее существенные при решении задачи......................... 203
Какие виды памяти играют роль при решении задач........................................... 204
Потеря знаний или навыков....................................................................................... 205
10.3. Автоматизация: создание имплицитной памяти..................................................................206
10.3.1. Имплицитная память с течением времени.............................................................. 207
Когнитивный этап........................................................................................................ 208
Ассоциативный этап.................................................................................................... 208
Автономный этап......................................................................................................... 209
10.3.2. Почему автоматизация помогает программировать быстрее.............................. 210
10.3.3. Улучшение имплицитной памяти..............................................................................211
10.4. Обучение на основе кода и его объяснения......................................................................... 212
10.4.1. Новый вид когнитивной нагрузки: соответствующая нагрузка.......................... 213
10.4.2. Примеры с решением на практике.............................................................................215
Работайте вместе с коллегой...................................................................................... 215
Используйте GitHub..................................................................................................... 215
Читайте книги или блоги об исходном коде........................................................... 216
Выводы.................................................................................................................................................. 216

ЧАСТЬ IV. О СОВМЕСТНОЙ РАБОТЕ НАД КОДОМ...................................... 217
Глава 11. Процесс написания кода.......................................................................... 219
11.1. Различные активности, выполняемые во время программирования............................... 220
11.1.1. Поиск............................................................................................................................... 220
11.1.2. Осмысление................................................................................................................... 221
11.1.3. Переписывание.............................................................................................................. 221
11.1.4. Наращивание.................................................................................................................. 222
11.1.5. Исследование................................................................................................................. 222
11.1.6. А как же отладка?......................................................................................................... 223
11.2. Программист отвлекся.............................................................................................................. 223
11.2.1. Задачи программирования нуждаются в «разогреве»........................................... 224
11.2.2. Что происходит после отвлечения............................................................................ 225
11.2.3. Как подготовиться к отвлечению...............................................................................225
Сохраняйте воображаемую модель.......................................................................... 225
Помогите своей проспективной памяти................................................................... 226
Определитесь с промежуточными целями.............................................................. 228

11.2.4. Когда отвлекать программиста.................................................................................. 228
11.2.5. Пара слов о многозадачности..................................................................................... 230
Многозадачность и автоматизация............................................................................230
Исследования многозадачности................................................................................. 231
Выводы................................................................................................................................................. 231

Глава 12. Проектирование и усовершенствование больших систем............... 233
12.1. Проверка свойств базы кода.................................................................................................... 234
12.1.1. Когнитивные измерения.............................................................................................. 234
Подверженность ошибкам.......................................................................................... 235
Согласованность........................................................................................................... 236
Размытость.....................................................................................................................236
Скрытые зависимости.................................................................................................. 237
Преждевременная фиксация решения...................................................................... 238
Вязкость..........................................................................................................................238
Поэтапное оценивание................................................................................................. 239
Выразительность ролей............................................................................................... 239
Близость соответствия................................................................................................. 240
Трудность мыслительных операций.......................................................................... 241
Вторичные обозначения.............................................................................................. 242
Градиент абстракции................................................................................................... 242
Наглядность....................................................................................................................243
12.1.2. Использование когнитивных измерений базы кода
для улучшения базы кода.......................................................................................................... 243
12.1.3. Проектные маневры и их плюсы и минусы.............................................................. 244
Подверженность ошибкам и вязкость...................................................................... 244
Преждевременная фиксация решения и поэтапное оценивание
против подверженности ошибкам............................................................................. 245
Выразительность ролей и размытость..................................................................... 245
12.2. Измерения и активности........................................................................................................... 245
12.2.1. Влияние измерений на разные активности............................................................... 245
Поиск............................................................................................................................... 245
Осмысление................................................................................................................... 246
Переписывание.............................................................................................................. 246
Наращивание................................................................................................................. 246
Исследование................................................................................................................. 247
12.2.2. Изменение базы кода под ожидаемые активности................................................. 247
Выводы.................................................................................................................................................. 247

Глава 13. Как ввести новых программистов в курс дела................................... 249
13.1. Проблемы процесса адаптации................................................................................................ 249
13.2. Различия между профессионалами и новичками................................................................. 251
13.2.1. Поведение новичка более подробно......................................................................... 251
Оригинальная концепция Пиаже............................................................................... 251
Концепция неопиажизма для программирования.................................................. 252
При изучении новой информации вы можете временно забывать
некоторые вещи............................................................................................................. 255
13.2.2. Разница между вещественным и абстрактным видением концепций.................255

13.3. Активности для улучшения процесса адаптации.............................................................. 258
13.3.1. Ограничение заданий до одной активности............................................................ 258
13.3.2. Поддержка памяти новичка........................................................................................ 259
Поддержка долговременной памяти: объяснение
релевантной информации........................................................................................... 259
Поддержка кратковременной памяти: ставьте небольшие
конкретные задачи....................................................................................................... 260
Поддержка рабочей памяти: используйте диаграммы.......................................... 261
13.3.3. Совместное чтение кода...............................................................................................261
Активация...................................................................................................................... 262
Определение важности................................................................................................262
Постановка предположений....................................................................................... 262
Наблюдение................................................................................................................... 262
Визуализация................................................................................................................. 263
Постановка вопросов................................................................................................... 263
Резюмирование..............................................................................................................263
Выводы.................................................................................................................................................. 263

Эпилог. Пара слов перед прощанием...................................................................... 265

Предметный указатель.............................................................................................. 267

Предисловие

Большую часть своей жизни я размышлял о программировании. Если вы сейчас
читаете эту книгу, то готов поспорить, что и вы тоже. Однако я никогда не тратил
много времени на размышления о том, как я думаю. Для меня всегда было важно
понятие о наших мыслительных процессах и то, как мы взаимодействуем с кодом
как люди, однако я не опирался ни на какие научные исследования. Давайте я при­
веду три примера.
Я — ведущий участник .NET-проекта Noda Time, предоставляющего набор типов
даты и времени, альтернативный встроенному в .NET набору. Это была отличная
возможность погрузиться в проектирование программных интерфейсов и особенно
в придумывание имен! Я увидел множество проблем, связанных с именами: они
звучат так, словно меняют уже существующее значение, хотя на самом деле воз­
вращают новое значение! Поэтому я постарался использовать такие имена, чтобы
код с ошибками при чтении выглядел неправильно. Например, тип LocaiDate с ме­
тодом PiusDays, а не AddDays. Надеюсь, что большинству С#-разработчиков данный
код покажется неправильным:
date.PiusDays (1) ;

В то время как следующий код будет более понятным:
tomorrow = today.PiusDays(1);

Сравните С методом AddDays .NET-Типа

DateTime:

date.AddDays (1);

Кажется, что это всего лишь изменение даты и ошибки тут нет, хотя этот вариант,
как и первый, неправильный.
Второй пример, более общего характера, также взят из проекта Noda Time. В то
время как многие библиотеки стараются (из лучших побуждений) выполнять всю
тяжелую работу за разработчика, мы хотим, чтобы пользователи Noda Time заранее
продумали код обработки даты и времени. Мы пытаемся заставить пользователей
однозначно сформулировать, чего именно они хотят достичь, а затем помогаем им
выразить это в коде.
И наконец, концептуальный пример: какие значения хранятся в переменных Java
и C# и что происходит, когда вы передаете аргумент методу. Мне кажется, что
большую часть своей жизни я пытаюсь опровергнуть концепцию того, что на Java
объекты передаются по ссылке. Похоже, что так и есть: я уже четверть века помо­
гаю другим разработчикам настраивать их мысленные модели.

14

Предисловие

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

С Фелиной Хермане я познакомился в 2017 году в Осло на конференции NDC, где
она выступала с презентацией «Programming Is Writing Is Programming». И моя ре­
акция в Твиттере говорит сама за себя: «Мне понадобится время, чтобы осознать
все это! Но я потрясен. Просто потрясен». Я минимум трижды (конечно, в разное
время) посещал эту презентацию Фелины и каждый раз узнавал что-то новое. На­
конец-то я получил научное объяснение тому, что пытался делать, а также узнал
и такие вещи, которые заставили меня изменить свой подход к работе.
Во время чтения этой книги у меня постоянно возникали реакции вроде «Я до этого
не додумался!» и «О, теперь я понимаю!». Подозреваю, что помимо очевидной
пользы от таких практических советов, как, например, применение дидактических
карточек, книга даст толчок, окажет более глубокое влияние. Возможно, вы будете
тщательнее обдумывать, куда именно в код нужно вставлять пустую строку. Воз­
можно, измените задачи, предлагаемые новеньким в команде, либо скорректируете
сроки выполнения этих задач. Возможно, мы станем по-другому объяснять концеп­
ции на платформе Stack Overflow.

Как бы там ни было, Фелина предоставила нам сокровищницу идей, которые мы
обдумаем в рабочей памяти, а затем сохраним в долговременной— ведь мысли
о мышлении вызывают привыкание!

Джон Скит,
менеджер по персоналу, Google

От автора

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

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

Благодарности

Я очень хорошо понимаю, как мне повезло, что я смогла закончить книгу по люби­
мой теме. Если бы не определенная череда событий, произошедших в определен­
ные моменты, моя жизнь была бы совсем другой и я не написала бы эту книгу. Де­
сятки самых различных встреч с замечательными людьми внесли неоценимый
вклад в эту книгу и в мою работу. Имена наиболее значимых я хочу назвать.
Марлиз Альдеверелд (Marlies Aldewereld) впервые познакомила меня с программи­
рованием и изучением языков. Мэрилин Смит (Marileen Smit) подтянула меня в
психологии, благодаря чему я написала эту книгу. Грег Уилсон (Greg Wilson) вер­
нул в тренды тему обучения программированию. Питер Наббе (Peter Nabbe) и Роб
Хогерворд (Rob Hoogerwoord) были для меня примером для подражания в сфере
обучения. Штефан Ханенберг (Stefan Hanenberg) дал мне совет, определивший на­
правленность моих исследований. Катя Мордаунт (Katja Mordaunt) открыла первый
в мире клуб чтения кода. Размышления Йевеллина Фалко (Llewellyn Falco) о зада­
чах привели в порядок мои мысли об обучении. Рико Хейберс (Rico Huijbers) был
моей поддержкой в моменты, когда я совершенно не знала, что делать.
Я также хочу поблагодарить людей из издательства Manning: Марьям Басэ (Marjan
Васе), Майка Стивенса (Mike Stephens), Тришу Лаувар (Tricia Louvar), Берта Бейтса
(Bert Bates), Михаела Батинича (Mihaela Batinic), Бекки Рейнхарт (Becky Reinhart),
Мелиссу Айс (Melissa Ice), Дженнифер Хаул (Jennifer Houle), Пола Уэллса (Paul
Wells), Джерри Кюха (Jerry Kuch), Рейчел Хед (Rachel Head), Себастьена Портебуа
(Sebastien Portebois), Кэндис Гилхули (Candace Gillhoolley), Криса Кауфмана (Chris
Kaufmann), Матко Хрватина (Matko Hrvatin), Ивана Мартиновича (Ivan Martinovic),
Бранко Латинчика (Branko Latincic) и Андрея Хофшусзера (Andrej Hofsuster) — за
то, что они взялись за работу, когда у меня были только наброски, и превратили их
во что-то понятное, интересное и легко читаемое.

А также всех рецензентов: Адама Качмарека (Adam Kaczmarek), Адриана Бэйертца
(Adriaan Beiertz), Алекса Риоса (Alex Rios), Ариэль Гаминьо (Ariel Gamino), Бена
МакНамара (Ben McNamara), Билла Митчелла (Bill Mitchell), Билли О'Каллагана
(Billy O’Callaghan), Бруно Соннино (Bruno Sonnino), Чарльза Лэма (Charles Lam),
Клаудию Мадертанер (Claudia Maderthaner), Клиффорда Тербера (Clifford Thurber),
Даниэлу Запату Риско (Daniela Zapata Riesco), Эмануэля Орижи (Emanuele Origgi),
Джорджа Онофрея (George Onofrei), Джорджа Томаса (George Thomas), Гилберто
Такари (Gilberto Taccari), Хэйма Рамана (Haim Raman), Жауме Лопеса (Jaume

18

Благодарности

Lopez), Джозефа Перения (Joseph Perenia), Кента Спиллнера (Kent Spillner), Ким­
берли Уинстон-Джексон (Kimberly Winston-Jackson), Мануэля Гонзалеса (Manuel
Gonzalez), Марцина Сэка (Marcin S$k), Марка Харриса (Mark Harris), Мартина
Кнудсена (Martin Knudsen), Майка Хьюитсона (Mike Hewitson), Майка Тэйлора
(Mike Taylor), Орландо Мендеса Моралеса (Orlando Mendez Morales), Педро Серомено (Pedro Seromenho), Питера Моргана (Peter Morgan), Саманту Берк (Samantha
Berk), Себастьяна Феллинга (Sebastian Felling), Себастьена Портебуа (Sebastien
Portebois), Саймона Чоке (Simon Tschoke), Стефано Онгарейо (Stefano Ongarello),
Томаса Хансена (Thomas Overby Hansen), Тима ван Дерзена (Tim van Deurzen),
Туомо Каллиокоски (Tuomo Kalliokoski), Унникришнана Кумара (Unnikrishnan
Kumar), Василе Бориса (Vasile Boris), Виктора Бека (Viktor Bek), Закари Бейела
(Zachery Beyel) и Чжицзюнь Лю (Zhijun Liu). Ваши предложения помогли мне сде­
лать эту книгу лучше!

О книге

Мозг программиста — это книга для программистов всех уровней, которые хотят
разобраться, как работает их мозг и как можно улучшить свои навыки и стиль про­
граммирования. В данной книге будут показаны примеры кода на разных языках,
включая JavaScript, Python и Java. Если вам удобно читать исходный код на языке,
который вы никогда не встречали, то вам не нужны серьезные знания какого-либо
из этих языков программирования.

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

Структура книги
Книга состоит из 13 глав, разделенных на четыре части. Главы следует читать по
порядку, так как все они связаны. Каждая глава содержит прикладные примеры
и упражнения, способствующие лучшему усвоению и закреплению полученного
материала. В некоторых случаях для выполнения упражнения вам потребуется по­
дыскать кодовую базу — так вы сможете работать с подходящим вам контекстом.
Вы также можете использовать полученные знания в вашей повседневной работе.
Я думаю, что эту книгу можно изучать долгое время вот с каким планом: сначала
вы изучаете главу, применяете упражнения из главы в своей практике программи­
рования, а затем переходите к изучению следующих глав:
□ В главе 1 рассматриваются три когнитивных процесса, которые играют роль при
программировании, а также рассматривается их связь с типами замешательства.
□ В главе 2 вы найдете советы о том, как быстро читать код и понимать его.
□ В главе 3 вы узнаете, как наиболее эффективно изучать синтаксис и концепции
программирования.

20

О книге

□ В главе 4 вы узнаете, как читать сложный код.
□ В главе 5 показаны методы, которые помогут глубже понять незнакомый код.
□ В главе 6 рассматриваются методы, которые «прокачают» способность решать
задачи программирования.
□ В главе 7 вы найдете советы о том, как избежать ошибок в коде и его понима­
нии.

□ В главе 8 вы узнаете, как выбрать подходящее имя для переменной.
□ Глава 9 посвящена признакам кода «с запахом» и лежащим в их основе когни­
тивным причинам.
□ В главе 10 рассматриваются более сложные способы решения трудных задач.
□ В главе 11 описывается процесс кодирования и исследуется разнообразие задач
программ ирования.

□ В главе 12 вы узнаете, как улучшить большие кодовые базы.
□ В главе 13 вы узнаете, как сделать процесс адаптации новых сотрудников менее
болезненным.
В данной книге вы найдете множество примеров исходного кода: и в пронумеро­
ванных листингах, и просто в тексте. В обоих случаях при написании исходного
кода используется моноширинный шрифт — так он бросается в глаза в обычном тексте.
Иногда код может быть выделен полужирным шрифтом — так показаны измене­
ния в коде, использовавшемся в предыдущих шагах в главе (например, при добав­
лении новой функции к уже существующей строке кода).

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

Дискуссионный форум liveBook
Приобретая книгу «Мозгпрограммиста», вы получаете бесплатный доступ к част­
ному веб-форуму Manning Publications, где вы можете оставить свои отзывы и ком­
ментарии о книге, а также задать технические вопросы и получить помощь от авто­
ра книги и других пользователей. Чтобы получить доступ к форуму, перейдите по
ссылке https://livebookmanning.com/book/the-programmers-braiii/discussion. Больше
о форумах Manning и правилах поведения на форуме можно узнать по адресу
https://livebook.manning.eom/#2/discussion.
Нашей обязанностью было создание уголка, где читатели могли бы вести содержа­
тельный диалог и друг с другом, и с автором. Вам необязательно ответят, так как
участие автора на форуме является добровольным (и не оплачивается). Тем не
менее можно задавать сложные вопросы автору!

Об авторе

Доктор Фелина Хермане — доцент Лейденского университета в Нидерландах, где
она проводит научные исследования языков программирования и методов обучения
программированию. Она читает лекции в академии учителей Амстердамского сво­
бодного университета, специализируясь на дидактике компьютерных наук, а также
преподает в средней школе Кралингена в Роттердаме.

Фелина является создателем языка программирования Hedy, предназначенного для
начинающих программистов, а также ведет подкаст Software Engineering Radio,
один из крупнейших интернет-подкастов о программном обеспечении.

Об обложке

Рисунок на обложке данной книги называется «Femme Sauvage du Canada», или
«Коренная жительница Канады». Изображение взято из коллекции костюмов раз­
ных стран Жака Грассе де Сен-Совера (1757-1810) под названием «Costumes civils
actuels de tous les peuples connus», изданной во Франции в 1788 году. Каждая ил­
люстрация была нарисована и раскрашена вручную. Показанное Грассе де СенСовером разнообразие напоминает нам о том, насколько города и регионы мира
были культурно обособлены всего лишь 200 лет назад. Изолированные друг от дру­
га, люди разговаривали на разных языках и диалектах. Встретив человека в городе
или в деревне, по одной лишь одежде можно было определить, чем он занимается
по жизни и где живет.

С тех пор манера одеваться сильно изменилась, а многие характерные признаки
регионов просто исчезли. Теперь очень сложно отличить жителей разных конти­
нентов, не говоря уже о городах или странах. Может быть, мы променяли культур­
ное разнообразие на разнообразную персональную жизнь — и уж точно на разно­
образную и быстро развивающуюся технологическую жизнь.
И когда одну книгу о компьютерах с трудом получается отличить от другой, изда­
тельство Manning демонстирует изобретательность компьютерного производства
с помощью обложек книг, которые основаны на богатом разнообразии региональ­
ной жизни 200 лет назад, описанном в книге Грассе де Сен-Совера.

Об улучшении
навыков чтения кода
Ч

Атение кода — основная часть программирования, однако не всегда даже опыт­
ные разработчики знают, как правильно это делать. Чтению кода не учат, и это
редко практикуется, а незнакомый код сбивает с толку. Первые главы этой книги
помогут вам понять, почему чтение кода — это сложно, и что можно сделать,
чтобы читать код было проще.

Замешательство — неотъемлемая часть программирования. Когда вы изучаете но­
вый язык программирования, фреймворк или какую-либо концепцию, новые идеи
могут напугать вас. Читая незнакомый код или собственный, но написанный вами
много лет назад, вы можете не понять, для чего он нужен или почему он написан
именно так. Когда вы приступаете к работе в новой сфере деятельности, то от но­
вых терминов и сленга у вас может получиться мешанина в голове.

Конечно, нет ничего странного в том, что первое время вы будете испытывать за­
мешательство — однако не стоит пребывать в этом состоянии больше необходимо­
го. Эта глава поможет вам распознать и определить ваше замешательство. Возмож­
но, вы никогда не задумывались об этом, но существует несколько способов впасть
в замешательство. Замешательство от незнания значения какого-то понятия при­
кладной области отличается от замешательства при разборе шаг за шагом сложного
алгоритма.
Разные типы замешательства относятся к разным когнитивным процессам. На
нескольких примерах программного кода мы подробно рассмотрим три типа заме­
шательства и объясним, что происходит в вашей голове.

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

28

Часть I. Об улучшении навыков чтения кода

1.1. Разные типы замешательства в коде
Любой незнакомый код сначала будет сбивать вас с толку, однако разные части од­
ного кода вы будете воспринимать по-разному. Давайте рассмотрим это на трех
разных примерах кода. Во всех трех примерах число N или п преобразуется в дво­
ичное представление. Первая программа написана на APL, вторая — на Java, а тре­
тья — на BASIC.
Уделите несколько минут подробному разбору этих программ. На какие знания вы
опираетесь? Чем ваши знания отличаются для каждой из программ? Возможно,
сейчас вы не сможете объяснить то, что происходит в вашем мозге, но я думаю, что
при чтении каждой из программ ваше восприятие отличается. В конце этой главы
будут представлены выводы, с помощью которых вы сможете обсуждать различ­
ные когнитивные процессы, происходящие в вашей голове при чтении кода.

Пример в листинге l.l — это программа на APL, преобразующая число п в двоич­
ное представление. Замешательство заключается в том, что вы можете не знать, что
такое т. Если вы не являетесь математиком из 1960-х, то вы, скорее всего, никогда
не работали на языке программирования APL. Этот язык был разработан специаль­
но для выполнения математических операций и на сегодняшний день практически
не используется.

2 2 2 2 2 Т п

Второй пример — это программа на Java, которая преобразует число п в двоичное
представление (листинг 1.2). Замешательство может быть вызвано незнанием рабо­
ты метода toBinaryString() .

public class Binarycalculator {
public static void mian(Integer n)

{

System.out.printIn(Integer.toBinaryString(n));
}
}

Третий пример— это программа на BASIC, которая преобразует число N в двоич­
ное представление (листинг 1.3). Замешательство связано тем, что вы не можете
отследить все шаги, выполняющиеся в ходе работы программы.

1 LET N2 - ABS

(INT

(N) )

2 LET B$ - ""
3 FOR N1 - N2 TO 0 STEP 0

Гпава 1. Определение вашего типа замешательства при кодировании
4

LET N2 = INT

5

LET В$ = STR$

6

LET N1 = N2

7

29

(N1 / 2)

(N1 - N2 * 2)

+ В$

NEXT N1

8 PRINT B$

9 RETURN

1.1.1. Первый тип замешательства — недостаток знаний
Теперь давайте разберемся в том, что происходит, когда вы читаете эти программы.
Сначала мы обратимся к программе на APL (листинг 1.4). Посмотрите, как про­
грамма преобразует число п в двоичное представление. Замешательство заключает­
ся здесь в том, что вы можете не знать, что означает т.

2 2 2 2 2 Т п

Я думаю, что большая часть читателей книги не знакомы с APL и не знают значе­
ние оператора т. Следовательно, замешательство в данном случае заключается
в недостатке знаний.

1.1.2. Второй тип замешательства —
недостаток информации
Во втором примере источник замешательства будет другим. Я предполагаю, что вы
знакомы с программированием, и даже если вы не эксперт по Java, вы сможете най­
ти соответствующие части программы. В этом примере показана программа на
Java, преобразующая число п в двоичное представление (листинг 1.5). В данном
случае замешательство может быть вызвано незнанием метода toBinaryStringO.

public class Binarycalculator {
public static void mian(Integer n)

{

System.out.printin(Integer.toBinaryString(n));
}

}

По имени метода можно догадаться о его назначении. Однако, чтобы полностью
понять, что делает код, вам нужно перейти к определению toBinaryStringO в дру­
гом месте исходного кода и продолжить чтение с того места. Следовательно, про­
блемой является недостаток информации. Информации о методе toBinaryStringO
нет, ее необходимо найти в коде.

Часть I. Об улучшении навыков чтения кода

30

1.1.3. Третий тип замешательства —
недостаток вычислительной мощности
В третьей программе, полагаясь на имена переменных и операций, вы можете
предположить, что делает код. Но если вы хотите отследить каждый шаг, то ваш
мозг не сможет справиться с этой задачей. Дело в том, что выполнение программы
на языке BASIC, преобразующей число N в двоичное представление, включает
в себя множество мелких шагов, которые вы не можете отследить. Если вам нужно
полностью понимать все шаги, то лучше использовать мнемоническое представле­
ние информации, например промежуточные значения переменных, показанные на
рис. 1.1.

1
2

3
4
5
6
7
8
9

LET N2
ABS (INT (N))
LET В$
О
FOR N1 = N2 ТО О STEP
LET N2 = INT (N1 / 2)
LET В$ = STR$ (N1 - N2 * 2) + В$
LET N1 = N2
NEXT N1
PRINT B$
RETURN
Рис. 1.1. Двоичное представление на BASIC

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

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

Гпава 1. Определение вашего типа замешательства при кодировании

31

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

Итак:
□ недостаток знаний = проблемы с долговременной памятью;
П недостаток информации = проблемы с кратковременной памятью;
□ недостаток вычислительной мощности - проблемы с рабочей памятью.
Эти три когнитивных процесса играют большую роль не только при написании ко­
да, но и во всей когнитивной деятельности, включая в себя (в случае программиро­
вания) написание кода, проектирование архитектуры системы и составление доку­
ментации.

1.2.1. Долговременная память и программирование
Первый когнитивный процесс, использующийся при программировании, — это
долговременная память. Долговременная память может хранить информацию
в течение длительного времени. Множество людей помнят события, происходив­
шие годы и десятилетия назад. Долговременная память играет большую роль во
всем, что вы делаете: при завязывании шнурков активизируется мышечная память,
которая автоматически запоминает последовательность действий, а при написании
бинарного поиска вы помните буквенный алгоритм, синтаксис языка программиро­
вания и то, как печатать на клавиатуре. В главе 3 подробно рассматривается ис­
пользование долговременной памяти, включая эти формы запоминания и способы
усиления данного когнитивного процесса.
В долговременной памяти хранится несколько видов информации, важной при про­
граммировании. Она может хранить воспоминания о том, как вы успешно приме­
нили какую-нибудь технику, значение ключевых слов Java, значение слов на анг­
лийском языке или тот факт, что константа maxint в Java содержит значение
2147483647.

Долговременную память можно сравнить с жестким диском компьютера, способ­
ным хранить информацию долгое время.

32

Часть I. Об улучшении навыков чтения кода

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

1.2.2. Кратковременная память и программирование
Другой когнитивный процесс, играющий большую роль в программировании, —
это кратковременная память. Ваша кратковременная память используется для
хранения поступающей информации в течение непродолжительного времени. На­
пример, когда вам диктуют номер мобильного телефона во время разговора по те­
лефону, то эта информация не сразу откладывается у вас в долговременной памяти.
Сначала номер телефона откладывается в вашей кратковременной памяти, емкость
которой ограниченна. Оценки емкости кратковременной памяти разнятся, однако
все ученые сходятся во мнении, что емкость кратковременной памяти составляет
всего несколько объектов. Ученые также сходятся во мнении, что емкость кратко­
временной памяти ограничена двенадцатью объектами.

Например, при чтении программы все ключевые слова, имена переменных и струк­
туры данных хранятся в кратковременной памяти.

Программа на Java с точки зрения кратковременной памяти
В программе на Java самым важным когнитивным процессом является кратковре­
менная память. Сначала вы просматриваете первую строку (листинг 1.6), из кото­
рой узнаете, что входной параметр п представлен целым числом. На данный мо­
мент вы еще не знаете, что делает данная функция, однако вы можете продолжить
просматривать код, зная, что п — это число. Информация о том, что п представлен
целым числом, какое-то время будет храниться в вашей кратковременной памяти.
Затем ВЫ переходите КО второй строке, В которой метод toBinaryString () определя­
ет, что возвращает функция. Возможно, вы забудете эту функцию через день или
даже через час, потому что как только вы поняли функцию, ваша кратковременная
память удаляет эту информацию.

public static void mian(Int n)

{

System.out.printin(Integer.toBinaryString(n));

Гпава 1. Определение вашего типа замешательства при кодировании______________ 33
Замешательство может быть вызвано здесь незнанием принципов работы метода
toBinaryString ().

Несмотря на то что в понимании данной программы большую роль играет кратко­
временная память, пользователь также использует и долговременную память. По
правде говоря, мы используем нашу долговременную память каждый раз, когда
что-либо делаем. Читая программу на Java, вы также опираетесь и на долговремен­
ную память.

Я думаю, что большинство моих читателей знакомы с Java, так что вот вам пример:
если вас попросят объяснить, что делает функция, то вы, скорее всего, знаете, что
можно не учитывать ключевые слова public class и public static void main. Готова
поспорить, что вы даже не заметили, что на самом деле метод называется mian, а не
main.
Ваш мозг нашел короткий путь посредством присвоения имени, характеризующего
смешение двух когнитивных процессов. Ваш мозг, опираясь на предыдущий опыт,
хранящийся в долгосрочной памяти, решил использовать main вместо имени, кото­
рое вы сохранили в краткосрочной памяти. Данный пример опровергает мои слова
о том, что эти два когнитивных процесса независимы друг от друга.
Если долговременную память можно сравнить с жестким диском компьютера, то
кратковременную память можно сравнить с оперативной памятью компьютера или
кешем, который используется для временного хранения информации.

1.2.3. Рабочая память и программирование
Третий когнитивный процесс, играющий роль в программировании, — это рабочая
память. Кратковременная и долговременная память чаще всего используется для
хранения информации. В случае кратковременной памяти информация хранится
в течение короткого периода времени после ее прослушивания или прочтения, а
в случае долговременной памяти информация хранится в течение длительного
периода времени. Однако процесс мышления происходит не в кратковременной и
не в долговременной, а в рабочей памяти. Именно здесь формируются мысли, идеи,
решения. Если долговременную память можно сравнить с жестким диском, а крат­
ковременную — с оперативной памятью, то рабочую память лучше всего сравнить
с процессором мозга.

Программа на BASIC с точки зрения рабочей памяти
При чтении программ на языке BASIC вы используете долговременную память:
например, когда вы вспоминаете значение ключевых слов let и return. Вы также
используете кратковременную память, в которой храните некоторую новую ин­
формацию, например что начальное значение в$ — пустая строка.

Однако, когда вы читаете программу на BASIC, ваш мозг выполняет множество
операций. Мысленно вы выполняете код, чтобы понять, для чего он нужен. Этот
процесс называется трассировкой — мысленной компиляцией и выполнением ко­
да. Часть мозга, использующаяся для трассировки и других сложных когнитивных

Часть I. Об улучшении навыков чтения кода

34

задач, называется рабочей памятью. Вы можете сравнить ее с процессором ком­
пьютера, выполняющим вычисления.

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

1.3. Совместная работа
когнитивных процессов
В предыдущих разделах я подробно описала три важных когнитивных процесса,
связанных с программированием. Таким образом, долговременная память в течение
длительного времени хранит полученную вами информацию, кратковременная
память временно хранит информацию, которую вы только что прочитали или
услышали, а рабочая память обрабатывает информацию и формирует новые мысли.
Хотя я и описала их как отдельные процессы, они тесно связаны друг с другом.
Давайте посмотрим, как именно они взаимосвязаны.

1.3.1. Краткое описание того, как когнитивные процессы
взаимодействуют друг с другом
Как показано на рис. 1.2, когда вы начинаете думать, в вашем мозге активируются
все три когнитивных процесса. Вы могли испытать все три когнитивных процесса
при чтении фрагмента кода на Java (листинг 1.2). Какая-то информация сохрани-

Информация

Рис. 1.2. Три когнитивных процесса, рассматриваемые в этой книге кратковременная память,
долговременная память и рабочая память Стрелки с цифрой 1 обозначают информацию, поступающую
в мозг Стрелки с цифрой 2 обозначают информацию, которая поступает в вашу кратковременную
память Стрелка с цифрой 3 обозначает информацию, которая из кратковременной памяти переходит
в рабочую, где она объединяется с информацией, поступающей из долговременной памяти (стрелка
с цифрой 4) Рабочая память — это место, где обрабатывается информация, пока вы думаете о ней

Глава 1. Определение вашего типа замешательства при кодировании

35

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

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

УПРАЖНЕНИЕ 1.1, Чтобы попрактиковаться в понимании трех когнитивных
процессов, я подготовила три программы. Однако в этот раз я не даю разъясне­
ний, что делают фрагменты кода. Вы должны самостоятельно прочитать листин­
ги программ и решить, для чего они нужны. Программы написаны на APL, Java
и BASIC соответственно. Программы друг с другом не связаны и выполняют
разные операции, поэтому, когда вы поймете первую программу, не стоит опи­
раться на полученную информацию при чтении следующих программ.
Внимательно прочитайте программы и попытайтесь определить, что они дела­
ют. Обратите внимание на то, как вы думаете, и на алгоритм ваших действий.
Для проведения самоанализа используйте вопросы из следующей таблицы.
Листинг 1
Вы получаете знания из долговременной
памяти*?

Если да, то какая это информация?

Вы сохраняете информацию в кратковременной
памяти?
Какую именно информацию вы сохраняете*?

Какую информацию вы не запоминаете, считая
ее неважной?

Листинг 2

Листинг 3

Часть I. Об улучшении навыков чтения кода

36

(продолжение)
Листинг 1

Листинг 2

Листинг 3

Ваша рабочая память может сразу же
обработать некоторые части кода?
Какие части кода сильнее всего загружают вашу
рабочую память'?

Вы понимаете, почему эти части кода загружают
вашу рабочую память?

f •

(V co-l)+V

{со= 5){
s2 -= 9;
}
}

}

return

(si

I- s2)

% 10 ■== 0;

прибавить цифру 2 *- 9 для 5-9

Глава 1. Определение вашего типа замешательства при кодировании

37

Что делает данный код? Какие когнитивные процессы были задействованы
в процессе чтения кода?

100 INPUT PROMPT "String:

" :ТХ$

120 LET RES$='"'

130 FOR I=LEN(TX$)
140

TO 1 STEP-1

LET RES$=RES$&TX$(I)

150 NEXT
160 PRINT RES$

Что делает данный код? Какие когнитивные процессы были задействованы
в процессе чтения кода?

Выводы
□ Замешательство во время кодирования может возникнуть по трем причинам:
недостаток знаний, отсутствие важной информации и недостаток вычислитель­
ной мощности мозга.

□ При чтении или написании кода активируются три когнитивных процесса.
□ Первый процесс — получение информации из долговременной памяти, где хра­
нится, например, значение ключевых слов.

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

В главе 1 были представлены три когнитивных процесса, которые играют важную
роль в программировании и чтении кода. Первым рассмотренным нами когнитив­
ным процессом была долговременная память, которую можно сравнить с жестким
диском, на который записываются воспоминания и факты. Вторым когнитивным
процессом была кратковременная память, которую можно сравнить с оперативной
памятью, хранящей информацию, которая поступает на короткое время. И наконец,
есть рабочая память, которая является процессором и обрабатывает информацию,
поступающую от долговременной и кратковременной памяти.
В этой главе все внимание будет уделено чтению кода. Большую часть времени
программист занимается именно чтением кода. Исследования показывают, что
примерно 60% времени программистов тратится на понимание кода, а не на его
написание'. Следовательно, повышение скорости чтения кода без потери качества
поможет вам улучшить ваши навыки программирования.
1 См. «Measuring Program Comprehension: A Large-Scale Field Study with Professionals», Син Ся и др. (2017),
https://ieeexplore.ieee.org/abstract/document/7997917.

40

Часть I Об улучшении навыков чтения кода

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

2.1. Быстрое чтение кода
В книге Харольда Абельсона (Harold Abelson), Джеральда Джея Сассмана (Gerald
Jay Sussman) и Джулии Сассман (Julie Sussman) «Структура и интерпретация
компьютерных программ» (MIT Press, 1996) есть известная фраза: «Программы
должны писаться для того, чтобы их читали люди, и лишь во вторую очередь для
выполнения машиной». В какой-то степени это является правдой, однако на самом
деле программисты больше пишут код, а не читают его.
Это начинается еще в самом начале пути каждого программиста. Обучение про­
граммированию нацелено на изготовление кода. Я уверена, что, когда вы учились
программированию— не важно, в колледже, на работе или в летнем 1Т-лагере
(буткемпе), — больше всего времени вы уделяли именно созданию кода. Целью
упражнений было найти и исправить ошибки кода. Могу предположить, что уп­
ражнений на чтение кода не было совсем. Из-за отсутствия практики чтения кода
программисту намного сложнее работать с кодом. Эта глава поможет вам улучшить
навыки чтения и понимания кода.
Вы будете читать код по разным причинам: чтобы добавить функцию, найти ошиб­
ку или расширить свое представление обо всей системе. В любом случае вы ищете
в коде конкретную информацию, например место, куда будет правильнее всего
вставить новую функцию, или место, где появляется ошибка, или место последнего
редактирования кода, или то, как применен определенный метод.
Когда вы научитесь быстро находить нужную информацию, вы заметите, что вы
стали реже возвращаться к самому коду. Вы также заметите то, что вам не нужно
перечитывать весь код для того, чтобы найти необходимую информацию. А время,
которое вы сэкономите на чтении кода и поиске в нем информации, можно уделить
исправлению ошибок или добавлению новых функций.

В предыдущей главе я просила вас читать программы на трех разных языках про­
граммирования — так вы получили представление о работе трех частей мозга. Что­
бы глубже понять роль кратковременной памяти, посмотрите следующую про­
грамму на Java, которая приводит в действие метод сортировки вставками (лис­
тинг 2.1). Времени дается не больше трех минут. По истечении времени закройте
код листом бумаги или рукой.
Не открывая код, постарайтесь воспроизвести по памяти код как можно точнее.

Гпава 2. Скорочтение кода

41

Листинг 2.1. Программа на Java, выполняющая сортировку вставками
public class InsertionSort {

public static void main
int

[]

(String

[]

args)

{

array - (45,12,85, 32,89,39,69, 44,42,1, 6,8);

int temp;
for

(int i = 1;

for

if

(int j =

1 < array.length;
j > 0; j--)

i;

(arrayfj]

< array

i++)

{

{

[j - 1])

{

temp - array[g];
array[3]

- array[j - 1];

array[j - 1]

= temp;

)

)
)

for

(int 1-0;

1 < array.length;

1++)

{

System.out.println(array[1]);
}

2.1.1. Что только что происходило в вашем мозге
Когда вы воспроизводили по памяти программу сортировки на Java, вы использо­
вали как кратковременную, так и долговременную память. Подробнее весь процесс
показан на рис. 2.1.

Воспроизведенный
код на Java

Рис. 2.1. Иллюстрация когнитивных процессов, которые происходят при запоминании кода
Часть кода сохраняется в кратковременной памяти (например, имена переменных или значения
переменных), а для другой части используются знания, которые хранятся в вашей долговременной
памяти (например, синтаксис цикла for)

42

Часть /. Об улучшении навыков чтения кода

Ваша кратковременная память сохраняла часть информации, которую вы только
что прочитали. Долговременная память дополняла полученную информацию двумя
способами. Во-первых, при чтении кода вы могли полагаться на знание синтаксиса
Java. Наверное, вы вспомнили, что «цикл for для массива», что, судя по тому, что
у вас хранится в долговременной памяти, эквивалентно for (int i = 0;
i < array. length; i++). Возможно, вы также вспомнили «вывод всех элементов
массива», что на языке Java соответствует for (1 = 0; i < array.length; i++)
{System.out.printin(array[i] )}.

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

2.1.2. Перепроверка воспроизведенного кода
Прежде чем мы углубимся в понимание когнитивных процессов, давайте еще раз
посмотрим на воспроизведенный вами код. Подумайте, какие части кода вы вос­
произвели с помощью кратковременной памяти, а какие — с помощью долговре­
менной. Пример воспроизведенного кода с комментариями представлен на рис. 2.2.

Рис. 2.2. Пример кода из листинга 2 1, воспроизведенного по памяти опытным программистом на языке
Java, с пометками, обозначающими когнитивные процессы. Выделенные темным цветом части кода
представляют собой информацию, хранящуюся в кратковременной памяти, а части кода, выделенные
светлым цветом, представляют собой информацию, поступающую из долговременной памяти.
Обратите внимание на то, что воспроизведенный код больше изначального кода из листинга,
например добавлены комментарии

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

Гпава 2. Скорочтение кода

43

будет выглядеть иначе. Также обратите внимание на то, что в примере присутствуют
комментарии, которых не было в исходном коде. В ходе тестирования программи­
стов я заметила, что некоторые из них при воспроизведении кода добавляют ком­
ментарии, которые облегчают запоминание кода. Например, сначала программист
пишет «выводим содержимое массива», а затем уже пишет сам код. А вы воспроиз­
водили код так же?

Чаще всего комментарии используются для описания уже написанного кода, одна­
ко в примере вы можете видеть, что комментарии можно использовать и как вспо­
могательное средство для написания кода. В следующих главах роль комментариев
в коде будет рассмотрена более подробно.

Вторая попытка воспроизведения кода
В главе 1 я объяснила, как при чтении кода взаимодействуют между собой долго­
временная и кратковременная память. Вы только что более подробно ознакомились
с их взаимодействием, воспроизведя части кода программы сортировки вставками
на Java с помощью информации, хранящейся в вашей долговременной памяти.

Чтобы лучше понять, как сильно вы полагаетесь на долговременную память, давай­
те выполним еще одно упражнение. Это упражнение ничем не отличается от пре­
дыдущего: посмотрите на код программы не больше трех минут, затем закройте
код и попытайтесь воспроизвести код по памяти.
Код на языке Java в листинге 2.2 следует использовать как упражнение для трени­
ровки памяти. Просмотрите код в течение трех минут, а затем воспроизведите его
по памяти.

void execute(int х[] ) {
int b = x.length;

for

(int v

b / 2 - 1; v >“ 0; v—)

func (x, b,

v);

// Извлекаем элементы по одному
for

(int 1 - b-1; 1 > 0;

1—)

{

// Перемещаем текущий элемент в конец
int temp = х[0];
х [0]

= х [1] ;

х[1]

= temp;

func

(х,

1,

0) ;

44

Часть I. Об улучшении навыков чтения кода

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

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

2.1.4. Почему читать незнакомый код так сложно
Как нам показал предыдущий пример, воспроизвести по памяти код не всегда лег­
ко. Почему так сложно запомнить код? Главная причина— ограниченная вмести­
тельность кратковременной памяти.
Как бы вы ни старались, вы не сможете сохранить всю информацию из кода в крат­
ковременной памяти. Как вы узнали из главы 7, кратковременная память хранит
информацию, которую вы слышите или читаете, в течение короткого периода вре­
мени. И когда я говорю «короткий», то я и имею в виду короткий! Согласно иссле­
дованиям, мы не можем сохранять информацию больше чем на 30 с. Через 30 с вам
придется сохранить нужную информацию в долговременной памяти, иначе она
будет потеряна навсегда. Представьте, что кто-то по телефону диктует вам номер
телефона, а вам некуда его записать. Если в ближайшее время вы не запишите но­
мер телефона, то вы его забудете.
Время, в течение которого вы можете запомнить информацию, является не единст­
венной проблемой кратковременной памяти. Второй проблемой является ее вме­
стимость.

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

Гпава 2 Скорочтение кода

45

2.2. Преодоление лимитов памяти
В предыдущем разделе вы узнали об ограничениях кратковременной памяти. Вы
испытали их на собственном опыте, когда пытались запомнить фрагмент кода. Од­
нако, скорее всего, вы запомнили несколько больше, чем просто шесть элементов
из кода. Разве это не противоречит тому, что память может вместить в себя только
шесть элементов?
Способность кратковременной памяти запоминать только шесть элементов распро­
страняется на любую когнитивную задачу, а не только на чтение кода. Так как же
люди могут вообще что-то делать с такой маленькой памятью? Например, как вы
можете читать это предложение?

Согласно теории Миллера, как только человек прочитает шесть букв, он начнет за­
бывать первые буквы. Очевидно, что человек может запомнить больше шести букв,
но как это возможно? Чтобы разобраться с тем, почему незнакомый код так тяжело
читать, а также узнать чуть больше о кратковременной памяти, давайте рассмотрим
один важный шахматный эксперимент.

2.2.1. Сила чанков
Теория чанков впервые была описана нидерландским математиком Адрианом де
Гроотом (Adrian de Groot). Он был аспирантом по математике и шахматистом.
И его постоянно волновал вопрос: почему один человек может стать великим шах­
матистом, в то время как другие игроки будут оставаться на среднем уровне всю
жизнь? Для исследования данного вопроса де Гроот провел два разных экспери­
мента.
В первом эксперименте (рис. 2.3) де Гроот на несколько секунд показывал шахма­
тистам расстановку. По истечении определенного времени де Гроот закрывал фи­
гуры, а участники эксперимента должны были восстановить шахматную расстанов­
ку по памяти. По сути, это задание очень похоже на упражнение, которое я давала
вам в начале этой главы. Де Гроот был заинтересован не только в способности ка­
ждого человека запоминать расположение фигур на шахматной доске; он специ­
ально разделил всех людей на две группы и сравнивал их. В первую группу входи­
ли любители шахмат, а во вторую — профессиональные шахматисты. Сравнивая
результаты обычных шахматистов с профессионалами, де Гроот обнаружил, что
опытным шахматистам намного проще воссоздать по памяти шахматную расста­
новку.
После этого эксперимента де Гроот пришел к выводу, что профессионалы превос­
ходят обычных, посредственных игроков, т. к. кратковременная память профессио­
налов вмещает больше информации. Он также предположил, что причиной боль­
шого объема кратковременной памяти профессиональных шахматистов является
то, что профессиональные игроки были прежде всего экспертами. Соответственно,
они могли запомнить позиции большего количества шахматных фигур, что, собст­
венно, и позволяло им лучше играть в шахматы.

46

Часть I. Об улучшении навыков чтения кода

Рис. 2.3. Первый шахматный эксперимент де Гроота, в котором профессионалов
и обычных шахматистов попросили воспроизвести шахматную расстановку.
Опытные игроки смогли вспомнить позиции большего количества фигур, чем любители

Однако де Гроот был не совсем уверен в своих выводах, поэтому он провел еще
один эксперимент. Второй эксперимент был похож на первый: профессиональных
и обычных игроков попросили запомнить расположение шахматных фигур после
быстрого просмотра шахматной доски. Разница заключалась в шахматных расста­
новках. Вместо того, чтобы показать участникам настоящую шахматную расста­
новку, он показал ситуацию, когда фигуры были расставлены в случайном поряд­
ке — так, как в реальности они никогда не стояли бы. Затем де Гроот снова сравнил
результаты профессиональных и обычных шахматистов. Результаты второго экспе­
римента отличались от предыдущих: обе группы показали себя одинаково плохо!
Разнящиеся результаты первого и второго экспериментов заставили де Гроота ра­
зобраться с тем, как именно обе группы запоминали шахматные расстановки. Ока­
залось, что в обоих экспериментах обычные шахматисты запоминали расстановку
фигуру за фигурой: «ладья на А7, пешка на В5, король на С8» и т. д.

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

Гпава 2. Скорочтение кода

47

хранить от двух до шести элементов, поэтому запоминание четырех позиций впол­
не возможно.

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

Де Гроот назвал группы, в которые люди объединяли информацию, чанками (англ.
chunks). Например, «силицианскую защиту» он принимал за один чанк, который
может поместиться в одну ячейку кратковременной памяти. Теория чанков также
дает логичное объяснение тому, почему во втором эксперименте обе группы шах­
матистов показали одинаковые результаты. В хаотичной шахматной расстановке
профессиональные шахматисты не могли полагаться на свой опыт и долговремен­
ную память, поэтому они не смогли разделить все фигуры на большие группы.

УПРАЖНЕНИЕ 2.1. Возможно, эксперименты де Гроота вас убедили, но лучше
всего испытать это на себе!
Посмотрите на это предложение пять секунд и постарайтесь запомнить его:

о|з

V 3D

Как много вы запомнили?

УПРАЖНЕНИЕ 2.2. Теперь попытайтесь запомнить это предложение, посмот­
рев на него пять секунд:

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

УПРАЖНЕНИЕ 2.3. Давайте попробуем еще раз. Это предложение также
состоит из трех слов и девяти неповторяющихся букв. Посмотрите на предложе­
ние пять секунд и попытайтесь его запомнить:
ocrt

loves

оа^е

Часть I. Об улучшении навыков чтения кода

48

Третье предложение намного проще предыдущих, да? А все потому, что вы мо­
жете разбить буквы на слова, благодаря чему вам просто нужно будет запомнить
три чанка: cat, love и cake. Разбив все предложение на три элемента, вы не пере­
полняете свою кратковременную память, в то время как количество элементов
в первых двух примерах превышало допустимый лимит вашей кратковременной
памяти.

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

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

2.2.2. Опытные программисты
запоминают код лучше начинающих программистов
Исследования де Гроота оказали большое влияние на когнитивную науку. Его экс­
перименты побудили исследователей в области информатики провести похожие
эксперименты и сравнить результаты.
Например, в 1981 году исследователь из Bells Labs Кэтрин МакКитен (Katherine
McKeithen) попыталась повторить эксперименты де Гроота с программистами2.
Кэтрин и ее коллеги показали программы на языке Алгол из 30 строк 53 людям:
начинающим, средней руки и опытным программистам. Некоторые программы бы­
ли реальными, как и в первом эксперименте де Гроота, в котором он просил участ­
ников запомнить реальную шахматную ситуацию. Код других программ был набо­
ром случайных строк, как и во втором эксперименте де Гроота, где шахматные
фигуры были расположены в случайных позициях. Участники рассматривали про­
граммы на Алголе в течение двух минут, а затем должны были воспроизвести их по
памяти.

Результаты эксперимента МакКитен были схожи с результатами де Гроота: лучше
всего запоминали реальные программы опытные программисты, а программисты

2 «Knowledge Organization and Skill Differences in Computer Programmers», Кэтрин МакКитен и др. (1981),
http://mng.bz/YA5a

Гпава 2. Скорочтение кода

49

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

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

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

2.3. Вы видите намного больше кода,
чем можете прочитать
Прежде чем мы перейдем к глубокому изучению кратковременной памяти, я хочу
рассказать о том, что происходит, когда информация попадает в мозг. Существует
стадия, через которую проходит вся информация, прежде чем она достигает крат­
ковременной памяти. Эта стадия называется сенсорной памятью.

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

Часть I, Об улучшении навыков чтения кода

50

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

2.3.1. Иконическая память
Прежде чем информация попадает в кратковременную память, она через органы
чувств поступает в сенсорную память. При чтении кода информация поступает че­
рез ваши глаза, а после на какое-то время она сохраняется в иконической памяти.
Лучший способ проиллюстрировать иконическую память — это представить, что
сейчас канун Нового года, а в руках у вас бенгальский огонь. Если вы быстро нач­
нете двигать рукой с бенгальским огнем, то сможете написать букву. Может, вы
никогда об этом не задумывались, как такое возможно, но именно иконическая па­
мять позволяет увидеть световые фигуры. Иконическая память на время сохраняет
визуальные стимулы, созданные увиденным изображением. Другой пример: за­
кройте глаза. Вы «увидите» форму страницы — это тоже иконическая память.
Перед тем как мы поговорим о том, как можно использовать иконическую память
при чтении кода, давайте посмотрим, что мы о ней знаем. Одним из первых иссле­
дователей иконической памяти был американский психолог Джордж Сперлинг
(George Sperling), занимавшийся исследованием сенсорной памяти в 1960-х годах.
В его самом известном исследовании3 трем участникам показывалась карта разме­
ром 3*3 или 3x4 буквы. Эту карту можно сравнить с таблицей для проверки зрения,
только на карте Сперлинга все буквы были одинакового размера (рис. 2.5).
Участникам показывали изображение в течение одной двадцатой секунды (0,05 с
или 50 мс), после чего их просили повторить случайно выбранную линию, напри­
мер верхнюю строку или левый столбец.

F С М В
Q Р V D
L X Т А
Рис. 2.5. Пример карты Сперлинга, которую участники должны были запомнить

За 50 мс невозможно нормально прочитать буквы, потому что время реакции чело­
веческого глаза составляет около 200 мс (или одна пятая секунды). Тем не менее
участники данного эксперимента смогли вспомнить все буквы в случайной строке
или столбце карты примерно в 75% случаев. Согласно этим результатам, участники
запомнили большую часть или все 9 или 12 букв, что намного больше того количе­
ства, которое может поместиться в кратковременной памяти.

3 «The Information Available in Brief Visual Presentations», Дж. Сперлинг (1960), http://mng.bz/Olao.

Гпава 2. Скорочтение кода________________________________________________ 51_

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

Иконическая память и код
Как вы уже узнали, все, что вы читаете, сначала сохраняется в иконической памяти.
Однако не все, что там хранится, может быть обработано кратковременной памя­
тью. Поэтому при чтении кода вы должны обращать внимание на то, какую инфор­
мацию вы можете обработать. Однако этот выбор проходит неосознанно— при
чтении вы совершенно случайно можете упустить какие-то детали. Это означает,
что чисто теоретически вы можете запомнить намного больше информации о коде,
чем можете обработать.
Вы можете использовать эту информацию для того, чтобы улучшить свой навык
чтения кода: сначала быстро посмотрите на код, а затем подумайте, что вы увидели
и запомнили. Упражнение «код с первого взгляда» поможет вам получить пред­
ставление о коде.

УПРАЖНЕНИЕ 2.4. Выберите фрагмент кода, который кажется вам знакомым.
Вы можете взять фрагмент из собственной кодовой базы или простой фрагмент
с GitHub. Язык программирования не имеет значения. Рекомендуемый размер —
полстраницы. Рекомендуется распечатать код на бумаге.
Несколько секунд посмотрите на код, затем закройте его и ответьте на следую­
щие вопросы:
□ Какова структура кода?

• Код сплошной или вложенный?
• Есть ли выделяющиеся строки?
□ Как пробелы влияют на структуру кода?
• Есть ли в коде пропуски?

• Есть ли в коде массивные куски?

2.3.2. Это не то, что вы помните;
это то, как вы запоминаете
Когда вы пытаетесь воспроизвести только что прочитанный код, изучение строк
кода может стать отличным диагностическим инструментом, который поможет вам

52

Часть I. Об улучшении навыков чтения кода

понять собственное (не)понимание. Однако это не только что вы можете запом­
нить — порядок, в котором вы запоминаете код, также может быть инструментом
для понимания.

Исследователи, повторившие шахматный эксперимент де Гроота с использованием
программ на языке Алгол, провели еще один эксперимент, который позволил
узнать больше о разделении информации на чанки4. Во втором эксперименте начи­
нающих, средней руки и опытных программистов обучали 21 ключевому слову
Алгола, например if, true и end.
Все ключевые слова, которые участники учили в ходе эксперимента, указаны на
рис. 2.6. Вы можете попробовать выучить все ключевые слова самостоятельно.

Рис. 2.6. 21 ключевое слово на языке Алгол, которое в своем эксперименте использовала МакКитен
Начинающим, средней руки и опытным программистам нужно было выучить все эти слова

Когда участники смогли запомнить и правильно повторить все ключевые слова,
исследователи попросили участников составить список всех ключевых слов. Если
вы тоже запомнили их, то запишите все ключевые слова и сравните свой результат
с результатом участников эксперимента.
Исходя из порядка, в котором участники повторяли ключевые слова, МакКитен
смогла понять, как участники связали ключевые слова. Эксперимент показал, что
начинающие программисты сгруппировали ключевые слова Алгола не так, как
опытные программисты. Например, для запоминания они составляли предложения
вроде «TRUE IS REAL THEN FALSE». Опытные же программисты при группиров­
ке ключевых слов использовали свои знания программирования. Например, они
объединили ключевые слова TRUE и FALSE, а также IF, THEN и ELSE. Этот экс­
перимент еще раз подтвердил то, что опытные программисты работают с кодом не
так, как начинающие.

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

4 Результаты представлены в статье «Knowledge Organization and Skill Differences in Computer Programmers».
МакКитен и др.

Гпава 2. Скорочтение кода

53

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

Используйте паттерны проектирования
Если вы хотите написать код, который легко будет делить на чанки, то используйте
паттерны (шаблоны) проектирования — к такому выводу пришел Вальтер Тихи
(Walter Tichy), профессор информатики Технологического института Карлсруэ
в Германии. Тихи исследовал чанки в программном коде, но вышло это случайно.
В основном его интересовал вопрос, помогают ли паттерны проектирования про­
граммистам, когда они сопровождают код (добавляют новые функции или устра­
няют ошибки).
Тихи начал с малого: на группе студентов он проверил, помогает ли информация
о паттернах проектирования понять код5. Он разделил всех студентов на две груп­
пы: обе группы получили одинаковый код, однако первой группе также дали до­
полнительную информацию о коде. Результаты исследования показали, что паттерн
проектирования намного упрощал работу с кодом, особенно когда программисты
знали, что этот паттерн есть в коде.
Тихи провел такое же исследование с опытными программистами6. В данном слу­
чае участники сначала выполняли упражнения по изменению кода, а затем прохо­
дили курс по паттернам проектирования. После прохождения курса они снова
модифицировали код с паттерном проектирования или без него. Результаты данного
исследования показаны на рис. 2.7. Следует отметить, что код, с которым участни­
ки работали после курса, отличался от кода из предыдущего упражнения. В иссле­
довании использовалось два кода: участники, которые до курса работали с кодом
А, после курса работали с кодом В, и наоборот.

На данном рисунке представлены результаты исследования Тихи с диаграммами
типа «ящик с усами»7. На рисунке видно, что после прохождения курса (на рисунке
это область справа, отмеченная как «заключительный тест») времени, требующего­
ся для сопровождения кода с паттернами, нужно намного меньше, чем для сопро­
вождения кода без паттернов. Согласно результатам исследования, наличие знаний
о паттернах проектирования улучшает навык деления на чанки, а также помогает

5 См. «Two Controlled Experiments Assessing the Usefulness of Design Pattern Information During Program Main­
tenance», Луц Прешель, Барбара Унгер и Вальтер Тихи (1998), http://mng.bz/YA9K.
6 «А Controlled Experiment Comparing the Maintainability of Programs Designed with and without Design Pat­
terns — A Replication in a Real Programming Environment», Марек Вокал, Вальтер Тихи, Даг Сьёберг, Эрик
Arisholm, Магне Альдрин (2004), http://mng.bz/G6oR.

7 Ящик представляет собой половину данных, где верхняя линия — это медиана третьего квартиля, нижняя
линия — медиана первого квартиля. Линия в ящике — медиана, а «усы» показывают минимальное и макси­
мальное значение.

Часть I. Об улучшении навыков чтения кода

54

быстрее обрабатывать код. Также обратите внимание на то, что разные паттерны
проектирования имеют разный эффект: на код с паттерном проектирования «На­
блюдатель» участникам понадобилось меньше времени, чем на код с паттерном
проектирования «Декоратор».
Паперн проектирования «Декоратор»
Предварительный тест

2

Время
в минутах

-

Без
паттернов

1
С папернами

Заключительный тест

яг

_

Без
паттернов

__



П

=
С паттернами

Паттерн проектирования «Наблюдатель»
Предварительный тест

80

Время

60

в минутах 40
20

"I
■В

Без
паттернов

"
С паттернами

Заключительный тест

Без
паттернов

С паттернами

Рис. 2.7. На этих диаграммах показаны результаты исследования паттернов проектирования с участием
опытных программистов, проведенного Вальтером Тихи Область «без паттернов» показывает время,
которое участники затратили на изменение кода без паттернов проектирования, а область
«с паттернами» — время, которое участники затратили на изменение кода с паттернами
проектирования. В области «Предварительный тест» вы можете увидеть время, которое участники
затратили перед прохождением курса по паттернам проектирования, а «заключительный тест» — время,
которое участники затратили после прохождения курса по паттернам проектирования Результаты
показывают, что после прохождения курса времени, затрачиваемого на код с паттерном проектирования,
нужно меньше, чем на код без паттернов проектирования

Пишите комментарии
Нужно ли вам писать комментарии или код должен быть «самодокументируемым»?
Этот вопрос на протяжении долгого времени остается предметом бурных дискус­
сий среди программистов.

Исследователи также изучили этот вопрос и пришли к некоторым интересным вы­
водам. Исследования показали, что когда в коде есть комментарии, то программи­
сту требуется больше времени, чтобы его прочитать. Вы можете подумать, что это
плохо — комментарии замедляют работу и вы тратите на них дополнительное вре­
мя, — но на самом деле это знак того, что программисты читают комментарии при
чтении кода. Это говорит о том, что вы не зря добавляете комментарии в свой код.
Марта Элизабет Кросби (Martha Elizabeth Crosby), исследователь из Гавайского

Гпава 2. Скорочтение кода

55

университета, изучала, как программисты читаю код и какую роль при этом играют
комментарии8. Работа Кросби показывает, что начинающие программисты уделяют
комментариям намного больше времени, чем опытные программисты. В части IV
этой книги мы подробнее рассмотрим процесс включения новых сотрудников в ко­
манду, однако результаты Кросби показывают, что добавление в код комментариев
помогает новым программистам понять вашу кодовую базу.
Комментарии не только помогают начинающим программистам, но также и играют
большую роль в том, как именно программисты делят код на чанки. Написанная
в 2010 году диссертация Чжуинь Фэнь (Quiyin Fan) из Университета Мэриленда
«The Effects of Beacons, Comments, and Tasks on Program Comprehension Process in
Software Maintenance» показала, что разработчики при чтении кода сильно зависят
от комментариев. Например, комментарии вроде «Эта функция выводит заданное
двоичное дерево по порядку» помогают программистам выделить крупные чанки
кода. С другой стороны, комментарии вроде «Инкремент i (на единицу)» после
строки i++; могут лишь запутать программиста.

Оставляйте «маячки»
Последнее, что еще можно сделать для того, чтобы упростить разбиение кода на
чанки, — это добавить «маячки». «Маячки» — это части программы, которые по­
могают программисту понять, что делает код. Вы можете представить «маячок» как
строку кода или даже как часть строки кода, на которую вы посмотрите, и у вас
возникнет мысль «теперь я понял!».

Обычно «маячки» указывают на то, что фрагмент кода содержит определенные
структуры данных, алгоритмы или концепции. В качестве примера давайте посмот­
рим на следующий код на языке Python, который обходит двоичное дерево (лис­
тинг 2.3).

# Класс,

представляющий узел в дереве

class Node:

def __ init__ (self,

key):

self.left = None

self.right = None
self.val = key

# Функция для выполнения последовательного обхода дерева

def print_in_order(root):
if root:

8 «How Do We Read Algorithms? A Case Study», Марта Э. Кросби и Ян Стеловский,
https://ieeexplore.ieee.org/document/48797 .

56

Часть I. Об улучшении навыков чтения кода
# Сначала возвращаемся на левом потомке

print_in_order(root.left)

# затем выводим данные по узлу
print(root.val)

# теперь возвращаемся на правом потомке

print_in_order(root.right)
print("Contents of the tree are")

print_in_order(tree)

Этот код на Python содержит несколько «маячков», по которым читатель может
сделать вывод о том, что в данном коде в качестве структуры данных используется
двоичное дерево:

□ комментарии со словом дерево;
□ переменные с именами
□ поля с именами

left

и

root

и

tree;

right;

□ строка текста С упоминанием деревьев (contents

of the tree are).

«Маячки» упрощают процесс понимания кода, т. к. чаще всего они выступают
в качестве триггера и подтверждают или опровергают различные догадки програм­
мистов. Например, когда вы начинаете читать код на Python из предыдущего лис­
тинга, вы, возможно, понятия не имеете, для чего нужен код. Однако, когда вы
прочитаете первый комментарий и увидите класс Node, вы догадаетесь, что код както связан с деревом. Поля left и right подтверждают вашу догадку и указывают на
то, что код работает с двоичным деревом.
Различают два вида «маячков»: простые маячки и составные маячки.

Простые «маячки» — это понятные без объяснений элементы синтаксиса кода, как,
например, значимые имена переменных. В коде на Python (листинг 2.3) root и tree
являются простыми «маячками». В некоторых случаях такие операторы, как +, >
и &&, и структурные операторы типа if, else и т. д. также могут считаться простыми
«маячками», т. к. они просты для обработки и помогают программисту понять
функциональность кода.
Составные «маячки» — это крупные элементы кода, состоящие из простых «маяч­
ков». Составные «маячки» обозначают семантическое значение функций посредст­
вом работы нескольких обычных «маячков». В коде на Python из листинга 2.3 «ма­
ячки» self .left и seif .right вместе образуют составной «маячок». По отдельности
они не дают глубокого понимания кода, а вот вместе дают. Составными «маячка­
ми» могут быть также элементы кода. Например, цикл for может быть составным
«маячком», т. к. он содержит переменную, начальное значение, а также инкремент
и граничные значения.
«Маячки» могут принимать разные формы: мы уже видели, что «маячками» могут
служить имена переменных и классов; другие идентификаторы, например имена

Глава 2 Скорочтение кода

57

методов, тоже могут быть «маячками». Кроме имен «маячками» могут быть и оп­
ределенные конструкции программирования, например инициализация пустого
списка или свопинг.
«Маячки» также имеют связь с чанками, однако многие исследователи рассматри­
вают их как разные концепции. Обычно «маячки» представляют собой более мел­
кие части кода, чем чанки. Кросби, работу которой мы рассмотрели ранее, также
изучала роль «маячков». Она обнаружила, что при чтении кода опытные програм­
мисты намного чаще начинающих используют «маячки»9. Следующее упражнение
поможет вам узнавать полезные «маячки».
УПРАЖНЕНИЕ 2.5. Для того чтобы научиться выбирать правильные типы
«маячков», может понадобиться практика. Используйте это упражнение для
практики использования «маячков» в коде.

Шаг 1. Выберите код
Для данного упражнения выберите незнакомую кодовую базу, но на знакомом
языке программирования. Если есть возможность, то было бы хорошо выпол­
нить это упражнение на кодовой базе, которую знает ваш коллега, друг или зна­
комый, — в таком случае он сможет проверить ваше понимание кода. В кодовой
базе выберите один метод или функцию.
Шаг 2. Изучите код
Изучите выбранный код и попробуйте понять общий смысл кода.
Шаг 3. Обращайте внимание на то, какие «маячки» вы используете
Каждый раз, когда наступает момент «ага, вот оно!» и вы понемногу начинаете
понимать код, выпишите, что именно привело вас к такому выводу. Это может
быть комментарий, имя переменной или метода, промежуточное значение — все
это может быть «маячком».

Шаг 4. Рефлексируйте
Когда у вас сложится полное представление о коде, а также будет составлен
список «маячков», задайте себе следующие вопросы:

□ Какие «маячки» вы выписали?
□ Это элементы кода или информация на естественном языке?
□ Какую информацию они содержат?
□ Представляют ли они знания о предметной области кода?
□ Представляют ли они информацию о функциональности кода?

Шаг 5. Содействуйте развитию кода (необязательно)
Иногда выбранные вами «маячки» можно улучшить. Или, например, в коде мо­
гут понадобиться дополнительные «маячки», которых пока что нет. Это хороСм. «The Roles Beacons Play in Comprehension for Novice and Expert Programmers», Марта Э. Кросби, Джин
Шульц и Сьюзен Уиденбек.

58

Часть I. Об улучшении навыков чтения кода

шая возможность разнообразить код новыми «маячками». Так как до этого уп­
ражнения вы не были знакомы с выбранным кодом, то вы прекрасно понимаете
чувства человека, который сталкивается с незнакомым кодом.
Шаг 6. Сравните свои результаты с кем-то другим (необязательно)

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

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

В этой книге вы часто встретите выражение осознанная практика. Осознанная
практика — это использование упражнения для улучшения определенного навыка.
Например, отжимания — это осознанная тренировка мышц рук; тональная лестни­
ца — осознанная практика для музыкантов; произношение слов по буквам — осоз­
нанная практика для тех, кто только учится читать. В программировании осознан­
ная практика обычно не особо популярна. Многие люди изучали программирова­
ние, много программируя, однако это не самый эффективный вариант обучения.
А вот целенаправленное деление кода на чанки и активное запоминание кода — это
отличные упражнения!
УПРАЖНЕНИЕ 2.6. Данное упражнение поможет вам понять, с какими кон­
цепциями вы уже знакомы, а какие концепции даются вам сложнее всего. Как
показали исследования, знакомые концепции запоминать проще, чем незнако­
мые. Вы можете запомнить то, что уже знаете, поэтому данное упражнение
можно использовать для (само)диагностики вашего знания кода.

Шаг 1. Выберите код
Выберите кодовую базу, с которой вы немного знакомы, но с которой редко ра­
ботаете. Также вы можете взять код, который вы недавно написали. Убедитесь
в том, что вы имеете базовые знания используемого языка программирования.
Вы должны немного понимать, для чего нужен код, но не знать его от начала до
конца. Вы должны оказаться в ситуации, похожей на ситуацию шахматистов:
они знают доску и фигуры, но не знают расстановку.
В кодовой базе выберите метод или функцию размером примерно в половину
страницы и не более 50 строк кода.

Гпава 2 Скорочтение кода

59

Шаг 2. Изучите код
Изучайте выбранный код максимум две минуты. Чтобы было удобнее, поставьте
таймер. После того как время таймера закончится, закройте код.
Шаг 3. Воспроизведите код
Возьмите чистый лист бумаги или откройте новый файл и попытайтесь воспро­
извести код как можно точнее.
Шаг 4. Рефлексируйте
Если вы уверены, что воспроизвели весь код, то откройте исходный код и срав­
ните его с вашим результатом. Ответьте на следующие вопросы:
□ Что запомнить было проще всего?

□ Есть ли части кода, которые вы воспроизвели частично?

□ Если ли части кода, которые вы не запомнили?
□ Вы понимаете, почему у вас не получилось воспроизвести эти части?
□ Есть ли в пропущенных частях незнакомые вам концепции программирова­
ния?

□ Есть ли в пропущенных частях понятия предметной области, с которыми вы
не знакомы?
Шаг 5. Сравните с кем-то другим (необязательно)
Если у вас есть друг, коллега или знакомый, который также хочет улучшить
свой навык разбиения кода на чанки, то вы можете выполнить это упражнение
вместе. Различия, которые появятся у вас обоих при воспроизведении кода, ста­
нут отличной темой для дискуссии. Так как мы знаем, что между начинающими
и опытными программистами есть большие различия, то это упражнение научит
вас оценивать ваш уровень знания языка программирования в сравнении с дру­
гими людьми.

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

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

60

Часть I. Об улучшении навыков чтения кода

«сортировка методом выбора в Python», которые занимают намного меньше
места в кратковременной памяти.
□ Когда вы читаете код, сначала он хранится в иконической памяти. До кратко­
временной памяти доходит лишь часть кода.

□ Запоминание кода можно использовать как инструмент для (само)диагностики
уровня кодирования. Так как всегда легче вспомнить то, что уже знакомо, части
кода, которые вы вспомните, могут выявить паттерны проектирования, конст­
рукции программирования или концепции предметной области, которые вы
знаете лучше всего.
□ Код может содержать в себе элементы, которые значительно упрощают его об­
работку: например, паттерны проектирования, комментарии и «маячки».

Эта глава посвящена тому, как люди учатся запоминать. Из этой главы вы узнаете,
почему одна информация врезается в память, а другая забывается. Например, в ка­
кой-то момент вы узнали, что System.out.print() — это метод языка Java, который
выводит текст на экран. Однако вы не помните все методы Java. Я уверена, что хоть
раз в жизни, но вам приходилось искать определенный синтаксис. Например, чтобы
добавить день К модулю DateTime, НуЖНО ИСПОЛЬЗОВаТЬ метод addDaysO,
addTimespan() ИЛИ plusDays?

Может быть, вы не хотите учить синтаксис наизусть, руководствуясь тем, что
в любой момент вы можете посмотреть его в Интернете. Но, как было показано
в предыдущей главе, ваши знания влияют на то, насколько эффективно вы читаете
и понимаете код. Следовательно, запоминание синтаксиса, концепций программи­
рования и структур данных поможет вам обрабатывать код быстрее.
В этой главе мы рассмотрим четыре метода, которые помогут вам лучше запоми­
нать концепции программирования. Вы будете запоминать концепции программи­
рования на долгое время, что позитивно скажется на вашей работе с кодом. Если вы

62

Часть I. Об улучшении навыков чтения кода

когда-нибудь пытались запомнить синтаксис Flexbox в CSS, порядок параметров
в boxplot () библиотеки matplotlib или синтаксис анонимных функций в JavaScript,
то эта глава для вас!

3.1. Советы по запоминанию синтаксиса
В предыдущих главах вы узнали, что запомнить код построчно не так просто. Да и
вспомнить, какой синтаксис нужно использовать при написании кода, тоже может
быть проблемой. Например, можете ли вы написать код для следующих ситуаций
по памяти?
□ Чтение файла hello.txt, а также запись всех строк в командную строку.
□ Форматирование даты в формате день-месяц-год.
□ Регулярное выражение для слов, начинающихся на 5 или на season.
Даже опытному программисту при выполнении этих задач могут понадобиться
сторонние источники информации. В этой главе мы рассмотрим не только то, по­
чему так сложно запомнить правильный синтаксис, но и узнаем, как можно улуч­
шить запоминание. Однако сначала мы рассмотрим, почему так важно помнить
код.
Многие программисты считают, что знать синтаксис необязательно — зачем тра­
тить время на то, что можно просто найти в Интернете? Однако есть две причины,
по которым «поиск в Интернете» может быть не самым лучшим решением. Первую
причину мы рассмотрели в главе 2\ то, что вы уже знаете, сильно влияет на вашу
эффективность при чтении кода. Чем больше концепций и примеров синтаксиса
вы знаете, тем проще вам будет делить код на чанки и, как следствие, проще код
запоминать и обрабатывать.

3.1.1. Отвлечение снижает производительность
Вторая причина заключается в том, что отвлечение от работы может нанести на­
много больше вреда, чем вам кажется. Открыв браузер, вы захотите проверить
электронную почту или почитать новости, которые не имеют никакого отношения
к причине, по которой вы открыли браузер. Вы также можете отвлечься на другие
темы, читая обсуждение за обсуждением на тематических сайтах по программиро­
ванию.
Крис Парнин (Chris Pamin), профессор Университета штата Северная Каролина,
изучил, что происходит, когда программисты отвлекаются от работы1. Парнин за­
писал 10 тысяч сеансов программирования с 85 программистами. Он посмотрел,
как часто программисты отвлекались на электронные письма или коллег (а отвле­
кались они часто!), но также и изучил то, что происходит после отвлечения. Пар­
нин также установил, что перерывы негативно влияют на производительность про1 См. «Resumption Strategies for Interrupted Programming Tasks», Крис Парнин и Спенсер Ругабер (2011),
http://mng.bz/Orpl.

63

Гпава 3. Как быстро выучить синтаксис

граммиста. Исследование показало, что после отвлечения человеку требуется при­
мерно четверть часа для того, чтобы вернуться к работе с кодом. Только в 10% слу­
чаев после отвлечения программисты могли вернуться к работе над редактировани­
ем кода менее чем за минуту.
Результаты исследования показали, что после отвлечения программисты часто за­
бывали важную информацию о коде, над которым они работали. Думаю, чувство
вроде «Что же я делал?» хоть раз в жизни посещало и вас. Программистам, при­
нявшим участие в исследовании Парнина, чаще всего приходилось прилагать уси­
лия для того, чтобы вспомнить, на чем они остановились. Например, они должны
были посмотреть несколько мест в кодовой базе, чтобы вспомнить детали, прежде
чем вернуться к работе над кодом.

Теперь, когда вы знаете, почему так важно помнить синтаксис, мы рассмотрим спо­
собы, как можно быстро выучить синтаксис.

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

Если вы решите использовать карточки для программирования, то с одной стороны
пишите концепцию программирования, а с другой стороны— соответствующий
код. Карточки для понимания генератора выражений в Python могут выглядеть так:

1. Базовое выражение

numbers =

2. Выражение С выборкой

[х for х in numbers].

odd numbers = [х for х in numbers if x % 2 == 1].

3. Выражение с вычислением

[x*x for x in numbers].

4. Выражение С выборкой И вычислением

squares -

[x*x for x in numbers

if

x > 25].

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

64

Часть I. Об улучшении навыков чтения кода

УПРАЖНЕНИЕ 3.1. Подумайте о 10 концепциях программирования, которые
вам трудно запомнить.

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

3.2.1. Когда использовать карточки
Ключ к изучению синтаксиса заключается в частом использовании карточек на
практике. Существует большое количество приложений, позволяющих создавать
свои собственные цифровые карточки, например: Cerego, Anki или Quizlet. Пре­
имущество таких приложений в том, что они напоминают вам о том, что пришло
время снова потренироваться. Если вы будете регулярно просматривать свои бу­
мажные карточки или заниматься в приложении, то в скором времени вы заметите,
что ваш словарный запас увеличился. Это значительно сэкономит ваше время, ко­
торое вы могли потратить на поиск информации в Google, а также не позволит вам
отвлекаться и улучшит ваш навык деления кода на чанки.

3.2.2. Расширяем набор карточек
Есть несколько моментов, когда можно добавить новые карточки в свой набор.
Первый момент: когда вы изучаете новый язык программирования, фреймворк или
библиотеку, вы можете создавать новую карточку каждый раз, когда вы встречаете
новую концепцию. Например, как только вы начали изучать синтаксис составления
списка, сразу же создайте соответствующий набор карточек.
Второй момент: вы собираетесь искать концепцию в Интернете. Это сигнал, озна­
чающий, что вы не знаете эту концепцию наизусть. Чем не повод создать для нее
карточку? С одной стороны карточки напишите концепцию, а с другой стороны
напишите код, который вы найдете.

Конечно, не нужно создавать карточку под каждую незнакомую концепцию. Со­
временные библиотеки, концепции и базы кодов настолько огромны, что нет смыс­
ла запоминать их все. При встрече со второстепенной концепцией или элементом
всегда можно прибегнуть к поиску в Интернете.

3.2.3. Убираем ненужные карточки
Если вы регулярно занимаетесь с карточками, то спустя какое-то время вы замети­
те, что вы выучили некоторые карточки. Когда это случится, вы можете убрать эти
карточки. Чтобы отслеживать свой прогресс, на каждой карточке ведите статисти­
ку, сколько раз вы дали верный и неверный ответ, как это показано на рис. 3.1.
Если вы несколько раз подряд правильно вспоминаете карточку, то можете убрать
ее. Конечно, если впоследствии вы снова забудете ее, то вы всегда можете вернуть
ее обратно в набор. Если при работе с карточками вы используете приложение, то

Гпава 3. Как быстро выучить синтаксис

65

Рис. 3.1. Пример карточки с указанием верных и неверных ответов Так вы можете отслеживать,
насколько надежно информация сохранена в вашей долговременной памяти

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

3.3. Как не забывать информацию
В предыдущем разделе мы узнали, как с помощью карточек можно быстро и легко
выучить синтаксис. Но как долго нужно тренироваться? Когда вы постигнете Java 8
полностью? В этом разделе вы узнаете, как часто нужно «освежать» знания, прежде
чем вы запомните информацию на долгое время.
Прежде чем мы перейдем к тому, как не забывать, нам нужно понять, почему люди
вообще забывают. Как вы уже знаете, у кратковременной памяти есть свои недос­
татки — она не сохраняет много информации, а информация, которая уже хранится
там, сохраняется на короткий период времени. У долговременной памяти тоже есть
ограничения, но другие.
Одной из главных проблем долговременной памяти является невозможность запо­
минать информацию на долгое время без постоянного повторения. После того как
вы что-то прочитали, услышали или увидели, информация переходит из кратко­
временной памяти в долговременную. Однако это не значит, что эта информация
останется в долговременной памяти навсегда. В этом смысле долговременную
память человека нельзя сравнивать с жестким диском компьютера, на котором ин­
формация вряд ли сотрется или потеряется.
Конечно, когда мы говорим о долговременной памяти, то она сохраняет информа­
цию не на несколько секунд, как это делаеткратковременная память. И все же это­
го очень мало. Посмотрите на кривую забывания на рис. 3.2. Примерно через час
вы забываете половину того, что прочитали. Через два дня остается только 25% от
полученной информации. Но это не все: график на рис. 3.2 показывает, сколько
в конце концов вы запомните, если не будете «освежать» полученную инфор­
мацию.

3.3.1. Почему мы забываем
Чтобы понять, почему некоторая информация так быстро забывается, нам нужно
подробно рассмотреть работу долговременной памяти. Начнем с того, как мы запо­
минаем.

66

Часть I. Об улучшении навыков чтения кода

Рис. 3.2. График, показывающий, сколько информации вы запомнили после того, как вы ее узнали
Через два дня в вашей долговременной памяти остается только 25% знаний

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

Иерархия и сеть
Мы сравнили долговременную память с жестким диском, однако на самом деле
человеческий мозг не работает по принципу иерархии, где все файлы лежат в пап­
ках и подпапках. Как показано на рис. 3.3, воспоминания представляют собой сеть.
Дело в том, что каждое событие, явление и воспоминание связано со множеством
других. Осознание связи между различными явлениями и воспоминаниями важно
для понимания того, почему люди забывают.

Рис. 3.3. Два способа организации данных слева представлена иерархическая файловая система,
а справа — сетевая система

Кривая забывания
Герман Эббингауз (Hermann Ebbinghaus), немецкий философ и психолог, интересо­
вался возможностями человеческого мозга в 1870-х годах. Тогда идея измерения
умственных способностей человека была не особо популярна.

67

Гпава 3. Как быстро выучить синтаксис

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

Для получения более правдивых результатов Эббингауз создал множество корот­
ких бессмысленных слов, например: wix. maf. kel и jos. Затем он провел серию экс­
периментов с самим собой в качестве испытуемого. В течение нескольких лет он
учил списки бессмысленных слов, читая все слова вслух под метроном, чтобы не
сбиться с темпа, и отслеживал, сколько потребовалось времени для того, чтобы
точно запомнить каждый список слов.
Через десять лет, в 1880 году, он произвел подсчеты и получил такой результат:
ему потребовалось почти тысяча часов на практику, а в минуту он цитировал
150 слов. Проверяя себя спустя разные периоды времени, Эббингауз смог опреде­
лить временной интервал для своей памяти. Он описал все свои результаты и выво­
ды в своей публикации 1885 года под названием Uber das Gedachtnis (О памяти).
В книге дана формула забывания, показанная на рис. 3.4, которая и лежит в основе
концепции кривой забывания.

Ь = 100х----- —

(logl00’»+1,84

Рис. 3.4. Формула Эббингауэа для расчета, как долго информация будет храниться в памяти

Недавнее исследование нидерландского профессора Япа Мюррэ (Jaap Мште)
из Амстердамского университета показало, что в основном формула Эббингауза
верна2.

3.3.2. Интервальное повторение
Теперь мы знаем, как люди забывают информацию. Однако как это поможет нам не
забыть синтаксис boxplot о библиотеки matplotlib или генератора выражений в
Python? Оказалось, что эксперименты Эббингауза с заучиванием бессмысленных
слов не только позволили определить, сколько нужно времени для того, чтобы за­
быть полученную информацию, но также и помогли понять, как можно предотвра­
тить забывание. Эббингауз заметил, что он смог выучить ряд из 12 бессмысленных
слов с 68 повторениями в первый день и с 7 повторениями на следующий день
(всего 75 повторений); также он пробовал учить такой же ряд из бессмысленных
слов, но с 38 повторениями в течение трех дней, что составляло половину от всего
времени учебы.

2 См. «Replication and Analysis of Ebbinghaus’ Forgetting Curve», Яп Мюррэ (2015),
https:/journals.plos.org/plosone/article?id=10.1371/journal.pone.0120644.

68

Часть I Об улучшении навыков чтения кода

Кривую забывания тщательно исследовали: проводились как эксперименты с ма­
ленькими детьми, которых обучали базовым математическим операциям, так и со
старшеклассниками. Исследование, пролившее свет на оптимальной период време­
ни между повторениями, провел Гарри Бахрик (Harry Bahrick) из Уэслианского
университета Огайо. Однако он проводил исследование не только над собой, но и
над своей женой и двумя взрослыми детьми, которые тоже были учеными и инте­
ресовались этой темой3.
Все они поставили перед собой цель выучить 300 слов на иностранном языке. Его
жена и дочь изучали слова на французском, а сам Бахрик учил слова на немецком.
Они разделили все слова на 6 групп по 50 слов и использовали разные интервалы
между повторениями для каждой из групп слов. Каждую группу слов учили 13 или
26 раз с интервалом в 2, 4 или 8 недель. Затем они проверяли, сколько они помнят
через один, два, три года или пять лет.

Через год после окончания эксперимента Бахрик и его семья обнаружили, что
больше всего слов они запомнили из группы, которая была с самыми длинными
интервалами между повторениями и с самым большим количеством повторений —
26 раз каждые 8 недель. Через год из этой группы они смогли вспомнить 76% слов,
в то время как из группы, где повторения были через каждые две недели, они смог­
ли вспомнить только 56% слов. В последующие годы количество выученных слов
уменьшилось, однако все равно количество запомненных слов из группы с самым
большим интервалом повторений было больше.

Из этого можно сделать вывод, что чем дольше вы что-то учите, тем больше вы за­
помните. Однако это не значит, что все время вы должны уделять заучиванию —
это означает только то, что вам нужно учить с увеличенными интервалами. Для
улучшения вашей памяти и лучшего запоминания информации будет достаточно
просмотреть ваши дидактические карточки раз в месяц. Конечно, этот подход не
сравнить с «обязательным» образованием, где мы стараемся изучить все-все за
один семестр, или учебными лагерями (буткемпами), где людей стараются обучить
всему за три месяца. Знания, полученные таким образом, останутся в вашей памяти
надолго лишь в том случае, если вы будете часто повторять то, что выучили.
Совет

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

3 См «Maintenance of Foreign Language Vocabulary and the Spacing Effect». Гарри Ьархик и др. (1993),
www.gHern.net/docs/spaced-repetition/1993-bahrick.pdf .

Гпава 3. Как быстро выучить синтаксис______________________________________ 69

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

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

3.4.1. Два способа запоминания информации
Прежде чем мы начнем разбираться с тем, как запоминание укрепляет нашу па­
мять, давайте сначала посмотрим на саму проблему. Вы можете думать, что память
либо находится в мозге, либо нет, но на самом деле все сложнее. Роберт и Элизабет
Бьорк (Robert и Elizabeth Bjork), профессора психологии Калифорнийского универ­
ситета, выделили два механизма извлечения информации из долговременной памя­
ти: уровень хранения и уровень воспроизведения.

Уровень хранения
Уровень хранения показывает, насколько хорошо сохранилась информация в дол­
говременной памяти. Дело в том, что чем больше вы что-то учите, тем лучше вы
это запоминаете. В конце концов вы так запомните материал, что уже никогда его
не забудете! Можете ли вы представить себе, что вы забыли, что 3 умножить на
4 это 12? Однако не всю информацию, хранящуюся в мозге, можно вспомнить так
же легко, как таблицу умножения.

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

Принято считать, что уровень хранения может только увеличиваться. Согласно не­
давним исследованиям, на самом деле люди никогда не забывают воспомина-

Часть I. Об улучшении навыков чтения кода

70

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

3.4.2. Просто увидеть недостаточно
При поиске определенного синтаксиса чаще всего проблема заключается в уровне
не хранения, а воспроизведения. Например, можете ли вы найти правильный код
для обхода списка в обратном порядке на C++ из нескольких вариантов (лис­
тинг 3.1)?

1.

rit = s.rbegin(); rit != s.rendO; nt++

2.

rit = s.revbeginO ;

3.

rit = s.beginr();

rit

' = s.endr();

4.

rit = s.beginr ();

rit

1 = s.end(); rit++

5.

rit = s.rbegin();

rit

1 = s.end();

6. rit = s.revbeginr 0;

rit

nt

!!= s.end() ;

rit++

rit++

nt++

1= s.revend(); rit++

Все приведенные варианты очень похожи, и даже опытному программисту на C++
может быть сложно вспомнить правильный, хотя он и видел его множество раз.
Когда вам говорят правильный ответ, то у вас создается впечатление, что вы всегда
его знали: «Конечно же, ЭТО ведь rit = s.rbegin(); rit ' = s.rendO; nt++!>>.
Следовательно, проблема заключается не в прочности, с которой знания хранятся
в долговременной памяти (уровень хранения), а в легкости, с которой вы можете
найти информацию (уровень воспроизведения). Этот пример показывает, что даже
если вы множество раз видели код, это не значит, что вы его запомнили. Нужная
информация хранится где-то в вашей долговременной памяти, однако это не зна­
чит, что вы всегда сможете ее вспомнить.

3.4.3. Воспоминания укрепляют память
Упражнение из предыдущего раздела показало, что просто хранить информацию
в долговременной памяти недостаточно. Вы также должны с легкостью ее вспом­
нить. Как и многое другое в нашей жизни, вспоминать информацию намного легче,
если вы постоянно это практикуете. Так как вы никогда не пытались целенаправ­
ленно вспоминать синтаксис, при необходимости вам будет трудно его вспомнить.
Мы знаем, что активные попытки вспомнить что-то укрепляют память — эта мето­
дика существовала еще во времена Аристотеля.

4 «Recollection. Familiarity, and Cortical Reinstatement: A Multivoxel Pattern Analysis», Джеффри Дж. Джонсон,
Сьюзен МакДафф, Майкл Д. Рагг и Кеннет Норман, Neuron, vol. 63, no. 5, September 8, 2009.

Гпава 3. Как быстро выучить синтаксис______________________________________ 71
Одно из первых исследований данной методики было проведено школьным учите­
лем Филипом Босвудом Баллардом (Philip Boswood Ballard), который в 1913 году
опубликовал статью «Obliviscence and Reminiscence» («Забывчивость и припомина­
ние»). В ходе эксперимента он попросил учеников выучить 16 строк из стихотворе­
ния «Крушение Тесперус"», в котором рассказывается история тщеславного шки­
пера, который стал причиной смерти его дочери. Когда Баллард исследовал спо­
собность учеников вспоминать выученное стихотворение, он заметил кое-что
интересное. Баллард не сказал ученикам, когда он спросит их в следующий раз, и
попросил их рассказать стихотворение через два дня. Так как ученики не знали, что
их будут спрашивать еще раз, они больше не учили стихотворение. Когда Баллард
просил учеников прочитать поэму во второй раз, то он заметил, что в среднем все
ученики запомнили на 10% больше, чем в прошлый раз. Еще больше материала они
помнили еще через два дня. Отнесшись к результатам с недоверием, Баллард по­
вторил это исследование несколько раз, однако результаты каждый раз были похо­
жими: когда вы активно пытаетесь вспомнить информацию, при этом не прибегая
к дополнительному заучиванию, вы вспоминаете больше материала.
Теперь, когда вы познакомились с кривой забывания и эффектами практики актив­
ного воспроизведения информации, вы понимаете яснее, что искать забытый син­
таксис каждый раз, когда он вам нужен, не самая лучшая идея. Так как найти син­
таксис на сторонних ресурсах не составляет никакого труда, наш мозг начинает
считать, что запоминать синтаксис не нужно. Следовательно, уровень воспроизве­
дения синтаксиса языков программирования остается слабым.
Забывание синтаксиса приводит к замкнутому кругу. Мы не помним синтаксис,
следовательно, нам нужно его где-то найти. Но если мы будем продолжать посто­
янно искать его вместо того, чтобы пытаться вспомнить, то наш уровень воспроиз­
ведения этих концепций программирования не повысится и мы снова должны
будем искать нужную нам информацию, и так до бесконечности.
В следующий раз, когда вы соберетесь что-нибудь загуглить, возможно, стоит сна­
чала вспомнить синтаксис самостоятельно. Даже если у вас не получится вспом­
нить синтаксис, сама попытка укрепит вашу память, и, может быть, в следующий
раз вы сможете вспомнить нужную вам информацию. Однако если это не помогает,
то сделайте дидактическую карточку и активно ее учите.

3.4.4. Укрепление памяти путем активного мышления
В предыдущем разделе вы узнали, что активные попытки вспомнить информацию
и практика помогают запомнить информацию. Вы также узнали, что лучше всего
запоминать информацию в течение длительного периода времени. Однако сущест­
вует еще один способ укрепления памяти — это активное мышление. Активное
обдумывание информации, которую вы только что выучили, называется проработ­
кой. Данный способ хорошо подходит для изучения сложных концепций програм­
мирования.

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

72

Часть I. Об улучшении навыков чтения кода

Схемы
Как вы уже знаете, все воспоминания представляют собой сеть, в которой они свя­
заны с другими воспоминаниями и фактами. Воспоминания и связи между ними
формируют схему или схемы.
Когда вы изучаете новую информацию, перед запоминанием информации в долго­
временной памяти в вашем мозге создается схема. Информация, которая больше
всего соответствует уже существующим схемам, запомнится лучше. Например,
если я попрошу вас запомнить числа 5, 12, 91, 54, 102 и 87, а затем воспроизвести
три из них, чтобы получить приз на выбор, то вы столкнетесь с трудностями —
числа сложно связать друг с другом. Поэтому числа сохранятся в новой схеме под
названием «Числа, которые я запомнила для того, чтобы выиграть классный приз».
Однако, если я попрошу вас запомнить числа 1,3, 15, 127, 63 и 31, то вы их запом­
ните с большей вероятностью. Если вы посмотрите повнимательнее, то заметите,
что все числа, если их преобразовать в двоичную систему, будут состоять только из
единиц. Так вы не только запомните числа быстро и легко, но и получите мотива­
цию запоминать числа — вы понимаете, что это имеет смысл и вы не тратите время
зря. Вы понимаете, что если вы знаете верхнюю границу чисел в битах, то это мо­
жет помочь решить вам некоторые проблемы.
Когда рабочая память обрабатывает информацию, она ищет в долговременной па­
мяти связанные с информацией воспоминания и факты. Если ваши воспоминания
связаны друг с другом, то найти их будет намного проще. Другими словами, уро­
вень воспроизведения выше для тех воспоминаний, которые связаны с другими
воспоминаниями.

Когда мы запоминаем информацию, она может быть немного изменена для того,
чтобы ее можно было связать с существующими схемами. В 1930-х годах британ­
ский психолог Фредерик Бартлетт (Frederic Bartlett) провел эксперимент, в котором
он попросил группу людей прочитать короткую сказку коренных американцев под
названием «The War of the Ghosts» («Война призраков») и вспомнить ее через не­
сколько недель или месяцев5. Слушая пересказ сказки спустя определенное время,
Бартлетт заметил, что участники частично изменили сказку, чтобы она соответст­
вовала их убеждениям или знаниям. Например, некоторые из участников опустили
детали, которые они считали неважными. Другие участники адаптировали сказку и
сделали ее более «западной», например заменили лук на ружье. Данный экспери­
мент показал, что люди не запоминают просто слова или факты, а подстраивают их
под уже имеющийся опыт, знания и взгляды.
Тот момент, что при запоминании информации мы можем ее изменить, имеет свои
недостатки. Два человека, попавшие в одну и ту же ситуацию, могут вспомнить ее
совершенно по-разному: сами мысли людей влияют на то, как они запоминают и
хранят информацию. Однако мы также можем опираться на тот факт, что воспоми5 См. его книгу «Remembering: A Study in Experimental and Social Psychology» (Cambridge University Press.
1932).

Глава 3. Как быстро выучить синтаксис______________________________________ 73
нания могут быть изменены в наших интересах: мы сохраняем основную информа­
цию, при этом добавляя часть от себя.

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

Например, если я вам скажу, что Джеймс Монро (James Monroe) был пятым прези­
дентом США, то вы запомните, что Монро — бывший президент, но забудете тот
факт, что он был пятым. Скорее всего вы не запомните номер по нескольким при­
чинам: вам могло показаться это сложным, вы могли отвлечься или посчитать эту
информацию неважной. На количество запоминаемых данных влияет много факто­
ров, в том числе и ваше эмоциональное состояние. Например, вы быстрее запомни­
те ошибку, над исправлением которой сидели целую ночь год назад, чем ошибку,
которую вы совершили сегодня и исправили за несколько минут.
И хотя вы никак не можете изменить свое эмоциональное состояние, есть много
вещей, которые можно сделать для того, чтобы сохранить как можно больше новых
воспоминаний. И проработка — это одна из таких вещей.

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

Если вы хотите лучше запомнить новую информацию, то вам нужно подробно ее
проработать. Процесс проработки укрепляет сеть связанных воспоминаний, а когда
воспоминание связано со множеством других, его проще вспомнить. Представьте,
что вы учите новую концепцию программирования, например генератор списков на
Python. Генератор списков— это инструмент для создания списка на основе уже
существующего списка. Например, вы хотите создать список квадратов чисел, ко­
торые вы уже сохранили в списке numbers. Вы можете создать такой список с по­
мощью генератора списка:
squares = [х*х for х in numbers]

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

Часть I. Об улучшении навыков чтения кода

74

УПРАЖНЕНИЕ 3.2. Используйте данное упражнение для изучения новой кон­
цепции программирования. Ответы на следующие вопросы помогут вам укре­
пить новые знания:

□ Думая о новой концепции программирования, вы вспоминаете другие кон­
цепции. Что это за концепции? Запишите их.
□ Для каждой из записанных концепций ответьте на следующие вопросы:

• Почему новая концепция заставляет меня думать об этой уже известной
мне концепции?
• У обеих концепций одинаковый синтаксис?

• Эта концепция может использоваться в данном случае?
• Является ли новая концепция альтернативой той концепции, которую я
уже знаю?
□ Знаете ли вы другие способы написать код, чтобы в итоге он выполнял нуж­
ную задачу? Постарайтесь написать как можно больше вариантов такого ко­
да.
□ Есть ли эта концепция в других языках программирования? Можете ли вы
записать примеры на других языках? Чем они отличаются от выбранной вами
концепции?
□ Соответствует ли новая концепция определенной предметной области, биб­
лиотеке или фреймворку?

Выводы
□ Важно знать синтаксис наизусть, т. к. знание синтаксиса облегчит деление кода
на чанки. К тому же, если вы решите искать синтаксис в Интернете, вы можете
отвлечься от работы.
□ Для практики и запоминания нового синтаксиса используйте дидактические
карточки: на одной стороне укажите подсказку, а на другой — сам код.

□ Важно регулярно повторять новую информацию, чтобы не забыть ее.
□ Лучшей практикой будет не поиск информации в Интернете или в документа­
ции, а попытка самостоятельно вспомнить нужную вам информацию.
□ Чтобы увеличить объем знаний, которые вы можете вспомнить, практикуйтесь
в течение продолжительного времени.
□ Информация в вашей долговременной памяти хранится в виде сети, в которой
все явления и факты связаны между собой.
□ Активная проработка новой информации позволяет укрепить сеть воспоминаний
и связать с ней новую информацию.

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

Иногда код бывает слишком трудным для понимания. Из-за того, что программи­
сты редко практикуют чтение кода, вы могли заметить у себя недостаток стратегий,
применимых к чтению кода. Стратегии вроде «прочти это еще раз» и «сдавайся»
чаще всего оказываются бесполезными.
В предыдущих главах мы рассмотрели способы, которые можно использовать для
улучшения навыка чтения кода. В главе 2 мы узнали о способах эффективного раз­
биения кода на чанки, а в главе 3 получили советы, как можно запомнить большой
объем синтаксиса в долговременной памяти и не забыть его. Однако иногда код
бывает настолько сложным, что даже умение делить код на чанки и отличное зна­
ние синтаксиса ничем не помогут.
В данной главе мы рассмотрим когнитивные процессы, лежащие в основе вычисли­
тельной способности мозга, которые мы обычно называем рабочей памятью. Мы

Часть I Об улучшении навыков чтения кода

76

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

4.1. Почему так тяжело понимать сложный код
В главе 1 я показала вам пример программы на BASIC, достаточно сложной, чтобы
полностью понять программу, только прочитав код. В подобных случаях, возмож­
но, имеет смысл записать рядом с кодом промежуточные значения, как это показа­
но на рис. 4.1.
1
2
3
4
5
6
7
8
9

LET N2 = ABS (INT (N) )
LET B$ = ""
FOR N1 = > N2 TO 0 STEP
LET N2 « INT (N1
LET B$ =
LET N1
1
NEXT N1
PRINT B$
RETURN

7
ll'l II

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

Сам факт того, что вам нужно что-то дополнительно записать, означает то, что
у вашего мозга недостаточно ресурсов для обрабатывания кода. Давайте сравним
код на языке BASIC со вторым примером из главы 7, программой на языке Java,
которая вычисляет значение числа п в двоичном представлении. Понимание этого
кода может потребовать некоторых умственных усилий, к тому же незнание прин­
ципа работы метода toBinaryString о может вызвать замешательство. Но, несмотря
на все это, вряд ли вам потребуется делать заметки во время чтения этого кода.

public class Binarycalculator {
public static void main(Integer n)

{

System.out.printin(Integer.toBinaryString(n) ) ;
}

}

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

Глава 4 Как читать сложный код

77

формацию, нам нужно рассмотреть третий когнитивный процесс из главы 1. Рабо­
чая память представляет собой способность человеческого мозга думать, формиро­
вать мысли, идеи, находить решение проблем. Ранее мы сравнивали кратковремен­
ную память с ОЗУ компьютера, долговременную память — с жестким диском. Если
следовать этой аналогии, то рабочую память можно сравнить с процессором мозга.

4.1.1. Чем друг от друга отличаются
рабочая память и кратковременная память
Некоторые используют термин «рабочая память» в качестве синонима кратковре­
менной памяти, и, быть может, вы видели, что иногда эти два термина взаимно за­
меняют друг друга. Другие, наоборот, проводят между двумя терминами четкую
границу— собственно, в этой книге мы придерживаемся такой же точки зрения.
Роль кратковременной памяти — это запоминание информации. С другой стороны,
роль рабочей памяти — это обработка информации. Поэтому данные процессы мы
будем рассматривать как отдельные, непохожие друг на друга.
Определение

Определение рабочей памяти, которое будет использоваться в оставшейся части
книги, — это «кратковременная память, использующаяся для решения проблем».

На рис. 4.2 показана разница между двумя процессами: если вы запоминаете номер
телефона, то вы используете кратковременную память; если вы складываете числа,
то вы используете рабочую память.

Кратковременная
память

память

Рис. 4.2. Кратковременная память на короткий период времени сохраняет информацию
(например, номер телефона, на рисунке — слева), тогда как рабочая память обрабатывает информацию
(например, выполняет вычисления, на рисунке — справа)

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

Часть I. Об улучшении навыков чтения кода

78

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

4.1.2. Типы когнитивной нагрузки
и как они связаны с программированием
В данной главе мы рассмотрим способы устранения когнитивной нагрузки, однако,
прежде чем приступить к этой теме, мы должны рассмотреть существующие виды
когнитивной нагрузки. Первым исследователем, предложившим термин «когни­
тивная нагрузка», был австралийский профессор Джон Свеллер (John Sweller). Он
выделил три формы когнитивной нагрузки: внутренняя, внешняя и соответствую­
щая нагрузка. В табл. 4.1 приводится краткое описание каждого типа когнитивной
нагрузки.
Таблица 4.1. Типы когнитивной нагрузки
Тип нагрузки

Краткое пояснение

Внутренняя нагрузка

Насколько задача сложна сама по себе

Внешняя нагрузка

Какие отвлекающие факторы усугубляют задачу

Соответствующая
нагрузка

Когнитивная нагрузка, созданная необходимостью хранить все мысли
в долговременной памяти

Мы сфокусируемся на первых двух типах когнитивной нагрузки. Соответствую­
щую нагрузку мы подробно рассмотрим в следующей главе.

Внутренняя когнитивная нагрузка при чтении кода
Внутренняя нагрузка — это когнитивная нагрузка, вызванная некоторыми особен­
ностями задачи, которые заложены в ней изначально. Например, представьте, что
вам нужно узнать значение гипотенузы треугольника (рис. 4.3).

6
Рис. 4.3. Геометрическая задача, в которой даны значения двух сторон треугольника и нужно вычислить
значение третьей стороны. Сложность этой задачи зависит от ваших знаний. В любом случае нельзя эту
задачу как-то изменить или пропустить в ней какие-то шаги

Для решения данной задачи вам нужно иметь определенные знания. Например, вам
нужно знать теорему Пифагора (а2+Ь2=с2), также вы должны уметь возводить числа
в квадрат, а потом извлекать квадратный корень из полученного числа. Так как не
существует других способов решить или упростить эту задачу, когнитивная на­
грузка является внутренней. В программировании мы часто используем термин
внутренняя сложность для описания внутренних аспектов какой-либо задачи.

Гпава 4. Как читать сложный код

79

А в когнитивистике мы говорим, что эти аспекты вызывают когнитивную нагрузку
внутреннего типа.

Внешняя когнитивная нагрузка при чтении кода
Кроме естественной внутренней нагрузки, причиной которой является какаянибудь задача, существует и другой тип когнитивной нагрузки, которая может до­
бавиться к задаче, часто случайно. Снова обратимся к задаче на вычисление длины
гипотенузы, но сформулируем ее так, что при решении нам придется мысленно
связать две стороны треугольника, длина которых уже известна, с их обозначения­
ми (рис. 4.4). Результатом такой дополнительной работы будет внешняя когнитив­
ная нагрузка мозга.
Определите значения а и b

Рис. 4.4. Задача с такой постановкой условий вызывает внешнюю когнитивную нагрузку

На самом деле решение задачи от этого условия никак не изменилось — нам все
еще нужно знать теорему Пифагора. Однако это условие сильно отражается на
производительности мозга: теперь мозгу нужно соотнести а со значением 8 и b со
значением 6. В программировании мы относимся к такой внешней нагрузке как
к ненужной сложности, т. е. к аспектам программы, которые делают поставленную
задачу сложнее, чем она есть на самом деле.
Однако то, что создает внешнюю нагрузку у одного программиста, необязательно
будет создавать ее у другого. Чем больше у вас опыта, тем меньшую когнитивную
нагрузку вы будете испытывать при решении задач. Например, в листинге 4.2 пред­
ставлены два эквивалентных кода на языке Python.

above_ten =

[a for a in items if a > 10]

above_ten =

[]

for a in items:

if a > 10: new_iterns.append(a)

Так как оба фрагмента решают одну и ту же задачу, когнитивная нагрузка на мозг
у них одинаковая. Однако внешняя когнитивная нагрузка зависит от уже имею­
щихся у вас знаний: если вы не знакомы со списками, то внешняя нагрузка в пер­
вом примере будет намного больше, чем для тех программистов, кто уже имеет
опыт работы со списками.

Часть I. Об улучшении навыков чтения кода

80

УПРАЖНЕНИЕ 4.1. В следующий раз, когда вы будете читать незнакомый код,
постарайтесь проконтролировать когнитивную нагрузку. Когда вам становится
трудно обрабатывать код и вы чувствуете необходимость в заметках или в по­
шаговом выполнении этой задачи, то, скорее всего, вы испытываете высокую
когнитивную нагрузку.
В этот момент стоит понять и определить, какие участки кода вызывают когни­
тивную нагрузку. Для этого вы можете использовать следующую таблицу:
Строка кода

Внутренняя когнитивная нагрузка

Внешняя когнитивная нагрузка

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

4.2.1. Рефакторинг
Рефакторинг— это перепроектирование кода с целью улучшения его внутренней
структуры, но без изменения его интерфейсов. Например, если один из блоков кода
слишком длинный, вы можете разделить его на несколько функций, или если в ко­
довой базе есть дублирование, то вы можете переписать код, собрав все строки
с дублированием в одном месте. Например, в следующем коде на Python (лис­
тинг 4.3) повторяющиеся вычисления можно поместить в метод.

vat_l = Vat (waterlevel - 10,
volume__vat_ 1

radius --- 1)

- math.pi * vat 1. radius **2 * vat 1. water_level

print (volume_vat_l'i

vat_l = Vat(waterlevel - 25,

radius - 3)

volume_vat_2 = math.pi * vat_2.

radius **2 ★ vat_2. water_level

print(volume_vat 2)

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

Гпава 4. Как читать сложный код

81

Однако код, который будет легок в сопровождении, не всегда может быть удобен
при чтении. Давайте рассмотрим пример кода, в котором есть множество вызовов
методов из разных частей файла или даже нескольких файлов. Такая архитектура
удобна больше для сопровождения кода, т. к. каждая программная фунция имеет
свой собственный метод. Однако такой делокализованный код загромоздит рабо­
чую память, потому что вам придется искать описание функций во многих местах.

Поэтому иногда вам захочется сделать рефакторинг кода, чтобы упростить его чте­
ние в данный период времени, а не для того, чтобы упростить сопровождение кода
в долгосрочной перспективе. Такой рефакторинг называется когнитивным. Когни­
тивный рефакторинг — это изменение кодовой базы без изменения интерфейса, как
и в случае обычного рефакторинга. Однако цель когнитивного рефакторинга за­
ключается в том, чтобы сделать код более читаемым для данного читателя в дан­
ный момент времени.
Когнитивный рефакторинг иногда может включать в себя обратный рефакторинг.
который снижает удобство эксплуатации, например встраивание кода — реализа­
ция метода и копирование тела функции в место вызова. Некоторые интерактивные
среды разработки могут выполнять этот рефакторинг автоматически. Если имя ме­
тода неясно, например calculate о или transform о, то встраивание кода может быть
особенно полезным. При вызове метода с непонятным для вас именем вам нужно
некоторое время для того, чтобы понять, что делает метод, и, возможно, вам нужно
будет поработать с этим методом еще несколько раз, прежде чем он отложится
в вашей долговременной памяти.

Встраивание кода снижает внешнюю когнитивную нагрузку и может помочь по­
нять код, вызывающий метод. К тому же изучение кода самого метода может
помочь вам понять код. В новом контексте вы можете выбрать подходящее имя для
метода.
В качестве альтернативы вы можете изменить порядок методов в коде — например,
код будет удобен для чтения, если метод будет располагаться рядом с вызовом ме­
тода. Конечно, в наше время многие интерактивные среды уже имеют метки для
перехода к определениям методов и функций, однако использование этой функции
также занимает определенное место в рабочей памяти. Следовательно, это тоже
может вызвать внешнюю когнитивную нагрузку.
Когнитивный рефакторинг чаще всего предназначен для одного человека, потому
что опыт и знания разных людей будут отличаться. Во многих случаях когнитив­
ный рефакторинг носит лишь временный характер и предназначен для того, чтобы
человек мог понять код. Затем, как только человек начинает понимать его, когни­
тивный рефакторинг не используется.
И хотя всего лишь несколько лет назад этот процесс мог быть большой проблемой,
сейчас системы контроля версий используются для большинства баз кода и вклю­
чены в большинство интерактивных сред разработки, что позволяет с легкостью
создать отдельную «ветвь», в которой вы выполняете изменения, упрощающие код.
И если что-то из рефакторинга окажется важным в широком смысле, то это всегда
можно объединить с основным кодом.

82

Часть I. Об улучшении навыков чтения кода

4.2.2. Замена незнакомых языковых конструкций
В оставшейся части главы мы рассмотрим способы, помогающие бороться с тремя
возможными источниками замешательства при чтении кода (недостаток знаний,
информации и вычислительной мощности). Если в коде есть концепции програм­
мирования, с которыми вы не знакомы, то это недостаток знаний. Мы начнем со
способа, который может помочь вам в таком случае.
В некоторых ситуациях незнакомые конструкции могут быть представлены в дру­
гом, знакомом вам виде. Например, многие современные языки программирования
(такие как Java или C++) поддерживают анонимные функции, чаще всего называе­
мые лямбда-функциями. Это функции, которым не требуется имя (отсюда и их на­
звание — анонимные). Другой пример — генератор списка языка Python. Лямбдафункции и списки очень помогают сделать код короче и читабельнее, однако мно­
гие программисты не знакомы с анонимными функциями и читают такой код
с большим трудом.
Если код простой и понятный, то лямбда-функции и списки не будут представлять
проблему; однако при работе со сложным кодом такие структуры могут приводить
к перегрузке рабочей памяти. Малознакомые языковые конструкции увеличивают
внешнюю когнитивную нагрузку на рабочую память, поэтому в сложном коде
лучше их не использовать.

И хотя некоторые языковые конструкции, которые вы хотите заменить, зависят
лишь от вашего опыта и знаний, обычно есть две причины замены кода: во-первых,
эти конструкции приводят вас в замешательство, и во-вторых, у них есть простой и
понятный для вас эквивалент. Обе причины применимы к лямбда-функциям и спи­
скам, поэтому они являются хорошими примерами для демонстрации. Иногда по­
лезнее заменить их на циклы for или while — так вы снизите когнитивную нагрузку
и начнете больше понимать, что делает код. Для рефакторинга могут также исполь­
зоваться тернарные операторы.

Лямбда-функции
Код на Java из листинга 4.4 является примером анонимной функции, которая ис­
пользуется как параметр для функции filter (). Если вы знакомы с лямбда-функ­
циями, то этот код не вызовет у вас никаких трудностей.

Optional product = productList.stream().

filter(p -> p.getldO

== id).

findFirst();

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

Глава 4. Как читать сложный код

83

public static class Toetsie implements Predicate {
private int id;
Toetsie(int id){

this.id = id;

}
boolean test(Product p){

return p.getIDO == this.id;
}

}
Optional product = productList.stream().
filter(new Toetsie(id)).

findFirst();

Генератор списков
Язык Python поддерживает синтаксическую структуру под названием генератор
списков, который умеет создавать списки на основе других списков. Например,
следующий код создает список имен, используя в качестве основы список клиентов
(листинг 4.6).

customer_names = [c.first_name for с in customers]

При составлении списка можно также использовать фильтры, которые усложнят
список— например, можно создать список имен клиентов старше 50 лет (лис­
тинг 4.7).

customer_names =

[с.first_name for с in customers if c.age > 50]

И хотя тем, кто давно работает со списками, этот код покажется достаточно легким
для чтения, тем программистам, которые никогда не имели дела со списками (или
работали с ними в рамках сложного фрагмента кода), он покажется трудным. К то­
му же такой код может вызвать большую нагрузку на рабочую память. Когдаэто
происходит, для облегчения понимания вы можете преобразовать генератор списка
в цикл for (листинг 4.8).

84

Часть I. Об улучшении навыков чтения кода

customer_names = []

for с in customers:
if c.age > 50:

customer_names.append(c.first_name)

Тернарные операторы
Многие языки программирования поддерживают тернарные операторы, которые
являются сокращением операторов if. Обычно они указывают условие — если ус­
ловие истинно, то следует один результат; если условие ложно, за оператором сле­
дует другой результат. Например, в листинге 4.9 представлена строка кода
JavaScript, который с помощью тернарного оператора проверяет, является ли логи­
ческая переменная isMember истинной. Если значение переменной True, то тернар­
ный оператор возвращает 2 доллара США; в противном случае возвращается
10 долларов США.

isMember ?

'$2.00'

:

'$10.00'

Языки программирования типа языка Python поддерживают тернарные операторы
в ином порядке: сначала они показывают результат, если условие истинно, затем
условие, а затем результат, если условие ложно. Следующий пример представляет
собой строку кода на Python, которая проверяет значение логической перемен­
ной isMember с помощью тернарного оператора (листинг 4.10). Как и в примере
с JavaScript, если значение переменной True, то оператор возвращает 2 доллара
США, в противном случае возвращается 10 долларов США.

'$2.00'

if is__member else '$10.00'

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

Гпава 4. Как читать сложный код

85

каждый определяет сам для себя. Если вы знакомы с шахматными дебютами, то
вам будет намного легче запомнить шахматную расстановку. Так же ситуация об­
стоит и с тернарными файлами: если вы знакомы с ними, то вам будет легко прочи­
тать код с их содержанием. Будет ли вам легко читать код или нет, зависит от
имеющихся у вас знаний, и нет ничего плохого или стыдного в том, что вам нужно
слегка упростить код для лучшего понимания.
Однако в зависимости от вашей базы кода вы можете захотеть отменить изменения,
внесенные в код в целях повышения читабельности кода, но только при условии,
что вы действительно понимаете его. Если вы новичок в команде или единствен­
ный, кто не знаком с концепцией генератора списков, то вы можете оставить код
с внесенными в него изменениями.

4.2.3. Синонимизация — отличное дополнение
к дидактическим карточкам
Хотя нет ничего стыдного во временном упрощении кода, это указывает на ограни­
ченность вашего понимания. В главе 3 вы узнали о применении дидактических кар­
точек для обучения и запоминания (другое их название — мнемонические карточки
или словарные карточки). С одной стороны карточек вы писали подсказку, а с дру­
гой стороны — код. Например, для карточки с циклом for на одной стороне вы
могли написать «выводить все числа от 0 до 10 на C++», а с другой стороны напи­
сать соответствующий код на C++ (как это показано в листинге 4.11).

for

(int i = 0; i = 0;

System.out.printf ("%s ", words[i]);
System.out.printin();

i

)

210

Часть III. О хорошем коде

10.3.2. Почему автоматизация
помогает программировать быстрее
Мы можем создать большую базу умений и навыков (скептики назовут их уловка­
ми), которую будем постоянно дополнять новыми навыками. Американский психо­
лог Гордон Логан (Gordon Logan) утверждает, что автоматизация происходит путем
извлечения воспоминаний из эпизодической памяти, в которой также сохраняются
воспоминания об обычной жизни. Выполнение таких задач, как вынесение множи­
теля уравнения за скобки или чтение буквы, создает новое воспоминание, которое
представляет собой экземпляр воспоминаний о задаче. Так как каждое воспомина­
ние представляет собой экземпляр некоего базового класса, например класса «вос­
поминания о вынесении за скобки», теория называется теорией экземпляров.
Когда вы сталкиваетесь с похожей задачей, вы можете не думать над ней — в отли­
чие от того, у кого не хватает памяти экземпляров, — вы вспоминаете, как раньше
решали похожую задачу, и применяете уже проверенное решение. Согласно Лога­
ну, процесс автоматизации завершается в тот момент, когда вы полностью полагае­
тесь на эпизодическую память и совсем не задумываетесь над задачей. Такое авто­
матическое выполнение задач происходит очень быстро и без лишних затрат энер­
гии, т. к. извлечение из памяти необходимой информации проходит быстрее, чем
активные размышления над задачей. Если вы полностью автоматизируете выпол­
нение задачи, то у вас даже не будет нужды проверять выполненную задачу. Кстати
говоря, при осознанном выполнении задачи у вас может появиться желание вер­
нуться к выполненному заданию и перепроверить его на наличие ошибок.
Я уверена, что для многих навыков, необходимых для программирования и реше­
ния задач, вы уже находитесь на автономном этапе. Написание цикла for, индекса­
ция списка или создание класса, скорее всего, уже являются автоматизированными
навыками. Следовательно, при программировании эти задачи не будут увеличивать
вашу когнитивную нагрузку.

Однако, в зависимости от вашего опыта и навыков, могут встретиться задачи, кото­
рые вы еще не довели до автоматизма. Как я уже говорила, при изучении Python я
очень долго запоминала цикл for. Я даже дидактическими карточками пользова­
лась! Но, несмотря на практику, каждый раз, когда я садилась за написание кода,
я писала for each вместо for. Мне нужно было изменить имплицитную память.
Перед тем как мы подробно рассмотрим стратегии изменения памяти, давайте про­
верим наши навыки и определим, какие из них можно улучшить.
УПРАЖНЕНИЕ 10.4. Начните новый сеанс программирования. Подумайте
о навыках; которые вы используете при программировании. Попытайтесь по­
нять, на каком уровне автоматизации находится каждый из ваших навыков,
и запишите полученные результаты в следующую таблицу. Данные вопросы по­
могут вам определить уровень автоматизации ваших навыков.

□ Нужно ли вам уделять особое внимание навыку? Если да, то вы находитесь
на когнитивном этапе.

Гпава 10. Совершенствуем навыки решения сложных задач______________________ 211

□ Вы можете применить навык, но только полагаясь на стратегии? Если да, то
вы находитесь на ассоциативном этапе.

□ Вы можете с легкостью применить навык, размышляя при этом над другими
задачами? Если да, то вы находитесь на автономном этапе.
Навык

Когнитивный

Ассоциативный

Автономный

10.3.3. Улучшение имплицитной памяти
Теперь, когда мы знаем о трех этапах владения навыками, давайте посмотрим, как
можно использовать осознанную практику для улучшения навыков, в которых вы
еще не достигли полной автоматизации. Как говорилось в главе 2. основная идея
осознанной практики состоит в том, чтобы выполнять маленькие задачи очень мно­
го раз, пока вы не достигните совершенства. Например, в спортивной интервальной
тренировке осознанная практика увеличения скорости — это бег, а в музыке то­
нальная лестница — это осознанная практика расположения пальцев.

В программировании осознанная практика не используется. Когда вы учите созда­
ние циклов for, то осознанный набор 100 циклов for покажется чем-то странным.
Однако развитие маленьких навыков поможет вам с легкостью решать большие
задачи, т. к. вся когнитивная нагрузка будет направлена на решение этих больших
задач.
Осознанная практика может выполняться разными способами. Например, вы може­
те писать много похожих, но отличающихся друг от друга программ, и практико­
вать необходимый вам навык. Например, если вы практикуетесь в написании цикла
for, то напишите много разных циклов for: вперед, назад, с использованием пере­
менной-счетчика с разным шагом и т. д..
Когда вы сталкиваетесь со сложной концепцией программирования, вы можете
адаптировать другие программы, а не писать их с самого начала. Адаптация кода
поможет вам сосредоточить все внимание на отличии новой концепции от уже зна­
комых концепций. Например, если вы пытаетесь понять список, то сначала вы мо­
жете написать несколько программ, в которых вместо списка используются циклы.
Потом вы берете код и адаптируете его до тех пор, пока не начнете использовать
список. Вы также можете вручную отменять изменения в коде, чтобы посмотреть
на разницу. Сравнение различных версий кода и похожесть концепций укрепится
в вашей памяти — мы уже наблюдали такой процесс в главе 3, когда рассматривали
использование дидактических карточек.
Как и в случае с дидактическими карточками, интервальное повторение очень по­
могает в обучении чему-либо. Каждый день уделяйте немного времени практике и
продолжайте повторять до тех пор, пока вы не доведете выполнение задачи до ав­
томатизма. Я хочу еще раз акцентировать ваше внимание на том, что эта стратегия

212

Часть III. О хорошем коде

редко применяется в программировании. И хотя сначала она может показаться вам
странной, продолжайте пытаться. Чем-то это похоже на поднятие тяжестей: каждое
повторение делает вас и вашу память чуть сильнее.

10.4. Обучение на основе кода
и его объяснения
В этой главе мы узнали, что не существует общих навыков решения задач и что
если просто много программировать, это не поможет нам лучше решать задачи. Мы
также узнали, что вы можете использовать осознанную практику для улучшения
навыков программирования. И хотя довести небольшие навыки программирования
до автоматизма необходимо, этого недостаточно для решения больших задач.
Вторая стратегия, которой вы можете воспользоваться для улучшения навыка ре­
шения задач, — это осознанное изучение того, как другие люди решают задачи.
Знание того, как другие решают задачи, часто называют примерами с решением.

Австралийский психолог Джон Свеллер (John Sweller), сформулировавший теорию
когнитивной нагрузки, описанной в главе 4. исследовал важность зависящих от
предметной области стратегий для способностей к решению задач.

Свеллер обучал маленьких детей математике путем решения алгебраических урав­
нений. Однако вскоре его ждало разочарование: решая классические задачи по
алгебре, дети получили не так много новых знаний. В тот момент Свеллер заинте­
ресовался экспериментами со стратегией обучения решению задач. Для того чтобы
получить более подробную информацию, Свеллер в 1980-х годах сам провел не­
сколько исследований. В его исследованиях принимали участие 20 девятикласс­
ников (дети в возрасте от 14 до 15 лет) из австралийской средней школы. Он разде­
лил учеников на две группы; каждой группе предложили решить алгебраические
уравнения, например: «а = 7 - 4а; найдите значение а».
Однако между группами была разница, показанная на рис. 10.5. Обе группы реша­
ли одни и те же уравнения, но вторая группа решала уравнения без дополнительной
помощи (уверена, вы так же решали уравнения в средней школе). Первой группе
дали не только уравнения, но и примеры с решением, в которых подробно описы­
вался метод решения уравнений. Вы можете думать о примерах с решением как
о рецептах, в которых подробно описаны шаги, необходимые для решения урав­
нений.
После того как обе группы детей решили уравнения, Свеллер и Купер сравнили их
результаты. Конечно, неудивительно то, что первая группа решила уравнения бы­
стрее второй группы, т. к. у них был пример решения задачи. Первая группа решала
уравнения примерно в пять раз быстрее второй группы.

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

Гпава 10. Совершенствуем навыки решения сложных задач

213

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

Рис. 10.5. Обе группы решали одни и те же уравнения, но группе с левой стороны были даны
примеры с решением, которые показывали ученикам, как решать такие уравнения

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

10.4.1. Новый вид когнитивной нагрузки:
соответствующая нагрузка
Для многих опытных программистов результаты исследования Свеллера могли по­
казаться неожиданными. Мы часто думаем так: если нам надо, чтобы дети хорошо
справлялись с задачами, нужно просто позволить им решать их; если мы хотим
стать хорошими программистами, то нам просто нужно много программировать.
Однако результаты исследования Свеллера показывают, что это не так. Давайте
подробнее рассмотрим, почему наши мысли неверны. Почему группа, получившая
примеры решения уравнений, справилась с заданиями лучше, чем группа, которая
решала задачи самостоятельно? Объяснение, данное Свеллером, касается влияния
когнитивной нагрузки на рабочую память.
Мы уже знаем, что рабочая память — это кратковременная память, участвующая
в решении определенной задачи. Следовательно, хотя кратковременная память и
может хранить от двух до шести элементов, что уже объяснялось в главе 2. рабочая
память может обрабатывать от двух до шести слотов памяти, которые доступны
для хранения информации.

214

Часть III. О хорошем коде

Мы также знаем, что когда рабочая память заполнена, то она не может правильно
функционировать. При заполненной рабочей памяти мозг также не может переда­
вать информацию из рабочей памяти в долговременную память. Это показано на
рис. 10.6.

Рис. 10.6. Соответствующая нагрузка необходима для активации выделенной стрелки
и передачи информации в долговременную память. Если рабочая память переполнена
(т. е испытывает высокую нагрузку), то информация в долговременной памяти сохраняться не будет

Мы рассмотрели две формы когнитивной нагрузки: внутренняя нагрузка, вызван­
ная самой проблемой, и внешняя нагрузка, вызванная формулировкой проблемы.
Однако существует третья форма когнитивной нагрузки — это соответствующая
нагрузка.
Соответствующая нагрузка (означает что-то вроде необходимой нагрузки) пред­
ставляет собой процесс, с помощью которого мозг передает информацию обратно
в долговременную память. Когда вся когнитивная нагрузка состоит из внутренней
и внешней нагрузки, то места для соответствующей нагрузки не остается; говоря
другими словами, вы не сможете вспомнить уже решенные задачи и способы, кото­
рыми вы их решали.
Именно поэтому после напряженного сеанса кодирования вы не можете вспомнить,
что именно вы делали. Ваш мозг был настолько занят, что не мог запомнить ваши
действия.
Теперь, когда вы знакомы с тремя формами когнитивной нагрузки, давайте снова
обратимся к эксперименту с австралийскими девятиклассниками. Теперь мы пони­
маем, почему группа, пользовавшаяся примерами с решениями легче решала новые
уравнения: т. к. их когнитивная нагрузка была низкой, они могли запоминать при­
меры решений и применять их на практике. Они узнали, что при решении уравне­
ний нужно одну часть уравнения перенести на другую сторону от знака равенства,
что при переносе знак «плюс» меняется на знак «минус» и что они всегда могут
поделить обе части уравнения на одно и то же число.
Навыки, которые ученики приобрели во время решения уравнений с помощью
примеров с решениями, пригодятся при решении практически всех задач алгебры,
так что ученики из первой группы могут применять полученные знания при реше-

Гпава 10. Совершенствуем навыки решения сложных задач______________________ 215
нии новых уравнений. Ученики из второй группы были больше сосредоточены на
возникших сложностях, а не общих правилах решения таких уравнений.
Люди, которых волнует обучение с помощью примеров с решением, считают ина­
че. Я согласна с тем, что это звучит логично: если мы хотим, чтобы дети научились
решать задачи, то они должны просто решать задачи. Такого образа мышления
придерживаются и программисты: если мы хотим быть хорошими программиста­
ми, то нужно много практиковаться! Нужно создавать программы, пробовать чтото новое — и вы научитесь. Но, видимо, все это неправда.

Хотя исследования Свеллера сосредоточены на обучении математике, проводились
аналогичные исследования и по обучению программированию. Исследования пока­
зали похожие результаты: дети получают больше пользы из чтения программ и их
объяснений, а не из программирования1. Как говорит нидерландский психолог Пол
Киршнер (Paul Kirschner): «Если вы будете делать что-то профессиональное, то это
не сделает вас профессионалом».

10.4.2. Примеры с решением на практике
Мы уже знаем, что изучение кода и процесса его написания позволяет улучшить
навыки программирования. Есть несколько источников, которые могут вам помочь
изучать код.

Работайте вместе с коллегой
Во-первых, вы не обязаны изучать код в одиночку; намного больше пользы будет
от совместной работы над кодом. Вы можете создать кружок читателей кода или
работать с коллегами, которые в этом заинтересованы. Если вы делаете это с кемто, то вы намного быстрее привьете себе привычку регулярно читать код
(https://code-reading.org/). Если вы состоите в кружке, то вы можете обмениваться
кодом, его объяснениями и учиться друг у друга.
В главе 5 мы рассмотрели стратегии понимания кода, в том числе и резюмирование
(создание краткого пересказа кода). Вы можете изучать собственный код и пересказ
кода, однако больше пользы вы получите в том случае, если вы сначала резюми­
руете свой код, а затем обменяетесь данными с коллегой.

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

1 «The case for case studies of programming problems» Communications of the АСМ, часть 35, no. 3, 1992, Мар­
сия Линн и Майкл Клэнси, https://dl.acm.org/doi/10.1145/131295.131301.

216

Часть III. О хорошем коде

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

Читайте книги или блоги об исходном коде
В блогах можно найти множество постов, в которых люди рассказывают о своем
опыте решения задач программирования. Вы можете вооружиться знаниями других
людей и применять их в программировании. Есть также несколько книг, в которых
рассказывается о коде: например, две части книги «Архитектура open-sourceприложений» Эми Браун (Amy Brown) и Грега Уилсона (Greg Wilson) или «500 Lines
or Less» Эми Браун и Майкла ДиБернардо (Michael DiBemardo).

Выводы
□ Многие программисты считают, что навык решения задач — это общий навык,
но на самом деле это не так. Знания в области программирования влияют на
скорость решения задач программирования.
□ Долговременная память делится на несколько видов памяти, которые играют
разную роль в решении задач — это имплицитная и эксплицитная память. Им­
плицитная память — это «мышечная память», или задачи, которые вы можете
выполнять автоматически, например печать вслепую. Эксплицитная память хра­
нит информацию, которую вы точно знаете и которую вам часто нужно вспоми­
нать, например синтаксис цикла for.

□ Для укрепления имплицитной памяти, связанной с программированием, автома­
тизируйте нужные навыки: например, печатайте вслепую или запоминайте соче­
тания клавиш.
□ Для укрепления эксплицитной памяти, связанной с программированием, под­
робно рассмотрите существующий код, а также его объяснение и то, как его
писали.

О совместной работе
над кодом
X Хока что в этой книге мы рассматривали только работу отдельного программи­

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

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

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

Часть IV. О совместной работе над кодом

220

11.1. Различные активности,
выполняемые во время программирования
Когда вы занимаетесь программированием, вы делаете множество разных вещей.
Впервые эти типы активностей были описаны британскими исследователями Тома­
сом Грином (Thomas Green), Аланом Блэквеллом (Alan Blackwell) и Мариан Петре
(Marian Petre) в их концепции когнитивных измерений, которая используется для
оценки когнитивного воздействия языка программирования или базы кода (их ра­
боту мы рассмотрим более подробно в главе 12). Авторы выделяют пять типов ак­
тивностей: поиск, осмысление, переписывание, исследование и наращивание.
На рис. 11.1 представлены все пять типов активностей, и задачи, которые вы, ско­
рее всего, выполняете во время программирования. На рисунке также показано,
из-за чего каждая из активностей может казаться сложной.

Рис. 11.1. Обзор активностей и систем памяти, которые при этом используются

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

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

Гпава 11. Процесс написания кода

221

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

11.1.2. Осмысление
Осмысление кода — это активность, когда вы читаете и выполняете код с целью
понять его смысл и функциональные возможности. Эта активность похожа на по­
иск, однако на данном этапе у вас нет полного понимания того, что именно делает
код, потому что вы написали этот код много лет назад или этот код написал другой
программист.

Как мы видели в главе 5, программисты тратят около 58% рабочего времени на ос­
мысление исходного кода, так что эта активность встречается довольно часто в ва­
шей повседневной жизни.
Кроме чтения и выполнения кода осмысление может включать в себя и использо­
вание тестовых программ — так вы сможете лучше понять, как именно должен ра­
ботать код. Как мы обсуждали в главе 4. осмысление может включать в себя и ре­
факторинг, который может упростить код.
Рефакторинг кода тесно связан с осмыслением из-за того, что осмысление — это
активность, которая негативно влияет на рабочую память. Вам нужно рассуждать о
коде, который вы не совсем понимаете. Следовательно, поддержка рабочей памя­
ти — это лучшее, что вы можете сделать на данном этапе. Попробуйте начертить
модель кода и корректируйте ее каждый раз, когда узнаете что-то новое. Так вы
будете получать информацию из внешнего источника, а не из собственного моз­
га, — следовательно, снизится нагрузка на вашу память. Модель кода также помо­
жет вам понять, есть ли у вас неверные представления о коде. К тому же если вы не
можете за один раз закончить этап осмысления, то сделанные вами заметки и мо­
дель помогут вам быстро вернуться к работе.

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

При переписывании задействована долговременная память, т. к. вам постоянно
нужно вспоминать синтаксические конструкции.

222

Часть IV. О совместной работе над кодом

11.1.4. Наращивание
Наращивание включает в себя поиск, осмысление и переписывание. Когда вы рас­
ширяете базу кода, вы добавляете новый функционал, что включает в себя поиск
мест(а), куда добавить код, а также осмысление уже существующего кода, чтобы
знать, куда именно нужно добавить код, а затем воплощение идеи в синтаксисе,
т. е. переписывание.
Так как наращивание включает в себя несколько действий, то данный этап может
быть труден для всех трех видов памяти. Поэтому задачи наращивания, с которыми
постоянно имеют дело опытные программисты, нуждаются в поддерже памяти
в форме заметок, а также в рефакторинге, чтобы код стал легче для осмысления.
Ваш опыт работы с определенным языком программирования и базой кода влияет
на то, какая память будет принимать наибольшее участие в активности. С одной
стороны, если вы хорошо знаете язык программирования, то ваша долговременная
память не будет напрягаться над вспоминанием синтаксиса. С другой стороны,
если вы знаете кодовую базу, то ваша рабочая память и кратковременная память
могут не испытывать нагрузки на этапе поиска и осмысления кода.

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

11.1.5. Исследование
Последняя активность, которая рассматривается Грином, Блэквеллом и Петре,—
это исследование кода. При исследовании вы по существу делаете «наброски» кода.
Вы можете иметь приблизительное представление того, над чем вы будете работать
дальше, но в процессе программирования вы все больше будете узнавать о пред­
метной области задачи и конструкциях, которые вам нужно использовать в коде.

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

Гпава 11. Процесс написания кода__________________________________________ 223
ким образом вы сможете освободить место в рабочей памяти для более глубокого
обдумывания задачи.

11.1.6. А как же отладка?
При обсуждении данной концепции разработчики часто задают вопрос: почему
среди активностей нет отладки? Ответ прост: обычно при отладке задействованы
сразу все пять активностей. Отладка ведет к исправлению ошибки, но иногда перед
тем, как исправить ее, вы должны выполнить поиск местоположения ошибки.
Соответственно отладка представляет собой последовательность исследования, по­
иска и осмысления, а затем написания кода. Очень часто отладку можно описать
как сочетание всех пяти активностей.

УПРАЖНЕНИЕ 11.1. В следующий раз, когда вы будете заниматься програм­
мированием, подумайте о пяти активностях из концепции когнитивных измере­
ний. Какая активность занимает больше времени? С какими препятствиями вы
столкнулись при работе с кодом?
Активность

Задача

Затраченное время

Поиск
Осмысление
Переписывание

Исследование
Наращивание

11.2. Программист отвлекся
Сегодня множество программистов работают в офисах открытого типа, где отвле­
кающие факторы — вещь обыденная. Но как отвлечение сказывается на мозге и
нашей продуктивности? Рини ван Солиген (Rini van Solingen), профессор Делфтского технического университета в Нидерландах, еще в середине 90-х годов изучал
влияние отвлечения на работу программиста.

Ван Солиген провел исследование, в котором он изучал две организации. Исследо­
вание показало похожие результаты в обеих организациях. Он обнаружил, что
отвлечение— это обычная вещь в «жизни» программиста, и каждое отвлечение
занимает от 15 до 20 мин. Около 20% всего рабочего времени программист отвле­
кается, а с ростом использования Slack и других мессенджеров отвлечение стано­
вится распространенным явлением1.

1 «Interrupts: Just a Minute Never Is», IEEE Software, ч. 15, № 5, Рини ван Солиген и др.,
https://ieeexplore.ieee.org/document/714843 .

224

Часть IV. О совместной работе над кодом

Существуют и более свежие исследования. Например, Крис Парнин, чью работу
мы рассмотрели в главе 3, также исследовал отвлечение: он записал 10 000 сеансов
программирования 86 программистов. Результаты этого исследования подтвердили
вывод ван Солигена касаемо того, что прерывания уже стали частью рабочей жизни
программиста. Согласно исследованию Парнина2, средний программист без отвле­
чений работает только два часа в день. Программисты также согласны с тем, что
отвлечение — это проблема. Исследование Microsoft показало, что примерно 62%
программистов считают возвращение к работе после отвлечения большой про­
блемой3.

11.2.1. Задачи программирования
нуждаются в «разогреве»
В главе 9 мы рассмотрели аппарат fNIRS как способ измерения когнитивной
нагрузки. С помощью данного аппарата мы узнали не только то, какие типы кода
вызывают нагрузку, но также и то, на какие задачи приходится больше всего на­
грузки.

В 2014 году Такао Накагава, исследователь из Института науки и технологий Нары
в Японии, измерил активность мозга с помощью аппарата fNIRS4. Участников по­
просили прочитать два варианта алгоритма, написанных на С. Первый вариант был
обычным, в то время как второй вариант был специально усложнен. Например,
были заменены счетчики циклов и другие значения, из-за чего переменные ме­
нялись часто и нерегулярно. Данные изменения не повлияли на функциональные
возможности программы.
Накагава получил два интересных результата. Во-первых, у 9 из 10 участников во
время выполнения задания когнитивная нагрузка не была постоянной величиной.
Процесс программирования сложный не все время: какие-то моменты вызывают
трудности, а другие делаются за пару мгновений. Во-вторых, исследователи отсле­
живали место в коде, где у участника максимально повышался кровоток и соответ­
ственно когнитивная нагрузка. Результаты показали, что именно в середине зада­
ния наблюдалась самая высокая когнитивная нагрузка.
Результаты исследования Накагавы указывают на то, что в задачах на осмысление
кода есть своего рода фаза разогрева и фаза охлаждения, между которыми работа
выполняется максимально интенсивно. Опытные программисты, вероятно, вспом­
нят это время разогрева, необходимое для того, чтобы «войти в форму», нужную
для построения воображаемой модели кода и переписывания кода. Как уже обсуж2 «Resumption Strategies for Interrupted Programming Tasks», Крис Парнин и Спенсер Ругабер,
https://ieeexplore.ieee.org/document/5090030.

3 «Maintaining Mental Models: A Study of Developer Work Habits», Томас ЛаТоза и др.,
https://dl.acm.org/doi/10.1145/1134285.1134355 .
4 «Quantifying Programmers’ Mental Workload during Program Comprehension Based on Cerebral Blood Flow
Measurement: A Controlled Experiment», Такао Накагава и др.,
https://posl.ait.kyushu-u.ac.jp/~kamei/publications/Nakagawa_lCSENier2014.pdf.

Глава 11. Процесс написания кода

225

далось ранее в этой главе, это может помочь выделить подзадачи в большой задаче
программирования.

11.2.2. Что происходит после отвлечения
Парнин также исследовал, что происходит после отвлечения от работы, и результат
его нисколько не удивил — отвлечение сильно снижает эффективность. После пре­
рывания программисту требуется около 15 мин, чтобы вернуться к работе. Если
программиста отвлекают на этапе редактирования метода, то сразу же возобновить
работу менее чем за минуту удается только в 10% случаев.
Что программисты делают для того, чтобы вернуться к работе над кодом? Согласно
результатам Парнина, рабочая память теряет важную информацию о коде, над ко­
торым работает программист. Участники его исследования должны были прило­
жить усилия для того, чтобы восстановить контекст. Для этого многие из участни­
ков просматривали несколько мест кода и только потом продолжали программиро­
вать. Некоторые из участников специально вставляли в код мелкие ошибки,
например случайные символы, из-за которых происходила ошибка компиляции.
Это служило тем, что Парнин назвал указателем путевого заграждения. — своего
рода гарантией того, что код будет доведен до конца, а не останется в наполовину
завершенном состоянии. Некоторые участники, чтобы вернуться к работе, также
искали разницу между рабочей версией кода и исходной.

11.2.3. Как подготовиться к отвлечению
Теперь, когда мы знаем, что отвлечение— это дело обычное и его очень редко
можно избежать, давайте посмотрим, что происходит в вашем мозге, когда вас от­
влекают. Так мы сможем лучше подготовиться к отвлечению. В этой главе мы рас­
смотрим три стратегии, которые помогут нам справиться с отвлечением.
1) Дай мне сохранить
< ментальную модель.

Можно кое-что
спросить?

2) Конечно, потому что
/ я поддерживаю проспективную память
3) Конечно, потому что я уже определился
с промежуточными целями.

Рис. 11.2. Три способа возвращения к работе

Сохраняйте воображаемую модель
Ранее мы уже обсуждали стратегии, которые можно использовать для поддержки
рабочей и кратковременной памяти: например, создание заметок и комментариев,

226

Часть IV. О совместной работе над кодом

визуализация моделей и рефакторинг кода. Данные стратегии могут быть полезны
и для возвращения к работе после перерыва.
Результаты исследования Накагавы показали, что на фазе разогрева программист
чаще всего создает воображаемую (ментальную) модель кода. Если фрагменты мо­
дели находятся вне кода, то тогда вы быстро сможете восстановить всю модель.
Также полезно писать заметки о модели в комментариях кода.
Некоторые программисты не одобряют написание подробных комментариев, т. к.
вся нужная информация должна находиться в коде. Однако очень редко в коде
можно отследить когнитивную деятельность программиста, из-за чего чаще всего
создается неправильная воображаемая модель автора кода. Мы не привыкли объяс­
нять в коде то, почему был выбран определенный подход, каковы наши цели или
какие варианты рассматривались для реализации кода. Но когда подобные мысли
нигде не записаны, то вы можете прийти к ним лишь случайно; в любом случае, это
довольно долгий и сложный процесс. Джон Оустерхаут (John Ousterhout) описыва­
ет данный момент в своей книге «The Philosophy of Software Design» (Yaknyam
Press, 2018) так: «Общая идея комментариев заключается в хранении информации,
о которой думал программист, но которая не была отражена в самом коде».
Кроме того, что заметки очень полезны для людей, читающих код, документирова­
ние решений может быть полезным также для временного хранения вашей вообра­
жаемой модели, что значительно упрощает возвращение к работе после долгого
перерыва. Фред Брукс в своей книге «Мифический человеко-месяц» пишет, что
комментарии очень важны на этапе осмысления программы, потому что они всегда
под рукой. И хотя комментарии на листке или в документе очень полезны, поиск
нужных документов, когда вы возвращаетесь к работе, может привести к тому, что
вы будете пытаться запомнить лишнюю информацию.

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

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

Тема поддержки проспективной памяти освещалась в нескольких исследованиях.
В них описывается, как программисты пытаются справиться с плохой проспектив­
ной памятью. Например, программисты часто добавляют к фрагменту, над которым

Гпава 11, Процесс написания кода

227

они работают, заметки to-do, которые потом напомнят им о том, что фрагмент кода
нужно закончить или как-то улучшить5. Естественно, и многие программисты это
могут подтвердить, к подобным комментариям часто не возвращаются и не закан­
чивают то, что в них написано. На рис. 11.3 показана история поиска на GitHub, из
которого видно, что код со словом to-do запрашивался 136 миллионов раз.

Рис. 11.3. Заметки to-do могут оставаться в коде невыполненными

Кроме заметок to-do и умышленных ошибок компиляции программисты также
применяют стратегии, которыми пользуются другие офисные работники: на рабо­
чий стол они вешают стикеры и отправляют письма на свою электронную почту.
Конечно, стикеры и электронные письма не имеют никакого отношения к кодовой
базе, но они тоже могут быть очень полезны.
Парнин также разработал плагин для Visual Studio, который позволяет программи­
стам поддерживать проспективную память в тот момент, когда им нужно прервать
5 «TODO or to Bug: Exploring How Task Annotations Play a Role in the Work Practices of Software Developers»,
Маргарет Энн Стори и др., https://dx.doi.org/doi: 10.1145/1368088.1368123.

228

Часть IV. О совместной работе над кодом

работу6. Например, плагин позволяет добавлять элементы to-do в код и указывать
дату, до которой их нужно выполнить.

Определитесь с промежуточными целями
Третья стратегия, которая поможет вам быстро вернуться к работе, называется оп­
ределением промежуточных целей. Данная стратегия подразумевает, что вы будете
записывать то, на какие небольшие этапы можно разбить задачу. Например, при
синтаксическом анализе и реструктуризации текста можно выделить такие этапы:

1. Разобрать текст в дерево синтаксического анализа.

2. Отсортировать дерево синтаксического анализа.
3. Преобразовать дерево синтаксического анализа обратно в текст.
Эти этапы легко запомнить, но если вас часто отвлекают от работы, то у вас могут
возникнуть трудности с возвращением к работе над кодом и осознанием, что вы
собирались делать. Если я работаю с большой задачей, то сначала я пытаюсь напи­
сать все этапы в виде комментариев в моемкоде, например:
# выполнить синтаксический анализ текста
# получить дерево синтаксического анализа
# отсортировать дерево синтаксического анализа и
# преобразовать дерево обратно в текстовый формат

Следовательно, я могу писать такие заметки в каждом фрагменте кода; в таком
случае у меня всегда есть план, которого я буду придерживаться. Исследование
программистов, проведенное Лорен Маргуле (Lauren Margulieux), профессором
кафедры образовательных наук Университета штата Джорджия, показало, что
предлагаемые вами промежуточные цели программисты используют для создания
воображаемой модели решения задачи7.
Промежуточные цели полезны для организации собственных мыслей после дли­
тельного отвлечения, однако они могут быть полезны и в других ситуациях. На­
пример, некоторые промежуточные цели, написанные в самом коде, могут так и
остаться в виде комментариев и стать частью документации кода. Промежуточные
цели также могут использоваться при совместной работе, когда опытный програм­
мист разрабатывает промежуточные цели, а его подчиненные программисты вы­
полняют их.

11.2.4. Когда отвлекать программиста
В главе 9 мы рассмотрели различные способы измерения когнитивной нагрузки,
с которой сталкиваются люди. Но есть и другие способы определения когнитивной
нагрузки, которую вызывает та или иная задача.

6 https://marketplace.visualstudio.com/items?itemName=chrisparnin.attachable*
7 «Subgoal-Labeled Instructional Material Improves Performance and Transfer in Learning to Develop Mobile
Applications», Лорен Маргуле и др., https://doi.org/10.1145/2361276.2361291

Гпава 11 Процесс написания кода__________________________________________ 229
Один из примеров — это измерение скорости выбора при выполнении двух совме­
щенных действий. Выполнение двух совмещенных действий — это две задачи, од­
на из которых выполняется в тот момент, когда человек решает исходную задачу.
Например, при решении уравнения на экране в случайное время появляется буква А.
Когда появляется эта буква, участник должен как можно быстрее нажать клавишу
с этой буквой. То, насколько быстро и точно участник выполнит вторую задачу,
является показателем того, какую когнитивную нагрузку испытывает человек. Ис­
следователи считают, что измерение скорости выбора при выполнении двух со­
вмещенных действий может быть хорошим способом оценки когнитивной нагруз­
ки. Как вы уже могли догадаться, у данного способа есть свои недостатки: вторая
задача тоже вызывает когнитивную нагрузку, отвлекая от исходной задачи.
Используя такой способ измерения, исследователи изучили связь между когнитив­
ной нагрузкой и отвлечениями. Брайан Бэйли (Brian Р. Bailey), профессор компью­
терных наук Иллинойского университета, большую часть своей карьеры посвятил
исследованию причин и последствий отвлечения.
В исследовании, проведенном в 2001 году8, приняло участие 50 человек. Участни­
кам предложили выполнить задание, во время которого их будут отвлекать.
В эксперименте использовались разные типы задач, от подсчета частоты появления
слов в сетке до чтения текста и ответов на вопросы. При выполнении этих задач
участников отвлекали нерелевантной информацией, например показывали заголов­
ки последних новостей или обновления фондового рынка. Это исследование прово­
дилось как эксперимент с двумя группами участников. Одну группу постоянно от­
влекали, пока участники выполняли основную задачу, а другую группу отвлекали
после выполнения задачи.
И хотя результаты исследования Бэйли не оказались чем-то удивительным, они по­
могают понять отвлечение. Бэйли обнаружил, что выполнение задачи, когда тебя
отвлекают, занимает намного больше времени, чем выполнение задачи, когда тебя
не отвлекают. Он также выяснил, что людям, которых постоянно отвлекают, зада­
ния кажутся более сложными.
Бэйли измерял не только время и сложность задач, но и исследовал эмоциональное
состояние участников во время всего исследования. Участники отвечали на вопро­
сы, в которых их просили определить уровень их раздражения и беспокойства каж­
дый раз, когда появлялась отвлекающая задача. Результаты опроса показали, что
уровень раздражения зависит от отображения прерывающей задачи. Участники
группы, которые отвлекались во время выполнения основной задачи, были раздра­
жены больше, чем участники второй группы. То же самое касается и уровня беспо­
койства. Участники, которых отвлекали, испытывали больше стресса. Повторное
исследование 2006 года, в котором использовалась похожая схема, показало, что
участники, которых отвлекали, совершали в два раза больше ошибок9.

8 «The Effects of Interruptions on Task Performance, Annoyance, and Anxiety in the User Interface», Брайан Бэй­
ли и др., http://mng.bz/G6KJ,
9 «On the Need for Attention-Aware Systems: Measuring Effects of Interruptions on Task Performance, Error Rate,
and Affective State», Computers in Human Behavior, ч. 22, № 4, стр. 685-708, 2006, Брайан Бэйли,
http://mng.bz/zGAA.

230

Часть IV. О совместной работе над кодом

Основываясь на этих результатах, мы могли бы сделать вывод, что программистам,
которым постоянно приходится отвлекаться, может быть полезнее отвлекаться
в более подходящее время (например, после выполнения основной задачи). Осно­
вываясь на этой идее, Мануэла Цюгер (Manuela Ziiger), в то время аспирант
Цюрихского университета, разработала интерактивный светильник FlowLight.
FlowLight (https://emea.embrava.com/pages/flow) — это аппаратный источник све­
та, который программист размещает на рабочем столе или возле экрана компьюте­
ра. На основе действий с компьютером, например скорости набора или щелчков
мышью, FlowLight определяет, насколько глубоко программист погружен в задачу
и испытывает ли он высокую когнитивную нагрузку. Обычно такое состояние на­
зывают «в ударе» или «в потоке». Если программист находится «в ударе» и его
нельзя отвлекать, то на FlowLight мигает красный индикатор. При меньшей актив­
ности красный индикатор FlowLight постоянно светится. Если разработчика можно
отвлечь, то на FlowLight будет светиться зеленый индикатор.
Цюгер опробовала FlowLight в большом исследовании с более чем 400 участ­
никами из 12 стран и обнаружила, что FlowLight помогает сократить количество
отвлечений на 46%. Многие участники исследования продолжили использовать
FlowLight даже после окончания исследования. FlowLight также доступен для по­
купки10.

11.2.5. Пара слов о многозадачности
Читая об отвлечении, вы могли задуматься о многозадачности. Неужели отвлече­
ние настолько плохо? Разве наш мозг не может выполнять одновременно несколько
задач, подобно многоядерному процессору?

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

Вспомните три этапа сохранения информации: когнитивный этап, ассоциативный
этап и автономный этап. Или, говоря другими словами, вы не можете делать два
или более дела одновременно, если вы не достигли в них автономного этапа. На­
пример, чтение на родном языке — это не то, чему вам все еще необходимо учить­
ся, так что вы можете что-то читать или слушать на нем, параллельно с этим зани­
маясь другими делами, которые также автоматизированы, например вязанием. Но
когда вы читаете особенно сложный отрывок книги, наполненный множеством но­
вых идей, то вы скорее всего выключите музыку и сосредоточитесь на тексте. Это
10 «Reducing Interruptions at Work: A Large-Scale Field Study of FlowLight», Мануэла Цюгер,
https://www.zora.uzh.ch/id/eprint/136997/l/FlowLight.pdf

Глава 11. Процесс написания кода

231

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

Исследования многозадачности
В 2009 году Энни Бет Фокс (Annie Beth Fox), сейчас профессор количественных
методов исследований Института медицинских профессий Массачусетской боль­
ницы общего профиля11, сравнила студентов, которые читали текст и одновременно
обменивались сообщениями, и студентов, которые работали только с текстом. Обе
группы понимали текст одинакового хорошо, но группе, которая отвлекалась на
переписку, потребовалось на 50% больше времени как на чтение текста, так и на
ответы на вопросы по теме.
В 2010 году нидерландский психолог Пол Киршнер (Paul Kirschner) провел иссле­
дование, в котором приняли участие около 200 студентов. В исследовании Кирш­
нер спросил их об их пристрастии к Facebook. Активные пользователи учились так
же долго, как и те участники, которые не были пользователями Facebook, однако
средний балл активных пользователей соцсети был значительно ниже. Данный вы­
вод особенно верен для тех студентов, которые отвечают на сообщение сразу после
его получения. Интересен тот факт, что люди, которые выполняют сразу несколько
задач, чувствуют себя очень продуктивными12.

В исследовании, где студенты выполняли упражнение, одновременно переписыва­
ясь с партнером, сами студенты оценили свою успеваемость как удовлетворитель­
ную, в то время как их партнеры оценили их успеваемость намного ниже. Это мо­
жет означать то, что не стоит совмещать программирование и переписку в Slack13.

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

11 «Distractions, Distractions: Does Instant Messaging Affect College Students’ Performance on a Concurrent Read­
ing Comprehension Task?» Cyberpsychology and Behavior, ч. 12, стр. 51-53, 2009, Энни Бет Фокс и др.,
https://doi.org/10.1089/cpb.2008.0107 .
12 «Facebook® and Academic Performance», Computers in Human Behavior, ч. 26,№ 6, стр. 1237-1245, 2010,
Пол Киршнер и Эрин Карпински, http://mng.bz/jBze.
13 «Impact of Simultaneous Collaborative Multitasking on Communication Performance and Experience», Линбэй
Сюй (2008), http://mng.bz/EVNR.

232

Часть IV. О совместной работе над кодом

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

□ Для того чтобы снизить негативный эффект отвлечения, делайте заметки или
комментарии.

□ Сознательно поддерживайте проспективную память: если вы не можете что-то
сделать, создайте план действий.
□ В периоды низкой когнитивной нагрузки постарайтесь ограничить количество
отвлечений: например, с помощью автоматизации и использования FlowLight
или вручную, поменяв свой статус в Slack.

До этого момента мы обсуждали то, как лучше всего читать и писать код. Мы изу­
чили, какие когнитивные процессы участвуют при чтении и написании кода. Одна­
ко при работе с большими базами кода на понимание влияют не только мелкие
фрагменты кода. Способ организации кода также играет роль в том, как легко лю­
дям будет взаимодействовать с кодом. Это особенно верно для кода библиотек,
фреймворков и модулей, которые другие люди не изменяют, а просто используют.
Очень часто, когда мы говорим о библиотеках, фреймворках или модулях, мы го­
ворим об их технических аспектах, к примеру языке, на котором они написаны. Но
базы кода можно рассматривать и с когнитивной точки зрения. В этой главе мы
рассмотрим концепцию когнитивных измерений— методику изучения баз кода
с когнитивной точки зрения. Концепция когнитивных измерений может помочь вам
ответить на вопросы о больших базах кода, например: «Этот код потом будет про­
сто изменить?» или «Смогут ли потом другие люди найти информацию в этой базе
кода?». Изучение баз кода с когнитивной точки зрения поможет вам лучше понять,
как другие люди взаимодействуют с вашим кодом.
После того как мы рассмотрим концепцию когнитивных измерений и то, как она
может поддержать наше понимание баз кода, мы подробнее изучим то, как эту кон­
цепцию можно использовать для улучшения структуры уже существующих баз ко­
да. Данное улучшение проводится с помощью когнитивного измерения базы кода.

234

Часть IV. О совместной работе над кодом

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

12.1. Проверка свойств базы кода
Очень часто, когда мы говорим о библиотеках, фреймворках или модулях, мы го­
ворим об их технических аспектах. Обычно мы говорим: «Эта библиотека написана
на Python», «В этом фреймворке используется node.js» или «Этот модуль был зара­
нее скомпилирован».

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

Но когда мы думаем о библиотеке, модуле, фреймворке или языке программирова­
ния, мы также можем задуматься о том, что они делают с нашим мозгом, а не ком­
пьютером.
УПРАЖНЕНИЕ 12.1. Подумайте о кодовой базе, на которой вы недавно рабо­
тали, но которую не составляли сами. Это может быть библиотека, код которой
вам нужно было прочитать для того, чтобы понять алгоритм вызова функции,
или фреймворк, в котором вы исправляли ошибки.
Теперь ответьте на следующие вопросы:

□ Что именно облегчило выполнение задачи (например, документация, пра­
вильные имена переменных, комментарии)?

О Что именно затруднило выполнение задачи (код был сложным, отсутствие
документации)?

12.1.1. Когнитивные измерения
Концепцию когнитивных измерений (CDN, cognitive dimensions of notations) можно
использовать для оценивания удобства использования баз кода. Изначально данная
концепция была создана британскими учеными Томасом Грином, Аланом Блэквел­
лом и Мариан Петре. Концепция включает в себя несколько измерений, каждое из
которых представляет собой отличный способ исследования баз кода. Изначально
измерения были созданы для изучения визуализаций, например схем, однако затем
их применили к языкам программирования. Языки программирования, как и схемы,
можно рассматривать как нотации, т. е. способ выражения мыслей.

Измерения, описанные Грином, Блэквелом и Петре, используются только по отно­
шению к нотациям, но в этой книге мы используем их при работе с базами кода,

Гпава 12. Проектирование и усовершенствование больших систем_______________ 235

а не языками программирования. Мы называем эти измерения когнитивными изме­
рениями баз кода (CDCB, cognitive dimensions of codebases) и используем их для
изучения баз кода. Так мы понимаем, что нужно изменить, дополнить или улуч­
шить. Когнитивные измерения баз кода особенно полезны для таких баз кода,
которые очень часто используются, но не изменяются другими пользователями.
Сначала мы подробно рассмотрим каждое из измерений по отдельности, а потом
изучим то, как измерения взаимодействуют друг с другом и как их можно исполь­
зовать для улучшения баз кода.

Подверженность ошибкам
Первое измерение, которое мы с вами рассмотрим, — это подверженность ошиб­
кам. При работе с одними языками программирования шанс сделать ошибку выше,
чем с другими. Например, JavaScript является одним из самых популярных языков
программирования, но, как нам известно, при его использовании нужно обращать
внимание на множество особенностей.
На JavaScript и некоторых других языках с динамической типизацией при создании
переменные не инициализируются сразу с типом. Так как во время выполнения
кода непонятно, какой это тип объекта, программисты могут запутаться в типах
переменных и совершить ошибку. К тому же неожиданное изменение типа пере­
менной тоже может привести к ошибкам. Считается, что языки со строгой системой
типов, например Haskell, менее подвержены ошибкам, т. к. при кодировании про­
граммист понимает тип каждого элемента.
В базах кода также могут совершаться ошибки, например из-за отсутствия доку­
ментации или непонятных имен переменных.

Иногда базы кода «наследуют» измерения от языка программирования, на котором
они были написаны. Например, написанный на Python модуль сильнее подвержен
ошибкам, чем библиотека, написанная на С, т. к. у Python нет строгой системы
типов.
Системы типов, предотвращающие ошибки

Вы можете заинтересоваться, а правда ли то, что системы типов предотвращают
ошибки. На основе множества экспериментов по сравнению Java и Groovy немецкий
исследователь Стефан Ханенберг (Stefan Hanenberg) показал, что системы типов
действительно могут помогать в нахождении и исправлении ошибок. Во многих случа­
ях в исследовании Ханенберга место, на которое компилятор указывал как на ошибку,
совпадало с местом, на котором при выполнении вылетал код. Выполнение кода
занимает много времени, поэтому лучше не стоит проверять ошибки с помощью вы­
полнения кода.
Ханенберг испробовал разные способы по улучшению кода, написанного на языке
с динамической типизацией. Он пытался уменьшить его подверженность ошибкам
с помощью интерактивных средств разработки и документации, но даже в таком слу­
чае в кодах, написанных на языке с динамической типизацией, наблюдалось множест­
во ошибок.

Часть IV. О совместной работе над кодом

236

Согласованность
Другой способ изучения того, как люди будут взаимодействовать с языком про­
граммирования или базой кода, — это согласованность. Насколько похожи эле­
менты? Всегда ли имена структурированы одинаково? В них используется та же
форма, которую мы обсуждали в главе? У разных классов одинаковое расположе­
ние файлов?

Пример, когда многие языки программирования демонстрируют согласован­
ность — это определение функций. Может быть, вы никогда не задумывались об
этом, но у встроенных функций тот же интерфейс, что и у пользовательских функ­
ций. Когда ВЫ СМОТрИТе На ВЫЗОВ фуНКЦИИ, например print () ИЛИ print customer о,
вы не видите создателя функции, создателя языка программирования или создателя
кода.
Фреймворк или язык, которые не согласованны в использовании имен или согла­
шений, могут привести к увеличению когнитивной нагрузки, т. к. вашему мозгу
потребуется больше энергии для того, чтобы понять, что к чему относится. Вам
также может потребоваться больше времени для того, чтобы найти нужную ин­
формацию.
Как мы видели в главе 9. согласованность связана с подверженностью ошибкам.
Код, в котором встречаются лингвистические антипаттерны проектирования, под­
вержен ошибкам и вызывает дополнительную когнитивную нагрузку.

Размытость
Ранее мы рассмотрели запахи кода, которые могут затруднить чтение кода. Напри­
мер, запах кода «Длинный метод», который заключается в том, что метод или
функция состоят из множества строк. Длинный метод всегда затрудняет понимание
информации.

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

Например, цикл

for

на Python выглядит так:

for i in range(10):
print(i)

Ha C++ этот же код будет выглядеть так:
for

(i=0;

i