Что такое код? (перевод)

Специальный выпуск Bloomberg Businessweek, 11.06.2015
Содержание:

Часть 1. Человек в бежевом пиджаке

Часть 2. Что такое компьютер?

Часть 3. Почему программисты так болезненно относятся к языкам?

Часть 4: Почему программисты такие злые?

Часть 5: Совещание о валидации email-адресов

Часть 6: Как создаются приложения?

Часть 7: Триумф менеджера среднего звена

Часть 3. Почему программисты так болезненно относятся к языкам?

Многие конференции организованы вокруг конкретных языков программирования или определённых сообществ. PyCon — для разработчиков на языке Python, Strata — для людей из мира big data, Oscon — для разработчиков софта с открытым кодом. Это ритуальные события для тех, кто в этой теме.

Программисты следят за развитием языков так же, как ярые спортивные фанаты за любимой командой. Они это бесконечно обсуждают на форумах типа Reddit (на ветку /r/programming подписано 620 тыс. человек), или на Hacker News (это сайт венчурного акселератора Y Combinator, названного в честь специальной функции, которая работает над другой функцией), или Lambda the Ultimate (названном так в честь серии статей о языке Scheme). Существуют тысячи программистских блогов, посвящённых каким-то определённым темам. Чем более специфическое название — тем более занудная тема. Из них люди понимают, какие тренды набирают силу, а что медленно умирает.

Но это не про веяния моды. Карьера программиста зависит от того, насколько глубоко он может работать с одним или несколькими языками. У языков существуют рейтинги популярности, которые постоянно обновляются и они редко кого-то удивляют. Согласно, например, индексу Tiobe, на 15 апреля самыми используемыми языками были Java, C, C++, Objective-C и C#, затем JavaScript, PHP и Python. Этот рейтинг не очень точный. Компания RedMonk, например, в своём списке ставит на первое место JavaScript, а затем Java. Из этого можно сделать много разных выводов, но самый очевидный: при прочих равных, сегодня разработчик на Java имеет больше карьерных возможностей, чем поклонник другого, более редкого языка.

Если ты программист, то в твоё поле зрения периодически попадают новые языки. В своих блогах разработчики их хвалят или, наоборот, ругают. Пробовать новые языки — хорошая практика для программиста. Обычно для этого достаточно скачать пару файлов, написать несколько строк кода и решить, стоит ли дальше с ним разбираться. Большинство из них бесплатны.

Но зачем люди создают новые языки, а потом бесплатно их раздают? Потому что создание нового хорошего языка — это работа программиста из высшей лиги. Это монументальный подвиг. Примерно как написание многотомного труда о войне, который все перечитывают. Или как поучаствовать в большой войне. Главная награда за это — слава.

А вот изменение языка — это как бесконечное возвращение к участию в одной и той же войне. Некоторые языки годами застревают в странном промежуточном состоянии между первой, не очень хорошей версией, и новой, обещаной. Perl 5 появился в середине 1990-х, идеально подходил для раннего веба и рос вместе с ним. Perl 6 должен был стать лучше во всём, и его обновление торжественно объявили в 2000 году. Но после пятнадцати лет непрерывной работы — часто бесплатной — официального обновления всё ещё нет. Разработчики других языков, наблюдая за этими мучениями, решили действовать не так масштабно. Разработка Python 3 началась в 2006 году. Первая рабочая версия вышла в 2008-м. В 2015-м переход на новую версию всё ещё продолжается.

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

Code Atlas

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

Некоторые универсальные вспомогательные технологии, типа SQL Server были исключены из исследования

3.1 Красота стандартной библиотеки

Клавная характеристика любого языка, по которой его оценивают, не в правилах расстановки знаков препинания. Всё решает стандартная библиотека. Язык программирования — это софт для создания софта. Стандартная библиотека — это набор предустановленных программных компонентов, которые ты можешь переиспользовать для написания своих программ снова и снова.

