Pull to refresh

Когда гаснет звезда: интервью с Джимом Вейрихом

Reading time10 min
Views13K
Original author: Pat Shaughnessy
От переводчика: Джим Вейрих — легендарная личность в Ruby-сообществе. К сожалению, он, как и все мы, смертен. Не так давно он покинул нас. Этот перевод — дань уважения к этому человеку, который немного изменил мир.

Я наслышан о Джиме достаточно давно: ведь он — автор утилиты rake, ставшей фактически стандартом де-факто среди рубистов. К моей большой удаче, я был в числе слушателей его выступления на GoRuCo 2012, на котором было рассказано о продвинутых возможностях rake. Помню, как меня поразила та ловкость и легкость, с которой Джим говорил на сложные темы. Позже, в том же году на конференции RubyConf я наблюдал еще одно его замечательное выступление, в котором объяснялись некоторые базовые принципы Лямбда-исчисления. Джим не только доступно объяснил эту не самую простую тему, но также не потерял своих слушателей по дороге.

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




Краткое резюме программиста


Как ты стал разработчиком? По каким причинам ты выбрал эту профессию?

Я столкнулся с программированием еще в школе, в старых-добрых семидесятых. Я тогда взял в библиотеке книгу, посвященной разработке под BCD системы. В качестве языка программирования использовался ассемблер-подобный язык. Вообще — это несколько безумно, конечно — писать под BCD на ассемблере, но я разобрался.

А что означает аббревиатура BCD?

BCD — это «Binary Coded Decimal», система, в которой все числа хранятся в десятичной системе счисления (в отличие от традиционной двоичной).

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

Не томи, что там была написано?

Ну, что-то вроде:

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

После этого я и подумал, что программирование — это здорово, но такая работа… Нет уж, увольте!

Во время моей учебы в колледже наш консультант посоветовал мне: «Почему бы тебе не записаться на курс „Фортран для начинающих“? Тебе может понравиться». Когда я пришел на первое занятие, лектор подошел к доске и принялся писать код, по ходу его объясняя. До сих пор помню название первой функции, которую он написал — member. Я слушал лекцию и вдруг меня осенило: «Это какой-то слишком странный диалект Фортрана. Слишком много скобочек!». О да, это был Лисп! Как оказалось, я попал на первый и единственный курс Дэна Фридмена, автора книги Little Lisper.

Ну, а как же зловещее описание программиста из брошюрки?

Ха, программирование оказалось весьма социальной деятельностью. На сегодняшний день, даже если работаешь в одиночку, то всегда можно пообщаться с другими людьми посредством Твиттера, IRC, issues на гитхабе, или почтовых рассылок… Мы больше не одинокие волки, какими нас описывали в 1970х.

Счастливое открытие


Как ты пришел к Руби?

Это было в 2000 году, если мне не изменяет память. Я тогда писал на C++ и Java, а также весьма прилично на Perl (ну, ты знаешь, мелкие скрипты для уменьшения каждодневной рутины). И Перл, к сожалению, через некоторое время начал меня расстраивать: он отлично подходил для быстрых хаков, но и только, поскольку на нем сложно писать красивые абстракции. Вот, к примеру, мне нужен список — пожалуйста, в Перле это раз плюнуть, а вот когда уже необходим список списков — то все, язык начинает вести себя неуклюже.

И вот я принялся искать новый, подходящий лично мне язык. Хотелось чего-то более выразительного, позволявшего бы активнее использовать абстракции. А поскольку я любил объектно-ориентированное программирование, то и язык хотелось соответствующий. Я очень, очень внимательно изучал Python и сделал как минимум 3 подхода к нему. Но, ты знаешь, не было в голове эдакого «Бам!». Поэтому через некоторое время я остановил свои подвижки в Питоне, поскольку он так и не стал мне близок.



