Статьи

Что делает код читаемым: не то, что вы думаете

Вы часто слышите о том, как важно написать «читаемый код».

У разработчиков довольно сильные мнения о том, что делает код более читабельным. Чем старше разработчик, тем сильнее мнение.

Но вы когда-нибудь задумывались о том, что действительно делает код читабельным?

Стандартный ответ

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

  • Хорошие имена переменных, методов и классов
  • Переменные, классы и методы, имеющие единственное назначение
  • Согласованный отступ и стиль форматирования
  • Снижение уровня вложенности в коде

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

(Кстати, отличным ресурсом для такого рода информации о «хорошем коде» является отличная книга Роберта Мартина «Чистый код» или книга Стива Макконнелла, которую должны прочитать все разработчики, Code Complete . * Обе эти ссылки являются партнерскими, спасибо за твоя поддержка.)

Вместо этого я хочу показать вам более глубокое понимание читабельности …

Словарный запас и опыт читателя

Я могу посмотреть на код и через 2 секунды сказать, хорошо ли он написан и хорошо читается или нет. (По крайней мере, мое мнение об этом.)

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

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

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

Существует фундаментальное различие в том, как опытный кодер читает код, а не как новичок

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

Начинающий или менее опытный разработчик читает код по-разному.

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

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

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

Пример: учимся читать

Подумайте, каково это научиться читать.

Когда дети учатся читать, они начинают с изучения фонетических звуков букв.

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

Представьте, что этот пост был написан в форме раннего читателя.

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

Считаете ли вы мой блог очень читабельным? Вероятно, нет, но детские сады, вероятно, найдут его гораздо более усваиваемым. (Хотя они, скорее всего, все равно будут игнорировать контент.)

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

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

Ограничения читабельности

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

Это лучше видно на примере. Давайте посмотрим на некоторый язык ассемблера.

.model small
.stack 100h
 
.data
msg     db      'Hello world!$'
 
.code
start:
        mov     ah, 09h   ; Display the message
        lea     dx, msg
        int     21h
        mov     ax, 4C00h  ; Terminate the executable
        int     21h
 
end start

Этот ассемблерный код напечатает «Hello World!» на экран в DOS.

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

Существует верхний предел читаемости языка ассемблера x86, независимо от того, насколько вы хороши программистом.

Теперь давайте посмотрим на Hello World в C #.

public class Hello1
{
   public static void Main()
   {
      System.Console.WriteLine("Hello, World!");
   }
}

Это не прямое сравнение, потому что эта версия использует .NET Framework в дополнение к языку C #, но для целей этого поста мы рассмотрим C # для включения библиотек базовых классов.

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

Хотите знать, почему Ruby так популярен? Вот Hello World в Ruby.

puts "Hello, world"

Вот и все, довольно маленький.

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

Теперь я понимаю, что я не сравниваю яблоки с яблоками здесь и что Hello World вряд ли является хорошим представлением словаря или грамматики языка программирования.

Я хочу сказать , что чем больше у вас словарный запас, тем более краткими могут быть высказаны идеи, что делает их более читабельными, НО только тем, кто владеет этим словарем и грамматикой.

Что мы можем извлечь из всего этого?

Итак, вы можете подумать: «О, хорошо, это интересно… Я не уверен, полностью ли с вами согласен, но я понимаю, что вы говорите, так какой в ​​этом смысл?»

Честный вопрос

Из понимания того, как словарный запас и опыт влияют на читабельность, можно извлечь немало.

Прежде всего, мы можем ориентировать наш код на нашу аудиторию.

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

В C # обычно утверждается, следует ли использовать условный оператор.

Должны ли мы написать код так:

var nextAction = dogIsHungry ? Actions.Feed : Actions.Walk;

Или мы должны написать код так:

var nextAction = Actions.None
if(dogIsHungry)
{
   nextAction = Actions.Feed
}
else
{
   nextAction = Actions.Walk;
}

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

Причина, по которой это зависит, заключается в том, что если ваша аудитория не привыкла к условному оператору, она, вероятно, посчитает, что код, использующий его, сбивает с толку. (Им придется разбирать словарь, а не фокусироваться на истории.) Но, если ваша аудитория знакома с условным оператором, длинная версия с оператором if будет казаться затянутой и пустой тратой пространства.

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

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

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

То, что мы выиграем в сокращении времени до мастерства, мы потеряем в его силе выразительности.

Один язык, чтобы управлять ими всеми?

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

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

Этот тип вещей должен развиваться с общими знаниями населения.

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

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

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