Возьмём Python, про который говорят, что он «поставляется с батарейками», имея в виду, что у него на борту имеется тонна готовых модулей, готовых к использованию. В его стандартной библиотеке есть, например, функция для скачивания веб-страниц или скрипты для автоматического внесения изменений в документы и обработки текста.

Давай на примере, что значит «обработка текста»? Допустим, у нас есть строчка текста «The Quick Brown Fox», сохранённая в виде переменной под названием my_string. Мы можем не изобретая ничего нового использовать стандартные методы языка Python для обработки этого текста, например команда my_string.lower() вернёт нам весь текст строчными буквами: the quick brown fox.

Собственно знание возможностей языка и понимание правил его использования — и означает его знание. Для того, чтобы изучить язык, нужно читать его документацию. Но стандартная библиотека — это только начало. Для многих языков — и Python здесь отличный пример — существует огромная экосистема дополнительных готовых модулей. Модуль (его ещё могут называть пакетом или библиотекой) — это код, который расширяет стандартные возможности языка.

Представим, что ты работаешь в рекламном агентстве. Тебе прилетела задача обработать 100,000 изображений: изменить их размер и повысить резкость. Безумная задача, если ты не умеешь программировать. Но если у тебя есть Python, ты вводишь команду sudo pip install Pillow, после которой скачивается и автоматически устанавливается новый модуль для работы с изображениями в рамках общего пакета Python.

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

И награда за это впечатляющая! Как только ты установила Pillow тебе становятся доступны десятки различных функций для работы с изображениями: теперь ты можешь менять цвета, вращать картинки в любую сторону, масшабировать, конвертировать GIF в JPEG — и всё это с такой скоростью, которая никакому Фотошопу и не снилась.

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

Быть программистом означает не только писать странные команды в файле. Это ещё и умение ориентироваться во вселенной чужого кода: где хорошие библиотеки, где качественная документация и где самые полезные форумы. Без этого понимания ты будешь тратить время на поиски, вместо того, чтобы создавать что-то интересное.

3.2 Чем отличаются разные языки?

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

Программист на C и программист на Java, в принципе, могут читать код друг друга. Но заставить код на C и код на Java работать вместе — гораздо сложнее. Эти языки по-разному представляют мир, по-разному структурируют данные и по-разному взаимодействуют с частями компьютера. Когда вся команда использует один язык, это даёт серьёзное преимущество: все мыслят одинаково о том, как именно объяснять машине, что делать с данными.

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

Некоторые языки, как например C, стараются сделать в точности то, что ты его попросила, даже если это приведёт к поломке компьютера. Другие, типа OCaml или Haskell, более строгие и выполняют только задачи, соответствующие определённым требованиям и заранее защищают программиста от совершения глупостей10.

10 Большую часть времени программисты работают с разными типами данных. Представим, что у нас есть код, который решает уравнение x*y. Что случится, если под x мы подставим 7, а под y укажем «кот»? Во многих языках это приведёт к ошибке, потому что число нельзя умножить на слово.

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

Некоторые языки очень строго следят за типами данных и за тем, какие операции с ними допустимы. Они заставляют программиста чётко определить типы заранее. Другие языки живут по принципу «сам виноват, программист».

У некоторых языков есть милые логотипы. Например, у языка Go — суслик.

Существует Scratch — учебный язык для детей. Он почти не использует текст: юные программисты двигают иконки на экране и собирают программы, как из Lego. Его логотип — улыбающийся кот на двух ногах.

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

Некоторые языки пользуются уважением в индустрии за свою элегантность. Их называют каноническими языками программирования. Одним из таких языков является «C». Многие популярные языки очень похожи на него. Логотипом языка «C» является буква «C». А такое название он получил потому, что появился после другого языка. Тот язык назывался «B».

3.3 Значение языка C

