Pull to refresh

Интервью: Брайан Керниган и Алан Донован

Reading time12 min
Views21K
Original author: Brian Kernighan, Alan Donovan
image


В этом году Брайаном Керниганом, автором классического труда «C Programming Language», в соавторстве с Аланом Донованом была написана книга «The Go Programming Language», которой, судя по всему, де-факто суждено стать одним из официальных источников первоначальных знаний по языку — не в последнюю очередь благодаря тому, что книга создавалась под пристальным контролем со стороны создателей самого языка. Электронная версия книги на английском языке выходит только сегодня — причиной нескольких переносов было исправление неточностей, допущенных в первом тираже книги; качественный перевод на русский язык ожидается не раньше марта 2016 года.

Вниманию всех интересующихся читателей предлагается перевод недавней сессии вопросов и ответов с авторами книги, проведенной ресурсом Slashdot.


Несколько недель назад все желающие имели возможность задать вопросы Алану Доновану и Брайану Кернигану на тему их совместного труда, книги «The Go Programming Language». Slashdot отобрал самые популярные вопросы читателей и получил на них ответы.

Донован/Керниган: Спасибо всем, кто не пожалел своего времени на то, чтобы задать нам интересные и провокационные вопросы; увы, на все ответить не получилось. Кроме того, ни один из нас не является членом команды разработчиков языка Go, поэтому мы изначально не могли дать более авторитетные ответы на вопросы о планах на будущее или подробно рассказать об утилитах.

OpenGL и LockOSThread


Я перестал использовать Go, когда увидел, к насколько «суровым» хакам мне придется прибегнуть, чтобы заставить библиотеки вроде OpenGL работать нормально. Есть ли в планах пофиксить это?

Донован: Суть проблемы в том, что многие библиотеки на C вроде OpenGL неявно используют идентификатор вызывающего потока для хранения информации о контексте. В некоторых случаях, это происходит по причине того, что дизайн API создавался до того, как многопоточность стала нормой, когда глобальные переменные могли быть безопасно использованы для хранения информации о контексте. В остальных случаях, использование этого дизайна — лишь вопрос удобства, поскольку он позволяет сэкономить на передаче дополнительного параметра в каждый вызов.

При проектировании Go идея локального хранилища потока (thread-local storage, TLS) была отклонена из-за своей склонности устраивать так называемое "действие на удалении" (action at a distance): позволив сделать программы лишь ненамного короче, TLS делает их гораздо менее читабельными (об этом, кстати, мы написали в книге). Поскольку отсутствие TLS в Go считается «фичей», планов «пофиксить» ее нет. Зато есть возможность заставить лучше работать с Go сильно зависящие от TLS библиотеки на C. Мой коллега David Crawshaw совсем недавно рассказывал об этом на DotGo 2015 в Париже.

Почему версионирование пакетов остается без внимания?


Почему версионирование пакетов продолжает оставаться без внимания? Вам самим ваше решение все еще нравится? Чем больше я использую Go, тем больше этот момент напоминает мне «ахиллесову пяту» языка; ПО существует уже десятки лет, и его развитие представляет собой непрерывную эволюцию. Система импортов в Go не позволяет указывать версию или «хинтить» на нее, не позволяет этого и команда 'go get' (хотя она и поддерживает все популярные системы контроля версий), поэтому изобретаются различные хаки вроде gopkg.in. Да и неясно в чем проблема, ведь пакетные менеджеры для других языков уже решили этот вопрос более или менее элегантным способом...

Донован: Go проектировался для написания больших программ, и общеизвестно, что в подобном контексте версионирование делать трудно.

Лет десять назад, в Google проводился эксперимент по внедрению версионирования в систему сборки (ее проектировал Роб Пайк и другие). Он провалился по причине проблемы diamond dependency, о которой, я думаю, многие из вас слышали — это классическая проблема нумерации версий. Допустим, имеется четыре пакета A, B, C, D, где A зависит от B и C, а B и C оба зависят от D. Вот это и есть diamond dependency. Если автор B решит, что подходит только версия 1 пакета D, а автор C потребует как минимум версию 2 того же пакета D, вы получите невозможный набор ограничений. Если вам повезет, то вы сможете «сбилдить» A с обеими версиями D, «старой» и «новой», но чаще всего это не сработает. После этого эксперимента, Google больше никогда не трогала автоматическое версионирование.

Способ, которым мы теперь делаем версионирование, простой, но «ручной»: мы принимаем каждую версию пакета за независимую сущность со своим отдельным именем (например, «D1», «D2»), и стараемся ограничивать количество версий каждого пакета, в идеале — до одного. Вот почему версионирование не является для нас в Google приоритетом.

