Есть гигантское множество книг о Java — а есть несколько «тех самых» книг о Java. В их число входит «Core Java» (в русском издании «Java. Библиотека профессионала») Кея Хорстманна и Гэри Корнелла. Она появилась лишь годом позже самого языка, сразу став одним из главных источников информации по теме. А за последовавшие двадцать лет выдержала целых десять изданий, скрупулёзно пополняясь информацией о новых версиях Java, так что на ней выросло уже не одно поколение Java-разработчиков.
Кей по-прежнему внимательно следит за нововведениями Java, и осенью на петербургской конференции Joker расскажет, что в Java 9 хорошего. А в ожидании его приезда мы расспросили его о многом: и о работе над книгами, и о том, могут ли их вытеснить онлайн-курсы, и об отличиях академического мира от индустрии, и о будущем Java.
— То, что «Core Java» стала очень известной и значимой, как-то влияет на работу над ней? Например, ощущаете ли вы, что фактчекинг вам требуется проводить тщательнее других авторов?
— Спасибо за тёплые слова о «Core Java». Я надеюсь, что каждый автор как следует занимается фактчекингом, и про многих точно знаю, что это так. Но когда «Core Java» вышла впервые, конкуренцию ей составляли несколько книг, попросту повторявших документацию API, а документация тогда не всегда была верна. Мы обнаружили это, когда написали маленькие, но реалистичные программы (а не просто «игрушечные» примеры), которые пускали API в дело. Сейчас сложно представить себе, насколько это всё усложняло: stackoverflow.com ещё не было, а доступ к исходному коду Java был ограниченным.
Некоторые книги, вроде «Java Concurrency in Practice», написаны такими выдающимися экспертами, что сказанное в них можно принимать на веру без примеров кода. Но давайте признаем, что многие книги приходится писать в спешке, когда новая технология развивается. И в этом случае очень важно, чтобы авторы предоставили хорошие примеры. Когда я вижу книгу, где у классов названия животных, а методы выводят «Гав» и «Мяу», мне это не нравится. Я хочу видеть код в реалистичном контексте. Для меня эталон — классическая книга Кернигана и Ритчи по С, в которой почти каждый сниппет мог бы быть из рабочей программы.
Когда «Core Java» впервые была опубликована, и там было сказано, что многие вещи в Java API не вполне корректно работают или неудобны для программиста, на моего редактора накричали в Sun Microsystems. Но я думаю, что это очень помогло репутации книги. Теперь, когда я работаю над изданием, приуроченным к Java SE 9, я по-прежнему пытаюсь объяснить, что работает хорошо, а что не очень. К счастью, на моего редактора больше никто не кричит.
— Работать над одной книгой десятилетиями — каково это? Возникает ли «легаси», когда какой-то фрагмент ощущается устаревшим, но просто «взять и выкинуть» невозможно? Похоже ли обновление книги на рефакторинг кода? И вызывало ли что-то, написанное годы назад, ощущение «какую глупость я написал»?
— Очень хороший вопрос. Когда я начал писать эту книгу, я был и автором учебников, и разработчиком, и для меня было естественным думать не просто об одной версии, а сразу и о последующих. Книга была рассчитана на то, чтобы расти вместе с языком и с API. Но мы сами были так же поражены, как и все, когда API разросся семимильными шагами, и «Core Java» превратилась в два толстых тома.
И да, работа над новым изданием ощущается как рефакторинг. Во многих случаях новый способ делать что-то делает другие подходы устаревшими, и мне надо разбираться с сотнями примеров кода. Я люблю использовать новые возможности во всех примерах, где они подходят, чтобы читатели не оказывались сбиты с толку смесью старого и нового. Простой случай — diamond operator, там требовалось просто найти выражения вида «new … <...>(...)». Но когда добавили лямбда-выражения, мне пришлось переписать больше половины программ-примеров, порой сильно их реорганизуя.
Мы не хотели, чтобы «Core Java» потолстела до трёх томов, так что в каждом издании какие-то вещи оказываются удалены. В числе таких — информация о багах в старых версиях, которые уже никого не волнуют, «обходные пути», которые устарели из-за улучшений в языке, и масштабные «выкосы» API. Когда-то у нас было очень подробное описание CORBA, и избавиться от этого было довольно лёгким решением. Когда удалили описание RMI, некоторые читатели расстроились, но слушайте, когда в последний раз кто-либо использовал это не в игрушечном примере? А теперь подбирается следующее сложное решение: что делать со Swing?
Порой в текст пробирается техническая ошибка, и я веду список замеченных ошибок, так что читатели могут о них сообщать. Я очень серьёзно подхожу к этим «баг-репортам», чтобы ошибки не проживали дольше одного издания. К счастью, ситуация «каким глупым я был» возникает нечасто, но порой моя точка зрения со временем развивается. Например, когда появились вложенные классы, я очень подробно объяснил, как работал захват локальных переменных, приводя результаты декомпиляции через javap. Позже я задумался об этом. Объяснял ли я в таких же подробностях, например, как технически работает вызов методов? Нет, и читатели не требовали таких деталей. На практике программисты полностью готовы доверять компилятору в том, что он способен разобраться и с вызовом методом, и с захватом локальных переменных, так что я убрал бесполезные детали.
Ещё хлопот доставляет рост информации, относящейся к конкретной версии. «Если у вас Java 6 (бедняжка), можете делать так-то, начиная с Java 7, можете делать и так, а в Java 9 вы почти достигаете нирваны, потому что теперь можете делать что-то ещё». В книге «Core Java for the Impatient» я просто объясняю, как работает последняя версия Java, представляя себе программиста, уже владеющего, например, JavaScript. Это очень освежает. Но, разумеется, многие пользователи вынуждены иметь дело с различными версиями, так что классическая «Core Java» по-прежнему будет это учитывать.
— В то время как некоторые книги обращаются к узкой аудитории, «Core Java» открывают самые разные люди, у которых знания и опыт очень различаются. Возникают ли сложности, когда пишешь «для всех»? Что помогает с ними справляться?
— Сложности есть, и неизбежно, что от читателя-новичка нельзя ждать понимания всего продвинутого материала. Я ожидаю, что читатель, который только учится объектно-ориентированному программированию, будет внимательно разбираться с наследованием и интерфейсами, а на рефлексию или модули лишь бегло взглянет, в то время как эксперт сделает противоположное. С главами об API проще, там для читателей естественно пропускать те главы, которые их не интересуют.
В наше время мало кто читает книгу по программированию от корки до корки. Многие мои читатели используют Safari Books, где просто открывают страницы, посвящённые конкретной теме. И я структурировал книги серии «Impatient» так, чтобы материал был легко понятен в этой форме, без постоянных отсылок к другим местам той же книги.
— Когда пишешь о Java на протяжении многих лет и вдаёшься в детали, возникает ли ощущение «как многое в Java сделано совершенно неправильно»? Пробовали ли что-то улучшить?
— Разумеется, когда речь о такой большой и сложной платформе, как Java, есть множество вещей, с которыми что-то не так. Но только в редких случаях что-то ужасно не так: например, это существование примитивных типов, которым следовало быть внутренним делом виртуальной машины. (И я надеюсь, что в будущем новая версия Java это исправит.)
Но, разумеется, есть множество мелких раздражающих факторов. Например, почему API потребовалось двадцать лет, чтобы дать нам метод для чтения потока в массив byte? Почему API для юникода такой неприятный? Я мог бы назвать десятки других.
К сожалению, их не так просто исправить. В других опенсорсных проектах кто-то просто предложил бы что-то лучше, могла бы возникнуть дискуссия, произойти доработка, и затем перемены были бы приняты, если бы только не возникли резкие возражения. А в случае с Java полная противоположность. Нужны ресурсы, чтобы активно продвигать любое изменение и чтобы оно прошло через регулирующую структуру. Разумеется, от этого есть польза, это означает, что у вашей программы Java 1.0 отличные шансы успешно скомпилироваться. Но это также отпугивает всех от каких бы то ни было изменений.
В качестве примера: я однажды предложил, что нужна возможность запустить программу, вызвав конструктор (с параметром String[] или без аргументов) класса, указанного в командной строке, если этот класс не содержит метода main. Я даже имплементировал это — код запуска в VM не такой уж сложный. Почему мне вообще было до этого дело? Потому что это было бы манной небесной для студентов и преподателей, которым не пришлось бы иметь дело с public static void main в первой же лекции. «Hello, World!» выглядел бы так:
public class Greeter
{
public Greeter()
{
System.out.println("Hello, World!");
}
}
Вторая пробная программа могла бы сразу же нырять в объекты, не беспокоясь о «static».
Не было никакого риска ошибок обратной совместимости, потому что ранее такой класс просто не мог бы быть запущен.
Было ли моё скромное предложение одобрено? Отнюдь. Оно было отвергнуто как «слишком сложное» и «способное угрожать обратной совместимости».
Но как бы то ни было, со временем многие раздражающие особенности API оказываются исправлены. Возможно, из-за того, что людей в Oracle они раздражают так же, как и нас.
Также давайте не забывать, насколько мы избалованы качеством Java API. Я видел многие API в JavaScript, Python и C++, которые заставляли меня чесать затылок и диву даваться, почему кто-либо мог спроектировать API так.
— Приходилось ли вам слышать от Java-разработчиков, что ваши книги не только научили их Java, но и повлияли на их стиль программирования?
— Нет, такого я от читателей не слышал. Возможно, они оставляют такие мысли при себе :-) А если серьёзнее, я обычно не уговариваю использовать конкретный стиль. Меня всегда немного раздражает, когда другие авторы говорят мне, что я делаю что-то неправильно, так что я стараюсь не поступать так же. Например, я не говорю читателям, что им следует быть менее объектно-ориентированными и более функциональными, или более реактивными, или ещё что-то. Я представляю преимущества различных подходов, и оставляю читателям возможность выбирать.
Есть исключение. Я написал книгу по Scala, где у меня довольно чёткая точка зрения: взгляд Java-программиста, который не хочет отказываться от своей объектно-ориентированности и переходить на чистое функциональное программирование. Тем читателям, которые разделяют мою точку зрения, понравилось. Тем, которые не разделяют — не очень.
В этом опасность книги с личным мнением. Если оно не настолько верное и убедительное, что становится мнением большинства, то вы ограничиваете собственную аудиторию. В случае с книгами «Core Java» я говорю читателю, как использовать Java эффективно, но помимо этого, не проповедую никакие конкретные методологии.
— У вас на сайте в разделе «memorable quotes» есть цитата, подкалывающая Герберта Шилдта. Поскольку ваши книги о Java конкурируют, хочется узнать — это просто шутка, или у вас соперничество? :)
— С Гербом — нет. Я никогда его не встречал. Я даже не знаю, существует ли он. Может, это кодовое имя для программы с искусственным интеллектом. Шучу, Герб :-) Мне просто понравилась цитата.
Мой редактор однажды сказал, что не может поверить, что я пожал руку автору конкурирующей книги. Я смотрю на это иначе. Есть авторы, которыми я восхищаюсь, а есть и такие, чей стиль я не стал бы перенимать. Но другие люди покупают и, по-видимому, любят их книги, так что я общаюсь с ними, узнавая больше о их подходах и их читателях.
А помимо этого, не каждый покупает книгу или смотрит видео, потому что хочет получить знания. Некоторые предпочитают, а некоторые авторы предоставляют, иллюзию знания.
— Вы участвовали в создании курса Intro to Java Programming на Udacity. Ощущаете ли вы, что будущее обучения программированию за онлайн-курсами? Становятся ли книги менее актуальны? Что бы вы посоветовали в первую очередь человеку, который хочет стать разработчиком: книгу или MOOC?
— Это тоже отличный вопрос. Когда я занялся MOOC-курсом, что произошло в рамках сотрудничества моего университета и Udacity, мне сказали: «Вы ничего не знаете, мы научим вас учить». И они научили меня полезным техникам. Ограничивать видеосегменты тремя минутами. Не давать ответ, а задавать вопрос. Делать всё визуальным. С точки зрения «первых шагов для человека, который хочет стать разработчиком» результат мне очень нравится.
Но Udacity также сказали: «Вы не можете требовать от обучающихся читать книгу. Даже отдельные страницы». А учащиеся это возненавидели. Их раздражала необходимость пересматривать видео только для того, чтобы найти какую-то конкретную информацию.
Так что, если бы мне пришлось выбирать между видеокурсом (будь то MOOC или нет) и книгой, я бы всегда выбрал книгу. Но я сейчас работаю над проектами, где эти две части объединяются: интерактивная часть для первого контакта, а книга для более глубокого понимания и в качестве справочника. Возможно, вот к этому и идёт мир.
MOOC могут быть отличными, если не просто смотришь видео. Если они снабжены серьёзным интерактивным материалом, заставляющим действовать, думать и учиться, и если на самом деле действуешь, думаешь и учишься, они могут быть очень эффективными. Но если просто прокликиваешь видео и распечатываешь сертификат, то это иллюзия знания.
— У вас есть опыт работы и в университетах, и в стартапе, то есть вам знакомы и академический мир, и индустрия. Каково переключаться между этими контекстами? Как далеко эти два мира друг от друга?
— Здесь кроется распространённое недопонимание. Студенты часто спрашивают что-то вроде: «Почему мне надо учить теорию автоматов? Что мне действительно нужно, так это курс по AngularJS».
Я не спорю с тем, что если студенту для конкретного проекта нужен AngularJS, то ему стоит учить AngularJS. Но в качестве университетского курса??? Университет хорош для того, чтобы научить вещам, которые будут по-прежнему актуальны спустя 20 лет. И научить учиться. Так что через 20 лет, когда бывшему студенту будет нужно изучить фреймворк XYZ, у него будет бэкграунд и навыки, чтобы быстро освоить его самостоятельно.
Некоторые люди считают, что университеты заходят слишком далеко с преподаванием бесполезного материала, и им с их четырёхлетними программами не хватает гибкости. Вот поэтому появляются все эти «хакерские академии» и «nanodegree». Мне самому приходят в голову некоторые способы модернизировать учебную программу в computer science, и я также признаю, что некоторые из этих способов не будут внедрены из-за институциональных барьеров. Но нетрадиционные образовательные программы уходят в другую крайность, не предоставляя достаточно фундаментальных знаний. Они также отличаются от университетов в другом отношении: им требуется фокусироваться только на самых мотивированных людях, способных заполнить многие пробелы самостоятельно.
Другое большое различие между университетом и работой в индустрии заключается в том, что академические исследования концентрируются на оригинальности, а работа в индустрии — на повторимости. В университетах мало ценят качество кода, за исключением людей, исследующих программную инженерию. Возможно, в университетах слишком уж упирают на оригинальные исследования. Пару лет назад я работал в небольшом швейцарском образовательном учреждении, где факультеты награждали за работу с местными компаниями. Мне это показалось хорошей идеей.
— А из-за разницы двух миров не оказывается так, что удачные идеи из академического мира, которые могли бы пригодиться в индустрии, попросту не попадают туда?
— Не знаю, происходит ли такое, чтобы в индустрии упускали много академических работ с прикладной пользой. У многих софтовых компаний есть сотрудники с учёными степенями, очень хорошо знакомые с исследовательской литературой.
Например, посмотрите на беспилотные автомобили. Это началось в университетах, а затем довольно органично переместилось в индустрию.
Или, в мире языков программирования, посмотрите на сборку мусора. Это годами было темой для исследований, но когда стало подходить для индустриальной обстановки, было быстро принято на вооружение. Так что я особо не переживаю по поводу бесценных интеллектуальных секретов, спрятанных в башне из слоновой кости.
— Вы преподавали CS по всему миру — в США, Швейцарии, Вьетнаме и Макау. Чем вызван такой разброс?
— Мне просто нравится путешествовать.
— А с точки зрения вашей работы была ли какая-либо значительная разница между этими странами, или computer science и в Макау computer science?
— Повсюду одно и то же. Везде у меня были и выдающиеся студенты, и не слишком выдающиеся. Ну, вьетнамские студенты не были приучены опираться на собственное суждение. Они постоянно задавали мне самые мелкие вопросы о том, как им следует действовать, а я постоянно отвечал, что они очень умные (они действительно были такими, их отобрали из 1% по результатам школьного экзамена), и им нужно сформировать собственное мнение. Думаю, это их научило большему, чем любая техническая информация, которую я давал в лекциях.
Думаю, нам в computer science довольно повезло с областью, в которой достижения можно оценить довольно объективно, а люди из разных мест успешно сотрудничают. Когда про Силиконовую долину говорят, что там меритократия, это в определённой степени верно. Конечно, только в определённой — мы все слышали истории людей, которым не предоставилась равная возможность проявить себя в качестве программиста. Но в computer science с этим куда лучше, чем в других областях, где основные деньги получают люди из одной тусовки.
— В Википедии указано, что на протяжении нескольких лет вы использовали в книгах собственный стиль отступов, а потом отказались от этого. Почему начали, и почему прекратили?
— История такая. В случае с C у нас есть стиль K&R и стиль Олмана:
if (args > 0) {
printf(args[0]);
}
и
if (args > 0)
{
printf("%s\n", args[0]);
}
Что мы хотим — сэкономить место, или выравнять фигурные скобки? А что, если хотим сразу и то, и другое? Вот тут и вступает в дело «стиль Хорстманна»:
if (args > 0)
{ printf("%s\n", args[0]);
}
Людям он не понравился. Для этого не было никакой заметной рациональной причины; писать так просто казалось странным. В итоге я сдался, потому что у стиля не было поддержки со стороны тулинга. Игра не стоила свеч.
— Недавно в Стэнфорде изменили свой вступительный курс по CS, решив вместо Java использовать JavaScript. Что вы думаете по этому поводу?
— Вступительный курс по computer science — это на самом деле не курс конкретного языка (во всяком случае, не должен им быть). Сложности у студентов возникают с циклами и массивами, с алгоритмами, декомпозицией и дебаггингом. Вне зависимости от того, используете вы Java, C++, Python или JavaScript, студенты скорее застрянут на цикле, чем на public static void main или на контринтуитивных особенностях JavaScript.
Так что не имеет особого значения, какой язык использовать, если только сам курс не акцентирует на этом внимание. Я видел курсы с C++, которые докучали студентам подробностями об указателях, и это не способствовало процессу. А в Стэнфорде всегда был первоклассный курс, с JavaScript они могут сделать его не хуже, чем с Java — но, думаю, и не лучше.
— Вы пишете о Java уже десятилетиями и видели, как всё менялось со временем. Что вы думаете о будущем Java? Она прошла свой пик и будет медленно терять в популярности? Или всё ещё впереди, а молодые JVM-языки вроде Scala и Kotlin помогут всей экосистеме?
— Вскоре после появления Java, во время её стремительного взлёта, было очень ясное ощущение, что Java станет «концом истории». От крошечной смарт-карты и до мощнейшего сервера — Java появилась, чтобы повелевать ими всеми.
Теперь мы знаем, что получилось совсем не так. Java укоренилась на серверах, но теперь ей в затылок дышит Node.js. Не по каким-либо техническим причинам, а потому что «фуллстековые» разработчики не хотят писать клиентскую сторону на JavaScript, а серверную на Java. Учитывая, что UI на Java сегодня редкость, это проблема. Если бы я был королём Java, я бы удостоверился, что Java останется языком для Android, а также продвигал Java-to-JavaScript технологию для браузеров. Но очевидно, что я не являюсь королём Java.
Я также вижу много энтузиазма вокруг Python в областях вроде data science. Нет никакой причины, по которой соответствующие библиотеки не могли бы быть написаны на Java, но они написаны не на ней. И на Kotlin их тоже не пишут. У Scala есть свои заметные территории, особенно Spark.
Моё предсказание очень скучное. Я думаю, мы увидим, как C/C++ продолжат терять позиции, Python и JavaScript будут расти, а новые приятные языки (и на JVM, и не только) будут заявлять о себе, но не достигать такой же популярности. И год за годом техническая пресса будет оказываться удивлена тем, что Java по-прежнему очень популярна, хотя её уже годами провозглашали как теряющую популярность.
На конференции Joker, которая состоится в Петербурге 3-4 ноября, Кей выступит с двумя докладами: «Java 9: the good parts (not modules)» и «Concurrency for humans».
И хотя до этого осталось ещё несколько месяцев, уже завтра (1 августа) билеты на Joker подорожают — так что есть смысл покупать их сегодня.