Язык C настолько важен, насколько ты себе можешь представить важность вычислений. Его создал Деннис Ритчи в 1950-х в Bell Labs, и он стал главным языком разработки для операционной системы UNIX (маленькими буквами теперь пишут идею Unix, а не торговую марку). Это была довольно простая операционная система. По сути — это ядро11, которое управляет памятью и запускает программы, плюс набор очень маленьких программ и «оболочка», которая позволяет связывать программы в нужный тебе порядок (скрипты). Если с помощью имеющихся скриптов, ты не могла сделать то, что хотела, ты могла написать свою программу на C и добавить её в библиотеку системных инструментов.

11 Ядро — это самый нижний уровень операционной системы. Ядро — это как двигатель автомобиля. Приборная панель, колёса и кузов могут быть сделаны кем угодно. Но без двигателя это всё никуда не поедет.

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

C — очень простой язык. Такой же простой, как дробовик, которым можно отстрелить себе ногу. Он позволяет управлять каждой деталью компьютера: памятью, файлами, жестким диском. Он просто идеален, если ты понимаешь, что делаешь. Программы, написанные на C известны своей скоростью, потому что при его компиляции используется несколько уровней оптимизации (в программировании это что-то типа налоговых лазеек). Можно представлять себе C как прямолинейного деда, который вырос среди охотников-браконьеров, прошёл несколько войн и до сих способен подтянуться 50 раз.

Легендарное руководство по языку — «The C Programming Language», написанное в 1978 году Ритчи и Брайаном Керниганом (его обычно называют просто K&R), — удивительно короткая и ясная книга. Физически она тонкая, особенно по сравнению с современными тысячестраничными руководствами для разработчиков. Именно из этой книжки программа «Hello, world!» стала каноническим примером работы кода для любого языка программирования.

Вот этот первородный текст языка самопредставления программы:

#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
}

Что после компиляции и запуска программы выведет на экран «Hello, world!». Теперь напишем программу, которая принимает число x и выводит квадрат всех чисел от 1 до x. Это задача из тех полезных и жизненноважных программ, с которых обычно начинают обучение программистов, чтобы продемонстрировать как может быть решена срочная потребность разработчика в списке корней:

#include <stdio.h>

void squares(int v)
{
  for (int i=1;i<v+1;i++) {
    printf("%d ", i*i);
  }
  printf("\n");
}

int main()
{
  squares(10);
}

Чтобы запустить эту программу на Маке, я сохранил этот файл как squares.c, открыл Терминал и ввёл команду:

gcc squares.c
$ ./a.out

Если дословно, то эта команда создала файл a.out и вывела мне его содержание:

1 4 9 16 25 36 49 64 81 100

Написанный нами код нельзя назвать идеальным. Но если приглядеться, можно понять, как из маленьких повторяющихся блоков собирается программа. Главная часть в ней — функция под названием квадрат (squares), которой мы скормили число. Функция берёт все числа от 1 до нашего числа, возводит каждое в корень и печатает его на экране. После этого печатает новую строку. Конец.

Ядро операционной системы Linux написано на C. Программа, которая связывает твой принтер с компьютером, скорее всего написана на C. Большинство веб-сервисов, которые генерируют тебе странички в интернете тоже часто написаны на C. Кроме того, это прекрасный язык для написания других языков! Python, PHP и Perl, как и многие другие тоже написаны на C.

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

Помнишь тот список популярных языков, в котором были C++, Objective-C, C# и Java? Большинство разработчиков сегодня пишет код не на чистом C, а на одном из его потомков. Их сторонники приводят массу аргументов: они лучше подходят для больших приложений и сложных команд, они организованы в библиотеки, которые легче совместно использовать, переиспользовать и поддерживать без лишних страданий. Все они объектно-ориентированные версии C.

3.4 Корпоративная объектная революция

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