Впрочем, в этом августе плодовитый Дейв Чейни предложил схему нумерации версий пакетов в Go, так что возможно мы увидим развитие этой идеи в будущем.

Обработка ошибок в Go


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

Керниган: В целом, Go настоятельно поощряет явно обрабатывать ошибки. Функции из стандартной библиотеки почти все возвращают статус ошибки вместе со значением функции, и ваш код должен что-то сделать с этим статусом; вы не можете просто проигнорировать ошибки. В этом плане, Go похож на Java, где вы должны ловить или выбрасывать ошибки; вы не можете просто ничего не делать. Да, это досадное неудобство в случае небольших одноразовых программ, но в случае с большими — настоящее спасения. И оба этих языка делают «правильную вещь», просто каждый по-своему.

В чем они различаются — так это в использовании исключений. В Go нет механизма исключений, поэтому здесь нет прямого пути для обработки всех ошибок в одном месте, что позволительно try/catch в Java, — хотя и оператор defer может помочь с «закреплением» места обработки ошибок. Всё это означает, что код на Java может быть чуть более компактным (только в этом плане!), но возможно ценой отсутствия возможность предоставления точных сведений о том, что же пошло не так.

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

Донован: Я написал немало кода на Java и, по моему опыту, «хорошая» обработка ошибок одинаково трудна в обоих языках. Однако, Go уменьшает синтаксическую цену дополнения сообщения ошибки при перебрасывании ее наверх, поскольку вы должны написать более-менее одинаковый код вне зависимости от того, собираетесь ли вы дополнять ошибку новой информацией или нет. Java, напротив, делает настолько заманчивым желание избежать написания блоков try/catch/throw, что программисты слишком часто бездумно перебрасывают ошибки наверх. Забавно, что подобные прагматичные знания о мелких различиях в использовании языков никогда не почерпнешь из чтения их спецификаций.

Применимость Go


Для каких сценариев и проектов вы рекомендуете (или не рекомендуете) использовать Go?

Керниган: Go — это очень хороший язык общего предназначения (general purpose language), и у нас не возникает препятствий для использования Go при решении любой новой задачи. Похоже, лучше всего он показывает себя на программах, которые вовлекают нетворкинг или другие конкурентные задачи; горутины — очень удобная и эффективная вещь, но в языке есть еще и хорошая поддержка более традиционных подходов по разделению памяти. Практика показывает, что людям, которые пишут новый код для работы с нетворкингом, нравится Go. Лично я бы использовал его для любой из своих задач, для которых раньше бы пришлось прибегнуть к C, Java или C++.

Go также получил некоторое признание как язык для написания скриптов, став потенциальной заменой большим скриптам на Python. Это может показаться немного удивительным, поскольку скриптовые языки очень удобны для быстрого «набрасывания» чего-нибудь в спешке, когда нужно, чтобы это побыстрее заработало. Проблемы приходят потом, когда «наброшенный» код начинает падать с ошибками типов или другими ошибками, которые можно было бы обнаружить гораздо раньше в любом статически типизированном языке. Go не заменит однострочники на Awk, не заменит Python, Perl или Ruby для 10- или 100- строковых программ, но когда задача становится чуть крупнее и серьезнее, комбинация безопасности типов и эффективности определенно стоит немного больших трудозатрат.

Почему я должен использовать Go?


Для человека вроде меня, любящего сборщик мусора, множественную диспетчеризацию (multiple dispatch), а также экстремальные возможности абстракции в высокоуровневых языках вроде Common Lisp, а также безопасность, обнаружение ошибок на стадии компиляции, читабельность и скорость в низкоуровневых языках вроде Ada и Haskell — в чем преимущества использования Go в сравнении с перечисленными двумя типами языков? Что действительно полезного привносит Go?

Керниган: Вообще-то, Ada и особенно Haskell не слишком-то похожи на низкоуровневые языки, к тому же Haskell обычно недосягаем для новичков; но ладно, это всё придирки. В Go есть всё, что вы упомянули в обоих ваших списках желаемых качеств (конечно, справедливость моего утверждения можно подвергнуть критике — это зависит от того, что вы подразумевали под "экстремальной абстракцией"), но также предоставляет конкуренцию (concurrency) в удобной и эффективной форме; для некоторых видов приложений это дает серьезный выигрыш.

