Зед Шоу – еще один известный писатель, который в своих книгах рассказывает о самых трудных способах выучить Ruby, Python и C (и не только). А еще он – создатель уникальной методологии разработки ПО «Пиши код, ..!». Сегодня мы предлагаем вашему вниманию статью Зеда Шоу про идиомы в программировании. А точнее – про то, что их не существует...
В последнее время я занимаюсь редактированием моей книги Learn Ruby The Hard Way – вношу кое-какие последние штрихи. И в ходе работы я столкнулся с феноменом, который приверженцы Ruby называют «идиомой». Он заключается в использовании циклов .each to do вместо for-loop. Считается, что это один из важнейших признаков того, что вы – настоящий Ruby-программист. А отказ от одной циклической конструкции в пользу другой – признак того, что вы просто некомпетентны или недостаточно хорошо понимаете, как принято работать в сообществе программистов Ruby. И такая ситуация возникает не только с Ruby. Python, Java – во всех языках есть эти странные «идиомы», которые сводятся к необходимости принять стандарты определенного сообщества. Я использую .each в Ruby лишь постольку, поскольку мне это насаждают, несмотря на то, что сама конструкция довольно спорна.
Но такие вещи нельзя называть идиомами. Идиома – это выразительная фразочка, которая имеет значение только для тех, кто употреблял ее «с младых ногтей», а для всех остальных может звучать как полная ахинея. Кстати, «с младых ногтей» – это и есть идиома, и такие идиомы определяются не столько языком, сколько региональными и культурными факторами. Например, в Великобритании употребляется масса идиом, не принятых в США.
Но если вы отправитесь в Великобританию, то англичане, конечно же, не станут требовать от вас, чтобы вы обязательно употребляли выражения вроде «собачьи яйца» (dog’s bollocks) в значении «классно», «отпад» (как это принято у них). Если бы идиомы в программировании были эквивалентны языковым идиомам, то никого не волновало бы, используете вы их или нет. Напротив, вместо того чтобы смущать вас нелепыми кодовыми фразами, другие программисты сами старались бы адаптировать свой стиль написания кода так, чтобы вам было легко его читать. Так что это – не идиомы, и именно потому, что некоторые граждане просто срываются на всех, кто пишет неидиоматичный код, а потом непримиримо их исправляют.
Раз уж речь зашла о стиле, то есть и другие сложности с тем, чтобы считать .each «идиомой». На уроках по творческому письму порой советуют избегать идиом, за исключением тех случаев, когда они употребляются в прямой речи персонажа. И это правильно, поскольку лишние идиомы усложняют текст, и он становится трудным для восприятия даже для ваших земляков.
А вот ситуация с идиомами в программировании прямо противоположная. От вас настойчиво требуют, чтобы вы использовали в коде конкретные идиомы, более того – даже не рассказывают вам о том, какие здесь могут быть варианты.
Представьте себе, что я пишу техническую статью для студентов и начинаю ее так: «Сконфигурировать модуль проще пареной репы, мамой клянусь». Специалист по стилистике тут же скажет мне, что две идиомы в такой фразе, да еще в таком тексте – это слишком. Лучше написать: «Сконфигурировать модуль очень просто». Соответственно, если бы идиомы программирования действительно были бы идиомами, то опытные программисты советовали бы вам избавляться от них, чтобы код становился чище и качественнее.
Что же это тогда, если не идиомы?
Если эти штуки, именуемые идиомами, практически обязательны, и за отказ от них люди подвергаются осуждению – давайте будем честны и прекратим называть их «идиомами». Особенно если учесть, какой град упреков сыплется на меня со стороны разработчиков из сообщества Ruby за гораздо более мелкие «грешки», нежели предпочтение цикла for циклу .each. Эти вещи лучше назвать другими словами, например, «нравы». Нравы в обществе – это нечто настолько обязательное, что пренебрегать ими преступно и оскорбительно. Со временем нравы превращаются в законы или в табу. Они обусловлены культурой, но почти никак не связаны с языком. Конечно, это не всегда так – например, ругательства (и отношение к ним) являются яркими примерами проникновения нравов в язык. Нет никаких сомнений в том, что так называемые «идиомы программирования» – не что иное, как нравы сообщества программистов, пишущих на том или ином языке. Действительно, если определенные выражения в коде обязательны для употребления, а пренебрежение ими делает вас изгоем и вызывает возмущение и порицание со стороны сообщества – они являются не чем иным, как устоявшимися нравами. Более того, рискну утверждать, что в языках программирования вообще нет идиом. Ведь идиома – это как раз то, от чего вы по возможности избавляетесь, составляя хороший, ясный текст.Насаждение нравов – это идеологическая обработка
Когда в моих книгах я учу читателей писать код, я сознательно стараюсь защитить их от идеологической обработки. Я считаю, что идеология – враг образования, так как она отучает людей думать самостоятельно. Такие люди могут жить и работать только в той культуре, в которой их воспитали. Идеология ментально порабощает людей, они перестают интересоваться тем, что же на самом деле происходит, и критически воспринимать реальность. Я же стремлюсь воспитывать людей, которым интересна истинная природа вещей. Такие люди исследуют мир и создают что-то новое, не отвлекаясь понапрасну на мысли о том, не нарушают ли они устоев какого-то сообщества. Подобный образ мыслей невозможен, если человек ограничен, в сущности, беспочвенными нормами. Когда вы насаждаете свои нравы, выдавая их за абсолютные истины – вы занимаетесь внушением, а не обучением. Когда специалисты по Ruby учат вас, что цикл .each лучше цикла for, не сомневайтесь – это банальное внушение. Когда специалисты по Python требуют, чтобы вы писали код на этом языке без всяких «фокусов» – вас идеологически обрабатывают. Я мог бы без конца перечислять языки и закрепившиеся в них загадочные нравы, которые на поверку абсолютно бессмысленны. Такие вещи существуют в любом языке, и можно сказать, что они калечат программистов – многие после этого просто не усваивают других языков. Это случается сплошь и рядом: программист начинает работать с новым языком и переносит туда все привычные постулаты и приемы, которым его научили в другом языке. Кроме того, вы наверняка встречались со случаями, когда человеку противно даже пытаться освоить новый язык. Специалист по Java будет возмущаться тому, что в коде Python нет скобок. Python-разработчик злится, когда в коде Ruby начинается «магия». А программист на Ruby обязательно укажет, что в Python непоследовательно используются методы. С другой стороны, не исключено, что именно поэтому нравы программирования насаждаются и прививаются так активно. Если вы заставите человека работать с .each и ничем больше, то он окажется как без рук, столкнувшись с языком, где отсутствует концепция «blocks-to-functions». Если подавать эти привычки как абсолютные истины, то человек начинает зависеть от языка, в котором они используются. Учтите – я не утверждаю, что учиться общественным нравам программирования вредно и этого следует избегать. Я против того, чтобы они позиционировались как универсальные истины. Я тоже рассказываю о них, но именно как об обычных причудах, которые полезно знать – так вам будет проще работать с людьми, которым когда-то вдолбили такие привычки. Такой подход очень важен, поскольку какие-то языки отмирают, какие-то становятся менее популярными. Надеюсь, что мои ученики смогут адаптироваться к новым языкам и легко изучить их. Если же человек слишком увлекается этими программистскими догмами, то в будущем им, возможно, будет несладко. В худшем случае, при масштабном изменении языковых предпочтений кому-то вообще придется завязывать с программированием.Почему знакомство с циклами на примере .each – крайне неудачная идея
Наконец, я хотел бы объяснить, почему .each не устраивает меня в качестве первого примера для обучения работе с циклами. Рассмотрим пример кода из руководства по стилю программирования на Ruby: arr = [1, 2, 3]# плохо for elem in arr do puts elem end
# хорошо arr.each { |elem| puts elem }
А теперь перечислим концепции, с которыми нужно познакомить читателя, чтобы объяснить ему, как работают, соответственно, циклы .each и for. Начнем с .each:- Переменные
- Массивы
- Перечни (enumerables)
- Наследование
- Примеси и их связь с множественным наследованием
- Передача и диспетчеризация сообщений
- Вызовы функций
- Блоки, передаваемые вызовам функций
- Вставка переменных в блоки
- Область видимости – в частности, при работе с блоками
- Переменные
- Массивы
- Оператор if
- Команды перехода (goto или jump)
Релоцировались? Теперь вы можете комментировать без верификации аккаунта.