У этого термина тоже существует масса определений, я дам своё и буду гововиться к последствиям. Объектно-ориентированное программирование по своей сути — это система организации кода. Любой, кто создавал общую сетевую папку или пытался организовать бумаги в архиве, знает: без нормальной системы этим невозможно будет пользоваться. В 1980—х и 90-х люди восхищались языком C, считали его привосходным. Но он не позволяет организовывать порядок. В конце концов у тебя получается набор функций, сваленных в одну кучу. Полный бардак.

Ну скажем, у нас есть некая структура данных о наших клиентах (имя, адрес и так далее) и набор функций для работы с этими данными (update_address, send_bill, delete_account). Проблема в том, что эти функции никак не связаны с данными кроме негласных правил и намёков в названиях. Сам язык об этих связях ничего не знает, и нет никакого механизма, чтобы указать «вот эта функция относится к вот этим данным». Что означает, что в будущем для понимания назначения функции тебе придётся догадываться об этом или из их названия, или полагаться на собственную память. Язык C не умеет называть вещи. Что приводит к тому, что в последствии их становится сложно искать.

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

А что если, что если мы просто попробуем, чисто ради эксперимента, что если мы создадим маленькую коробочку под названием Customer (назовём её «класс» — чисто в таксономическом смысле, как Customer является подклассом вида «человек», который в свою очередь является подклассом млекопитающих и так далее.), и сложить в неё всё что относится к нашим клиентам — и данные, и методы, которые с ними работают. Технически запишем это public class Customer {}, а всё, что внутри фигурных скобок будет относиться к этому классу.

Причем заглядывать внутрь этой коробочки тебе не обязательно. Ты просто скачиваешь большой набор каких-то классов, они каким-то образом вложены друг в друга, смотришь в документации доступные методы работы с ними и ожидаемые результаты, и начинаешь программировать. Кладёшь данные в коробочку, получаешь что-то на выходе. Каждый новый клиент создаёт новый экземпляр соответствующего класса Customer. Код превращается в чёрный ящик, из которого торчат щупальца и провода, и тебе не нужно (и не хочется!) знать, что там внутри происходит. Ты просто ставишь два таких ящика рядом, соединяешь их щупальца и наблюдаешь их таинственное взаимодействие.

И это прекрасно работает, в теории.

Эталонный объектно-ориентированный язык Smalltalk создавался командой гениев в Xerox PARC в самые плодотворные годы этой легендарной лаборатории. Smalltalk появился на свет в 1972 году — том самом, что и C — и окончательно оформился к 1980-му. На его разработку повлияли множество больших идей, витающих в то время в информатике, а ещё — платонизм, клеточная биология и язык-предшественник Simula, первый объектно-ориентированный язык, который, как следует из названия, был создан для… симуляции объектов. Пока C развивался в лабораториях промышленного гиганта AT&T для решения их внутренних задач, Smalltalk создавался в исследовательском отделе другого гиганта, Xerox, чтобы решать задачи далёкого будущего. Отсюда и разное мировосприятие двух языков.

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

Один не лучше другого и не хуже. Они разные. Вот пример кода на Smalltalk:

Transcript show: 'Hello, world!'.

Этот код выводит на экран в окне Transcript заданную фразу. Transcript — это объект, который принимает сообщение show: с аргументом — то есть входными данными — в нашем случае это «Hello, world!» Ты вводишь команду, выделяешь её мышкой (уже в начале 80-х!) и говоришь компьютеру её выполнить. Он компилирует этот объект и добавляет к другим объектам уже работающей системы. Это выглядело примерно так:

Множество окон, которые «переговариваются» друг с другом. Каждое окно — объект. Вместо программирования и компилирования кода ты просто погружаешься в эту живую, дышащую, оконную среду и начинаешь создавать объекты, которые отправляют сообщения другим объектам. Если ты сохранила текущее состояние, через пять лет всё будет находиться ровно там, где ты их оставила.