Донован: Go выглядит очень простым в сравнении с языками вроде Common Lisp, C++, Java, или Python. В нем нет макросов, темплейтов, загрузчиков классов (ClassLoader), нет метаклассов. Перечисленные фичи — это первое с чем я, как PL гик, несусь поиграться, когда я пишу забавы ради первые программы на новом языке, вот только когда мы переходим на больший масштаб, они значат не так много. Я могу вспомнить немало неприятных дней, проведенных за отладкой перемудренного использования C++ STL, не-гигиеничных макросов на Lisp или метода __call__ в Python. Дизайн Go регламентирует, что простота, однородность и узнаваемость большой кодовой базы более ценны для команды в целом, чем преимущества от использования каждым внутри группы своих любимых «мутных» возможностей языка для решения каждой из задач.

Потенциал Go


Какой серьезный потенциал в реальном мире вы видите для Go? Каким вы видите потенциал Go в замене существующих open source веб-стэков вроде Apache и PHP, Python or Ruby?

Керниган: Причина, по которой Богу хватило всего шести дней на то, чтобы создать вселенную, в том, что ему не пришлось иметь дело с предыдущим наследием. Рассуждая реалистично, ни один из языков программирования не сможет сподвигнуть полностью заменить большие кодовые базы — это попросту слишком большая работа. Go часто является хорошим выбором для новых проектов или там, где планировалось переписать существующую систему в любом случае; вдобавок, он может предоставить удобный интерфейс для существующего кода через интерфейсы внешних функций — в частности, для библиотек на C. Но крупномасштабные замены чьей-либо кодовой базы в целом кажутся маловероятными.

Донован: Я соглашусь с Брайаном в том, что Go вряд ли поможет «избавится» от другого языка или библиотеки — но это никогда и не было его целью. Скорее, Go представляет собой привлекательную альтернативу. Значительная часть популярности Go происходит из того, насколько просто вы можете создавать полезные веб-серверы и другие распределенные системы, пользуясь лишь немногим большим набором средств, чем компоненты стандартной библиотеки. Стандартная библиотека была создана совсем недавно, причем ею занимались эксперты в создании различных систем, благодаря чему серверы третьих сторон вроде Apache или фреймворки вроде Rails не требуется для первых шагов при разработке своих приложений — хотя подобные фреймворки, конечно же, существуют и для Go.

Официальное IDE для Go?


Разрабатывается ли официальное кросс-платформенное IDE для Go? Опыт показывает, что адаптацию языка среди широких масс может существенно ускорить некий набор инструментов, которым можно легко и быстро начать пользоваться — например, IDE Android Studio, предлагаемая Google. Есть ли подобные планы в отношении Go?

Кстати, как насчет GUI — когда у меня наконец появится возможность «слезть» с С++ для разработки производительных декстопных приложений с интерфейсом?


Донован: Мы согласны с тем, что хорошая IDE сыграет в пользу привлечения новых желающих попробовать Go, в то время как мои коллеги и я постепенно пришли к осознанию того, что (и это неудивительно) большая часть нас использует очень традиционные редакторы вроде Vim, Emacs, Sublime Text и даже Acme, а это не то, о чем большая часть людей думает как об IDE. Заметная инициатива исходит от JetBrains, которая в этом году собрала команду для разработки плагина для Go в IntelliJ IDEA, что позволит всем желающим собирать, тестировать, производить отладку и рефакторинг программ, написанных на Go, так же легко, как и на любом другом языке.

Касаемо кросс-платформенных библиотек для GUI — канонического решения пока не существует, хотя уже были некоторые интересные эксперименты вроде GXUI и Shiny.

Должен ли Go заменить Java?


Должен ли Go прийти на смену Java в качестве платформы для разработки/языка для Android?

Донован: Разработчики языка Go в Google активно трудятся над тем, чтобы Go можно было использовать для написания приложений под Android и iOS; если вам стало интересно, посмотрите доклад Ханы Ким (Google) на GopherCon 2015. Но сейчас это всего лишь эксперимент, так что, как Брайн уже сказал раньше, целью Go не является замена существующих крупных кодовых баз.

Безопасная производительность


Переписывание тулчейна Gnu+Linux на Go может дать ту безопасность, которую не смог дать С за десятки лет (я имею в виду недавние баги в BASH и OpenSSL). Даже небольшая порция подобного труда добавила бы безопасности Android. Производительность в 1.5 и загрузка библиотек помогут сделать размер исполняемых файлов небольшим. Существует ли движение заинтересованных в перестройке базы Linux?

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

Я не в курсе подобных проектов.

tEoPS