Где-то во время моей 3 попытки изучить Питон мне пришло письмо от Дейва Томаса, в котором он написал: «Я тут нашел небольшой язык под названием Руби и мне он очень понравился, также он может прийтись по душе и тебе.» Я тогда закончил читать книжку The Pragmatic Programmer и решил, что если уж сам Дейв что-то рекомендует, то на это определенно стоит как минимум взглянуть. Я скачал Руби, поигрался с ним буквально несколько минут и вдруг осознал: «Ну вот же оно! Это именно тот язык, что я искал!». Через 3 дня я перестал писать на Perl и полностью перешел на Руби.

Что за версия Ruby это была?

Это был Руби 1.6 (поскольку на дворе тогда было лето 2000).

Чем именно тебя так зацепил Руби?

Он делал все таким же образом как и Перл, но только в объектно-ориентированной манере. Помню, я тогда размышлял: «Ну ладно, эту задачку я бы написал на Perl, но если бы у меня были объекты, то я бы решил задачу уже вот таким способом». После этого я садился за Руби, и мое решение, построенное на объектах просто работало! Конечно, при этом я мог использовать быстрые (и грязные) трюки, подобно тем, что позволял делать Перл, но через некоторое время я обнаружил, что у Руби есть просто превосходные абстракции и сам язык развивался очень правильно. Я был просто счастлив, что встретил его.

Функционален ли Руби?


Ну что ж, Руби — объектно-ориентированный язык. Но является ли он при этом функциональным? И что вообще слово «функциональный» значит?

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

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

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

Функциональное программирование интересно своей реализацией многопоточности. Одна из важных проблем в многопоточном программировании это состояние гонки, когда у вас есть, к примеру, 2 потока работающих с одними и теми же данными. При этой гонке неизвестно, кто победит. К примеру, увеличение счетчика. Есть 2 потока, первый из которых считывает текущее значение, увеличивает его в регистре памяти и затем кладет обратно. В это время второй поток считывает, увеличивает значение и записывает его. Если (и только если), они будут чередоваться в строгом порядке друг за другом и мы начнем с числа 10, то дальше будут 11, 12 и так далее. Нужно быть очень, очень осторожным, когда у потоков разделяемый ресурс может быть изменен.

Для решения этой проблемы есть 2 способа: не использовать разделяемый ресурс, либо не изменять этот самый ресурс. Функциональное программирование использует второй подход: данные не изменяются, а только создаются. При таком подходе многопоточное программирование становится заметно проще. Я думаю, что в нашем технологичном обществе с каждой новой железякой/процессором нужда в многопоточности будет только расти. А в такие языки как Clojure уже встроены очень хорошие конструкции для легкой манипуляции потоками. В Clojure, если вы даже изменяете данные, то делаете это в очень определенных условиях, когда это безопасно.

Боюсь, что Руби страдает от этого, поскольку его модель для потоков исходит из 1960-1970 годов.

Модель потоков в Руби


Да, особенно это коснулось MRI Руби. Я лично считаю, что сам интерпретатор не является потокобезопасным. Действительно ли это так?

Интерпретатор потокобезопасен, но достигнуто это было с помощью GIL (Global Interpreter Lock), разработчики о нем много говорили на RubyConf. Суть этого подхода заключается в том, что при входе в интерпретатор устанавливается блокировка, чтобы другие потоки не смогли войти в него в одно и тоже время. Все это приводит к потокобезопасности, конечно, но несколько, скажем так, усложняет работу с самими потоками.



Однако JRuby и Rubinius потокобезопасны?

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

Матц упоминал, что они тестировали другой подход, с микро блокировками (microlocking), другими словами, накладывание блокировки на разделяемые данные. Он также сказал, что в этом случае код начинал работать гораздо медленнее, чем версия с GIL. Вот такая вот цена решения. Так что если нужно работать с потоками, то вам стоит присмотреться к JRuby или Rubinius. Но даже при их использовании нужно помнить, что разделяемые ресурсы могут изменяться, поскольку Руби пока что не предлагает хороших решений этой проблемы.

10 публикаций, которые должен прочесть каждый разработчик


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

Это вещи восьмидесятилетней выдержки!

