Программирование и кратковременная память

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

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

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

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

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

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

Теперь посмотрим как работает наша кратковременная память во время написания кода.

Выдвинем гипотезу:

Чем умнее программист (чем более объёмной рабочей памятью он располагает), тем более длинные методы и функции он пишет.

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

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

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

Но давайте попробуем подсчитать какой объем рабочей памяти задействуется при написании кода объемом примерно в 150 строк.

Для этого я проанализировал целый ряд функций размещенных в Gist на Github и подсчитал количество объектов фигурирующих в коде с помощью грубого подсчета. Получились такие средние значения:

  • 4 аргумента функции, которые используются не менее 10 раз;
  • около 30 внутренних переменных, используемых около 100 раз;
  • около 10 обращений к 10 различным внешним сущностям.

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

Я дополнительно просмотрел методы, которые работают с обращением к различным элементам хэшей, которые передаются в качестве аргументов функции и обнаружил что в таких методах присутствует около 50 обращений 20 различным элементам хэшей. Что увеличивает количество объектов в памяти до 64.

Но важно другое, мы получили 44 и 64 объекта против “магических” максимальных 7.

Можно долго спорить на тему того, что раз код работает, то значит и 44, и 64 объекта не проблема. К тому же рассматривались не самые длинные методы.

Значит ли это что можно удерживать в памяти больше объектов? К тому же никто не говорит что все объекты удерживаются в памяти единовременно.

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

Кратковременная память и метрики качества кода

Метрик оценивающих качество кода много. Исследования в этом направлении идут с 70-х годов (Морис Холстед).

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

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

“Будет” – так как код является результатом работы мозга-инструмента, а “должен” поскольку код является еще и исходным материалом для создания. Из этого следует следующая гипотеза:

Код должен отвечать определённым критериям, чтобы мозг-инструмент не сломался во время его обработки.

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

Теперь мы можем ответить на вопрос о метриках кода так:

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

Итог

Решения описываемые “шаг за шагом” нужны не только тем, кто не может в уме удерживать большой объем данных. Это необходимо для того, чтобы при чтении и проверке решения тратилось сравнительно небольшое умственное усилие. Профессионал разберется и без промежуточных шагов, а вот новичок застрянет. Ведь сложных фрагментов кода в которых нужно разобраться в течении дня бывает несколько десятков.

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