Изюминка в том, что все эти коробочки можно трогать. И это выглядело пугаеще мощно: в других языках всегда существуют чёткие границы между данными и кодом, между файлами и исполняемыми программами, между программами и операционной системой, между открытым и закрытым софтом — здесь все эти границы были намеренно размыты. Smalltalk представлял собой видение компьютера как самостоятельной и самодостаточной среды. Вся система могла быть изменена кем угодно. Основная версия языка называется Squeak с мышкой на логотипе, а обновлённая — Pharo с маяком. Обе бесплатны и доступны для скачивания.

Для меня, как средненького программиста, Smalltalk кажется абсолютно завораживающим! Но он так и не смог затянуть меня на свою сторону Зазеркалья. Когда-то я пообещал себе однажды прочитать или хотя бы осмысленно пролистать всю спецификацию Smalltalk. Которая по сути представляет собой грандиозную попытку организовать реальность посредством компьютерного кода. Проблема в том, что это требует от читателя принятия не только методов работы, но и философию мира, который организован как иерархия классов. Быть адвокатом Smalltalk — это примерно как быть фанатом словенского кинематографа или фри-джаза. Среди её поклонников бывают невероятно талантливые люди. Но я не дотягиваю до их уровня.

Историю Smalltalk обычно описывают как немного трагичную. Поскольку многие их по-настоящему революционные идеи так и не были реализованы в культуре программирования. Но он всё ещё жив, у него есть пользователи и любой может скачать и установить его на свой компьютер. Кроме того мы видим его влияние во многих других сегодня популярных языках:

  1. Java работает на виртуальной машине, идеи которой заложены Smalltalk;
  2. Objective-C, как следует из названия, соединил в себе C и Smalltalk;
  3. C# (произносится «си-шарп») основан на C, испытал влияние Smalltalk и Java и создан Microsoft для своего фреймворка .NET;
  4. C++ — объектно-ориентированная версия C, хотя корни его уходят скорее к Simula.

Количество цифровых инноваций, появившихся в 1972 году (это, кстати, год выхода «Крёстного отца»), и обсуждающихся до сих пор — ничтожно мало. Мир постоянно на что-то отвлекается вместо погружения в чистое видение тех великих идей. Но не смотря на это, я считаю Smalltalk оглушительным, диким и глобальным успехом всей индустрии.

3.5 Смотри, какие масштабные и странные вещи можно делать с помощью Python

Python — это ещё один популярный и довольно интересный язык. Он объектно-ориентированный, но без фанатизма12. Он сильно проще и понятней для разрабочиков по сравнению с C, поскольку предоставляет им больше абстракций. Он скрывает большинство механических странностей и всяких подробностей о том, как происходят вычисления. Он работает заметно медленней, чем C, но такова цена упрощений и дополнительных уровней абстракций. Но в большинстве реальных задач это отличие в скорости не имеет значения, сколько бы кто не возмущался. Это становится проблемой только в случае, если какой-то фрагмент написанного тобой кода выполняется миллиарды раз, заметно тормозя компьютер.

12 «Объектно-ориентированный», «императивный» и «функциональный» — это парадигмы. Языки вроде Python принято называть «мультипарадигменными».

Возможные проблемы со скоростью — не повод отказываться от Python, поскольку у него есть заслуженная репутация «языка-клея». Ты можешь взять код на других, низкоуровневых языках — типа C, C++, Fortran или любой другой близкий к железу код, — и написать для них «функции-обёртки». То есть встроить супер-быстрый код в медленную, но зато удобную систему.

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

Стиль Python настолько полюбился программистам, что они стараются его «склеить» буквально со всеми другими языками. Настолько, что если с какими-то языками Python сам по себе не очень хорошо работает, они создают специальные версии: существует Jython для работы с Java, или IronPython для работы внутри окружения Microsoft.NET. Люди тратят десятки тысяч часов, чтобы стало возможным работать с Python в любой среде. Вокруг языка постоянно проводятся конференции, выпускаются обновления и делаются живые рассылки.

Язык выбирают в том числе и за его культуру. Разработчики на Python чаще всего очень приятные люди.