Есть ли у тебя в рукаве еще такие штуки?

В 2009 году Michael Feathers написал статью «10 Papers Every Programmer Should Read at Least Twice» (к сожалению, сам оригинал статьи более недоступен).

Первая книга написана David Parnan и называется «On the criteria to be used in decomposing systems into modules». Он написал простую программу «Keyword in context».



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

Не одна ли это из идей объектно-ориентированного программирования (ООП)?

Да, одна из них, в ООП каждый объект хранит порцию информации, а что происходит внутри окружающий мир не волнует. Поэтому, изменение способа хранения и взаимодействия с внутренними деталями не повлияет на окружающих. И этот очень простой эксперимент показал, что нужно делать. Я очень рекомендую прочитать эту статью целиком. Мне нравится, что Дэвид действительно провел эксперимент: он написал код и проверил как тот себя ведет под новыми условиями.

Еще одна классная статья это «Can Programming Be Liberated from the von Neumann Style?», которую написал John Backus. Это одна из первых публикаций, которую он назвал «ML», то есть функциональный язык программирования. ML стал основанием для таких языков как Haskell и OCalm.

Еще одно восхитительное исследование, которым я бы хотел поделиться, это «Reflections on Trusting Trust» от Ken Thompson. Он описал хак для компилятора, с помощью которого можно добавить баг в Unix, которого нету в исходном коде.

Выступления


У тебя природный талант: ты умеешь объяснить очень сложные темы. Как у тебя это получается?

Знаешь, я прочел кучу книг о выступлениях: как правильно готовиться, как проводить, собственно, выступление и прочее. Во всех книгах рекомендуется делать заметки на полях и прочие подобные штуки — но этот подход не работает со мной!

При подготовке к выступлению я люблю пользоваться маркерной доской или утилитой, наподобие Omnigraffle для Mac OS. Я начинаю с маленьких прямоугольников, внутри которых пишется идея. После этого я соединяю соответствующие идеи линиями. К примеру, если выступление связано с Руби, то я выписываю все те вещи, о которых мне бы хотелось поговорить. После этого, я соединяю их связями, ну ты знаешь, наподобие «mind mapping». У меня, правда, получается направленный граф.

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

То есть, это что-то вроде технического писателя?

Да, мне нравится такое описание!

Преобразить такие трудные темы как Лямбда-исчисление в интересную историю — это искусство. Думаю, у многих бы выпали глаза при попытке почитать оригинальные научные работы на эту тему, написанные 80 лет назад.

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

Rspec-given


Планируешь ли ты еще выступать?

В Январе я собираюсь рассказать о своем детище: фреймворке Given/When/Then. Это мое любимое дитя: каждый раз, когда я пишу тесты, то использую именно мой фреймворк, поскольку он очень элегантно выражает мои мысли. Я расскажу о нем на CodeMash.

Имеет ли этот фреймворк что-то общее с философией BDD? А с Cucumber? Или тот факт, что ты используешь те самые 3 ключевых слова — просто совпадение?

Это просто совпадение, мой фреймворк не связан с Cucumber, хотя мне он очень нравится своим подходом с использованием Given/When/Then.

Используя Rspec-Given вы просто указываете: вот это дано, вот код, который мы тестируем и вот это должно быть истинной, чтобы тесты прошли. По моему, это отличный способ для написания тестов. Я использовал похожий подход, даже когда писал на Test::Unit: даны данные, вот код тестов, а вот и сами тесты. Но я пытался найти более изящное решение, поскольку ни Test::Unit, ни Rspec не дают нужных методов.

Около 2-3 лет назад я размышлял над этой проблемой, набросав свои идеи на бумагу. В то время я был на конференции Ruby Hoedown в городе Nashville. Я передал этот клочок бумаги разработчиками по соседству, чтобы собрать отзывы и мнения. И тут Joe O'Brien повернулся ко мне и сказал: «Ты же не собираешься писать очередной фреймворк для тестов?».

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

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

Ссылки:

Tags:
Hubs:
+58
Comments6

Articles