Написано немало книг о том, как научиться программировать — но лишь немногие из них рассказывают о том, как программировать хорошо. Брайан, ваша книга «The Elements of Programming Style» — настоящая классика, но у моих студентов возникают проблемы с чтением примеров (они на Fortran 66 и PL/I). Есть ли надежда на их обновление, или же возможно существует какая-либо альтернативная книга?

Керниган: Языки, которые мы с Биллом Плагером использовали в «The Elements of Programming Style» либо давно мертвы (PL/1), либо сильно эволюционировали (Fortran), так что сегодня код в книге действительно читается с трудом, пусть большая часть правил хорошего стиля все еще в силе. Билл и я одно время писали версию книги для C, но далеко дело не продвинулось. Одна из проблем заключалась в том, что для нас представлял сложность поиск примеров для наших правил. Другая проблема в том, что реальные программы гораздо больше и сложнее, чем они были когда-то, так что найти и отобрать фрагменты кода, которые можно было бы использовать в подобной книге сейчас, достаточно тяжело. Таким образом, вряд ли данная книга когда-либо будет обновлена.

Касаемо же других книг, Джош Блох и Скотт Мейерс написали прекрасные книги соответственно про то, как писать хороший код на Java и С++. В более широком плане, мне всегда нравился «Совершенный код» Стива МакКоннелла, и я каждый год перечитываю «Мифический человеко-месяц» Фреда Брукса, чтобы взглянуть на него свежими глазами. Этим список заслуживающих прочтения книг не ограничивается; попробуйте почитать труды про конкретные окружения и языки программирования.

Место C в сегодняшнем мире


Как гласит легенда, язык C был создан для разработки операционных систем. Со временем, С++ заменил его как средство разработки ОС для «больших» платформ, оставив своему предшественнику только ниши встраиваемых систем (вплоть до тех, в которых используются 8-битные процессоры и стоит 256 байт памяти) и драйверов в «больших» системах. Какие решения относительно дизайна С вам кажутся сегодня разумными, и что бы вы изменили, чтобы приспособить его под текущие задачи?

Керниган: Учтите — язык C это плоды трудов Денниса Ричи; я утверждаю, что я всего лишь написал вместе с ним книгу. Деннис был отличным писателем — не хуже, чем программистом — так что книга создавалась нашими взаимными усилиями.

При всем этом, С действительно все еще очень популярен для программирования встраиваемых систем и драйверов, где важны эффективность и возможность спустится на уровень «железа». Я думаю, что попытка изменить C сегодня была бы контр-продуктивным решением, ведь одно из достоинств языка как раз в том, что он относительно стабилен. Серьезно, у меня есть подозрения (хотя мне и нечем их подтвердить), что за исключением мелких возможностей вроде комментариев при помощи //, большинство программистов используют C в том виде, в котором он был представлен в стандарте ISO 1988 года; стандарты С99 и С11 не слишком многое меняют в ежедневной работе программиста.

Мотивация для написании книги


Мне любопытно — зачем при существовании такого количества книг про Go требуется еще одна? Чем «The Go Programming Language» отличается от «Go Programming Blueprints» или «Go in Action», с которой у нее даже практически оглавление совпадает? В чем смысл еще одной книги — хотите заиметь еще одну «The C Programming Language», но про Golang?

Керниган: Как сказано в Экклезиасте, 12:12, «составлять много книг — конца не будет», чем я как бы вам намекаю, что ваш вопрос о необходимости еще одной книги — довольно-таки старая тема.

Когда кто-то пишет книгу, он всегда верит (или хотя бы искренне надеется), что у него это получится «лучше», чем у предшественников — я имею в виду не что-то негативистское, а надежду на то, что организация новой книги, ее примеры, объяснения и стиль письма сложатся таким образом, что читатели найдут эту книгу полезной. Это то, чего мы с Аланом старались достичь в случае «The Go Programming Language». Если она окажется настолько же полезной, как и моя книга по C — это замечательно, но замахиваться на подобный успех мы не будем.

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

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

Сравнение с K&R напрашивается само собой — мне неизвестна другая техническая книга, которая оказалась бы настолько же влиятельной. Это было не просто обучающее руководство для самого важного языка поколения «до Интернета», но также справочник по языку, и де-факто — его спецификация. Сегодня, конечно, к вашим услугам есть The Go Tour, Godoc, и спецификация The Go Language Specification — причем все они доступны прямо с вашего телефона. Библиотеки стали больше, утилиты — важнее. Получается, что современная книга о языке должна была фокусироваться на совсем ином — вот мы и попробовали, как же это все сочетается вместе.
Tags:
Hubs:
+34
Comments40

Articles

Change theme settings