🧠 Резюме мозга программиста
Предлагаем рассмотреть краткое изложение книги «Мозг программиста», чтобы лучше понять, как программисты работают, думают и ведут себя.
Перевод публикуется с сокращениями, автор оригинальной статьи Stewart Wolfe.
Часть первая. Лучше читать код
Понимание
Все знают, что мы читаем код больше, чем пишем. Тем не менее, мы все еще не пишем код для чтения. Чтобы написать что-то в удобочитаемой, компактной форме приходится приложить сознательные усилия. Мы оптимизируем скорость и структуру, но редко (если это делаем), оптимизируем читаемость для понятности, чтобы угодить читающему, заглянуть вперед и подумать, кем и как этот код будет прочитан вновь…
Данная часть предлагает несколько решений для облегчения этой боли.
Источник
Определяет три момента: недостаток знаний, недостаток информации и недостаточная вычислительная мощность.
Недостаток информации – вы не знаете достаточно о проекте/коде, который ищете.
Недостаток знаний – отсутствие знаний о том, что вы делаете, например, непонятный синтаксис языка, с которым не знакомы.
Отсутствие мощностей – кусок кода, который используете слишком большой, или вам сложно разбить его на мелкие логические части.
В книге говорится о том, как работает когнитивная нагрузка и почему необходимо заботиться о ней (более подробно это описано в книге). В основном все дело в том, насколько сложным что-то выглядит, пока у вас не будет достаточного опыта в долговременной памяти, чтобы иметь возможность мгновенно все расшифровать.
Нехватка вычислительной мощности устраняется за счет заметок, функций и переменных о коде, который вы пишете. Используя «второй мозг» (бумагу), вы облегчаете нагрузку на свою текущую рабочую память. Кроме того, может быть полезно преобразовать что-то, что вы понимаете и с чем уже знакомы. Например, разбивая список Python на циклы for, пока не поймете все целиком. Затем все снова соберите вместе и перечитайте еще раз.
Недостаток знаний исправляется изучением указанной темы – так вы становитесь в ней лучше.
Недостаток информации можно поправить и чтением.
Чтение
Затем в книге объясняется, как быстрее читать код на примерах исследований, проведенных с экспертами и программистами.
Как бы сильно Go-разработчики не любили говорить о шаблонах дизайна в Go, они существуют не просто так. Причина в том, что существуют распространенные проблемы, имеющие известные, проверенные решения. И именно от этого зависит скорость чтения. Паттерны. Чем больше паттернов вы распознаете, тем быстрее читаете код.
for loops, if err != nil
Теперь это укоренилось в вашей памяти, и можно в будущем быстро это прочитать.
Это означает, что для
того, чтобы помочь с чтением вашего кода, необходимо сосредоточиться на маяках.
Маяки – это небольшие, понятные с первого взгляда части кода. Комментарии,
шаблоны, такие как if err != nil
, цепочки, правильные имена функций – все это
маяки, которые помогают лучше понимать и читать код.
Для быстрой скорости чтения кода вы должны узнавать шаблоны с первого взгляда. Практикуйтесь, пока не выучите их. Например, не нужно смотреть дважды на мост над водой, чтобы определить, что это мост, верно? Вы знаете, что это мост, потому что он выглядит как мост. Он мог бы быть и над улицей, но все равно был бы мостом.
Чтобы иметь возможность учиться быстрее, в книге, как и во всех источниках, предлагается использовать интервальное повторение.
Одно из лучших предложений, которые я почерпнул из этой книги, заключается в том, что если вам приходится что-то гуглить во второй раз, потому что вы не помните, как это работает, вы тратите время впустую и увеличиваете свою когнитивную нагрузку. Вместо этого, приложите усилия, чтобы запомнить все с первого раза с помощью предложенных выше советов и записать информацию своими словами, а затем используйте интервальное повторение.
Часть вторая. Размышления о коде
Стратегии чтения
Затем мы переходим к чтению и пониманию кода. Данные, подтвержденные исследованиями, доказывают, что математические знания не помогут лучше понять код, а лингвистические подкрепляют навыки программирования больше, чем математические. Логические – самые крутые и помогают намного больше.
Эффективное чтение можно разбить на следующие этапы:
- Активация – попробуйте запомнить моменты, которые связаны или похожи на то, что вы читаете.
- Мониторинг – проверяйте свое понимание по мере продвижения.
- Определение важности – отбросьте несущественные вещи.
- Делать выводы – вычленять только те вещи, о которых идет речь в тексте.
- Визуализация – рисование помогает только в том случае, если вы визуал. Необходимо делать все, что поможет вам в усвоении.
- Вопросы – без возвращения назад ничего не отложится.
- Подведение итогов – напишите резюме своими словами.
Когда вы читаете код, сначала разбирайтесь с мелкими частями, а понимание более широкой картины придет позже. Хотя, все люди разные – кто-то может понять общую картину намного проще, чем короткий кусок. В любом случае, это хорошее упражнение.
В книге разделяются переменные, основанные на поведении. Это может помочь лучше понять код после его прочтения. Используются следующие 11 категорий:
- Follower
- Stepper
- Walker
- Temporary
- Counter/Gatherer
- Container
- Fixed value
- Flag
- Organizer
- Most-recent Holder
- Most-wanted Holder
Они не требуют пояснений, но пометка переменных может дать вам представление об их назначении. В последствии, вы можете переработать их или обозвать соответствующим образом.
Решение проблем
Ментальные модели
То, как вы мысленно создадите модель проблемы, определит, как вы будете ее решать. Это означает, что, если решение кажется ошибочным, вам просто может потребоваться изменить свою модель проблемы или данные, представляющие ее. Ментальной моделью может быть все, что представляет логику кода: диаграммы, графики, состояние.
Мышление моделями о логике кода является важным навыком. Абстрагирование проблемы может дать огромную пользу в ее решении.
Чем больше общих ментальных моделей вы храните в своей долговременной памяти, тем легче будет выявлять и решать проблемы. Используйте любой способ для запоминания как можно больше ментальных моделей.
Условные машины
Лучший способ описать условную машину – это абстракция исполняемого кода. Своего рода ментальная модель, но она всегда верна. Нормальная ментальная модель может быть неверной. Условные машины помогают понять, как работает машина и выполняется код. Существует несколько машин, которые могут работать вместе. Чтобы узнать о них больше, либо прочтите книгу, либо исследовательскую статью о них.
Заблуждения
Это интересно и заслуживает объяснения. Вы должны постоянно проверять свои предубеждения в отношении кода, концепций и своих ментальных моделей. В противном случае вы попадете в рутину постоянного использования неправильной модели. Это не всегда легко, потому что поначалу это может быть неочевидно. Но никогда не думайте, что ваши знания априори правильные. Конечно, существуют такие аксиомы, как 1 == 1, которые всегда будут верны, но это не значит, что концепция, которую вы используете, является аксиомой.
Всегда читайте документацию и код текущего проекта, над которым работаете, тщательно проверяя свои ментальные модели. Они могут быть устаревшими или неверными.
Часть третья. Написание лучшего кода
Придумываем имена
Это важная глава, потому что именование – самое сложное. Совет заключается в том, чтобы называть вещи в том контексте и отношении, в которых они пребывают. Хорошее имя иногда решает всю проблему само по себе.
Был один раз, когда мне необходимо было реализовать функцию. Я потратил целый день на то, чтобы придумать хорошее решение. Я отступил назад и подумал о проблеме, не глядя на код, выстроил ментальную модель, думая о том, что мне нужно. Мне пришло в голову крутое название, основанное на необходимости, обстоятельствах, поведении и реализация открылась передо мной, потому что я знал, что мне нужно.
Точно так же плохое имя лишит вас понимания и значительно затруднит реализацию чего-либо еще в этом контексте.
В книге предлагается трехступенчатая модель процесса выбора имени разработчиком.
Избегайте плохого кода и когнитивной нагрузки
Что за когнитивная нагрузка? Это означает, что вам придется потратить много мозговых сил/энергии на понимание кода по любой из причин: код слишком сложный для того, что он делает, плохо написан, вы не понимаете смысла происходящего, не понимаете синтаксиса и т. д. Но можно облегчить боль следующими способами.
Убедитесь, что вы полностью понимаете смысл
Вам должно быть абсолютно ясно, что вы понимаете происходящее. В противном случае код либо не будет иметь смысла, либо его будет трудно интерпретировать. Понимая суть, вы сможете разобраться в коде, рассуждать о нем, быстрее находить баги и прочее.
Упростите код
Иногда код написан безумно сложно без видимой причины или причина есть, но вы ее еще не видите. Это нормально! Начните с рефакторинга, чтобы понимание пришло. У меня есть история об этом.
В eksctl был тикет. Реорганизовать логирование, чтобы расширить журнал вложенных задач:
превратить в такое:
Оказывается, то, что анализировало сообщения журнала, было настолько запутанным и рекурсивным, что его было трудно разгадать. В конечном счете, я начал переписывать его фрагменты и упрощать все это, снова и снова, чтобы увидеть, как оно работает. Это была свободная, полурекурсивная структура, в которой было неизвестно, насколько глубоко вы находитесь в данный момент. Таким образом, вы не могли просто делать отступы на основе счетчика или трекера. Она всегда была глубиной 1 или 0.
Урок здесь заключается в том, что упрощение и переписывание кода помогли лучше понять, что там происходит, и я, наконец, смог переписать его.
Далее в книге рассказывается о том, как запахи кода многократно увеличивают когнитивную нагрузку, а их устранение повысит понятность. Запахи кода были введены Кентом Беком и стали более известными, когда Мартин Фаулер написал о них. Книга по рефакторингу идентифицирует такие запахи кода:
- длинные методы;
- длинный список параметров;
- операторы switch;
- альтернативные классы с различными интерфейсами;
- чрезмерное использования примитивных типов в классе;
- неполный библиотечный класс;
- большой класс;
- ленивый класс – делает слишком мало;
- класс данных – просто работа с данными;
- временные поля;
- дивергентное изменение – приводящее к нежелательным переменам в разных частях кода;
- классы не должны быть напрямую связаны с другими классами;
- дублированный код;
- излишние комментарии;
- посредник – делегирование методов другим вызовам;
- наследование неиспользуемого поведения;
- добавление кода «на всякий случай».
Некоторые из них не часто используются, особенно пункты о классах и наследовании, но на некоторые следует обратить внимание. Дальнейшие анти-паттерны являются структурными и лингвистическими.
Структурные: код в порядке, но структурирован таким образом, что его трудно понять и обработать, что увеличивает когнитивную нагрузку. Лингвистические: плохие имена приводят к путанице и ошибкам.
Решение сложных задач
Как и ранее – определите, в чем заключается проблема. Перепишите/переформулируйте ее своими словами. Это позволит убедиться, что вы правильно понимаете рассматриваемую проблему. Затем как можно подробнее обрисуйте проблему, определите существующие индивидуальные ограничения. Перечислите их и изучите. Если уперлись, начните удалять или добавлять ограничения.
Не существует универсального базового метода для решения проблем, следом за которым будут решаться все возможные проблемы. Вы должны решать конкретные задачи, «набивая руку». Обучение игре в шахматы не сделает вас умнее, но поможет хорошо в них играть.
Что вам определенно поможет, так это автоматизирование обычных алгоритмов: обход дерева, построение графиков, операции на стеке, поиск в глубину и т.д. Практикуйте их до тех пор, пока не запомните и не сможете применить.
Постоянное гугление и просмотр StackOverflow не помогут вам лучше решать проблемы. Это не значит, что вы не должны этого делать. Вы должны извлекать из этого урок. Это нормально – смотреть на решения других людей. Вы пытаетесь понять, как они это сделали и повторяете пока не зазубрите. С этого момента вы растете и находите свой собственный стиль.
Изучайте. Понимайте. Создавайте свое – так вы научитесь.
В книге подробно рассказывается о том, какая память участвует в этих проблемах. По сути, автоматизация процессов в вашем мозге освободит когнитивную нагрузку при обдумывании кода и решении проблем.
Часть четвертая. Совместная работа над кодом
Написание кода
Далее перечисляются различные действия при написании кода и объединяются в следующих подразделах.
Поиск
Чтение и изучение кода. Участвует кратковременная память. Помогает запомнить, где вы находитесь, что вы ищете и что вы уже нашли, чтобы снять когнитивную нагрузку.
Понимание
58 % нашего времени уходит на это занятие. Речь идет о понимании кода и попытке выяснить, что он делает и как. Изменение/упрощение кода помогает. Рисуйте модели и оставляйте заметки, которые помогут потом все вспомнить.
Транскрипция
«Just coding», тут вы знаете, что собираетесь писать, где и почему.
Рост
Добавление новой функции. Это всегда тяжело, но необходимо.
Исследование
Наброски кода. Смутная идея, но, написав код, ваши идеи укрепляются. Написание структуры поможет упорядочить мысли и освободить умственное пространство для другого.
Совершенствование проектирования больших систем
Эта глава заставляет задуматься о дизайне вашей системы с точки зрения когнитивной нагрузки и о том, как трудно было бы другим найти в ней свой путь. Разрабатывайте свою систему для людей. Легко ли ее поддерживать? Имеют ли смысл названия пакетов? Должен ли именно этот код тут быть? Ваша архитектура может быть крутой, но если другие не могут ее прочитать, они не будут с ней работать. Это особенно важно, если работаете в команде. В книге это называется CDCB (когнитивное измерение кодовых баз).
CDCB определяет следующие измерения:
- Подверженность ошибкам. В основном касается безопасности типов и того, насколько легко в вашем коде допускать ошибки.
- Согласованность. Насколько согласован ваш код. Названия, структура, где и почему логика находится там, где она есть.
- Диффузность. Сколько места занимает программная конструкция. Как долго существуют циклы и языковые структуры. Насколько компактен код.
- Скрытые зависимости. Насколько много зависимостей. Есть ли скрытые фичи, которые нужны пользователю, но не очевидны и не задокументированы?
- Вязкость. Насколько код устойчив к изменениям.
- Прогрессивная оценка. Определяет, насколько сложно выполнить кусок кода.
- Выразительность. Насколько просто понять, что делает конкретный код. Например, в Ruby трудно понять, является ли что-то вызовом функции или переменной: thing.other – other может быть чем угодно. В других языках легко понять, что thing() – это функция.
- Сложные мыслительные операции. Код требует сложных мыслительных операций, таких как расшифровка неясного синтаксиса или понимание сложных идиом, таких как монады и неочевидные системы типов. Если ваш проект требует сложных умственных операций, контрибьюторы не захотят присоединятся к нему.
- Вторичная нотация. Комментарии и именованные параметры.
- Абстракция. Позволяет пользователям вашей системы создавать свои собственные абстракции, которые столь же мощны, как и встроенные.
Как привлечь новых разработчиков
Эта глава полностью посвящена различиям между старшими и новоприбывшими и отсылает нас к когнитивной нагрузке, кратковременной и долговременной памяти, сенсорной и информационной перегрузке. Это интересное чтиво, если вы проводите много интервью, я определенно рекомендую прочитать все. Подведем итог тому, что я почерпнул.
Не перегружайте новичков. Им нужно многое узнать о вашей среде, динамике группы, командных процедурах, решении проблем и т. д. и это мы еще не говорили о коде…
Как только вы овладеваете чем-то, вы забываете, как это было трудно. Это важный момент, о котором мы склонны забывать. У вас есть лучшее представление об общей картине, вы лучше знаете отдельные части кода. Новички, как правило, больше сосредотачиваются на деталях и пока не видят общей картины.
Замечать закономерности. Даже если у вас не сразу найдется ответ на проблему, вы быстро его найдете. Вы можете лучше разбивать код на части, можете быстрее читать его и более эффективно выявлять определенные шаблоны, поскольку уже сталкивались с ними сто раз.
Заключение
На этом все. Спасибо за внимание. Мы надеемся, что прочтение книги принесет больше понимания, как все устроено в этом мире и какая сложная штука этот наш мозг. Как обычно, ждем ваших комментариев о материале и о книге после прочтения. Удачи!
Дополнительные материалы:
- 3 лучших книги по объектно-ориентированному программированию
- Настольные книги по Linux на русском языке
- Книги по программированию: как читать и что именно
- Настольные книги по фреймворкам JavaScript на русском языке
- Бесплатные книги по управлению проектами для новичков и профи