Я зарабатываю в интернете с 2007 года, с тех пор как оставил работу на полную ставку в качестве менеджера по маркетингу и основал собственную компанию, специализирующуюся на издательских и консультационных услугах.
Мой первый сайт, PersonalMBA.com, дает мне средства к существованию: в сущности, я обучаю науке бизнеса, хоть и не преподаю в университете. Каждый год я пополняю список написанных мною книг, которые посвящены законам бизнеса и предназначены для читателей, желающих овладеть его основами [1]Ad infinitum — до бесконечности (лат.). — Прим. пер .
.
С момента первой публикации в 2005 году список рекомендуемой литературы из книги «Сам себе MBA» оставался одним из самых популярных, а дополнения к этому списку делают посетители сайта со всего мира. С 2005 года сайт PersonalMBA.com посетили более 2 миллионов читателей.
Моя первая книга «Сам себе MBA» была естественным развитием сайта PersonalMBA.com и стала международным бестселлером. Издание книги предполагает также и ее распространение, и поэтому я на протяжении нескольких лет изо всех сил старался привлечь новых читателей.
О книге «Сам себе MBA» упоминалось в New York Times, Wall Street Journal, Fortune, Forbes, FastCompany, на многих популярных сайтах, в блогах. И после каждого такого упоминания на PersonalMBA.com приходили тысячи новых посетителей.
Цена прогресса
Тысячи посетителей вашего сайта — это здорово, но при условии, если все они имеют возможность одновременно на него попасть. Моя проблема состоит именно в этом: каждый раз, когда трафик сайта значительно увеличивается и достигает определенного порога, сайт рушится в зените своей славы и популярности, оставляя посетителям лишь сообщения с кодом ошибки.
Вот типичный пример: популярный блог Lifehacker.com, посвященный программному обеспечению и компьютерам, за последние семь лет три раза помещал список литературы «Сам себе MBA». И каждый раз тысячи людей одновременно пытались зайти на сайт PersonalMBA.com, перегружая мой веб-сервер (компьютер, предоставляющий веб-страницу по запросу пользователя). Вместо запрашиваемой информации сервер выдавал сообщение «Ошибка установки связи с базой данных» или «Ошибка 503», что эквивалентно просьбе о пощаде в цифровой форме.
И каждый раз, когда сервер падал из-за перегрузки, вместе с ним умирала частичка моей души. Время, потраченное на маркетинг моего сайта, оказывалось израсходованным впустую. В конечном итоге мне удавалось заинтересовать своим предложением тысячи любознательных людей, но из-за рухнувшего сервера они уходили разочарованными, с пустыми руками. Маркетинг оказывался слишком хорош, и система не справлялась с внезапно возросшими требованиями.
Изучение проблемы
Моя первая реакция — усилить сервер, добавив вычислительной мощности и памяти. Это помогло, но лишь до некоторой степени. При превышении определенной нагрузки мой сайт снова рушился, что совпадало с каждым серьезным успехом в маркетинге.
В то время PersonalMBA.com использовал популярную систему управления сайтами под названием WordPress [2]Гладуэлл М. Гении и аутсайдеры. Почему одним всё, а другим ничего? — М.: Манн, Иванов и Фербер, 2013.
. Эта система оптимизирована под легкость установки и использования, а не под работу с большими нагрузками. В стандартной конфигурации WordPress каждый запрос веб-страницы запускает цепочку действий сервера, генерируя сотни внутренних запросов, чтобы предоставить каждую страницу пользователю.
Такой процесс делает каждый отдельный запрос веб-страницы «затратным». То есть выполнение каждого запроса требует выделения существенного объема памяти и вычислительной мощности. Если один посетитель сайта просматривает пять страниц, то он генерирует пять затратных запросов. Если тысяча посетителей сайта одновременно обращаются к одной и той же странице, то сервер попытается запустить тысячу идентичных затратных процессов одновременно.
Система зависла
В такой ситуации бедный осаждаемый запросами сервер попытается ответить на все запросы, но поскольку каждый из них требует значительных ресурсов, память сервера будет исчерпана раньше, чем он справится со всеми ими. В этот момент сервер выбрасывает белый флаг — и посетители сайта остаются ни с чем.
В попытке решить эту проблему я пять раз менял компании, предоставляющие услуги веб-хостинга, и потратил сотни часов, обучаясь конфигурировать серверы WordPress таким образом, чтобы они не отключались при большой нагрузке. Каждая новая конфигурация усложняла сервер, и каждая новая инсталляция требовала все больше времени на ее поддержку.
В конечном итоге я разрабатывал пользовательские конфигурации сервера, требовавшие длинных цепочек загадочных системных команд для установки, настройки и изменения сложных серверных приложений, которые я с трудом понимал. Устранение каждой ошибки или поиск ответов на вопросы, встречавшиеся в процессе установки и поддержки сервера, требовали многочасовых поисков.
И в довершение всего популярность и относительная уязвимость WordPress сделали систему любимой мишенью для хакеров и спамеров. Приблизительно раз в неделю какой-нибудь хакер находит новую уязвимость, а затем использует ее для того, чтобы заполнить спамом миллионы блогов WordPress. Поддержание безопасности системы и своевременное обновление программного обеспечения — это уже работа в полную смену, особенно если вы поддерживаете несколько сайтов. (Я поддерживал 12 сайтов одновременно и катастрофически не справлялся.)
В какой-то момент мне стало ясно, что я трачу больше времени на обеспечение работоспособности сайтов, чем на материалы для своих читателей. Это было бессмысленно. Не только из-за того, что уменьшалась полезная отдача, но еще и потому, что я до этого не обучался программированию. Я узнавал лишь набор ситуативных приемов и «заплаток», применимых конкретно к системе WordPress. Не самый эффективный вариант [3]Шелли П. Б. Озимандия / Пер. К. Бальмонта. — Прим. пер .
.
Я решил поискать другой способ поддержки своих сайтов, и находка многообещающей альтернативы не заняла много времени.
Потенциальное решение
Однажды я наткнулся на Jekyll [4]Привет, как дела, отлично (исп.). — Прим. пер .
, программу управления сайтами, созданную Томом Престоном-Вернером, который известен как основатель социальной сети для программистов GitHub [5]Кауфман Дж. Сам себе MBA. Самообразование на 100 %. — М.: Манн, Иванов и Фербер, 2013.
. Система Jekyll предназначена для того, чтобы заменить WordPress, обеспечив простое управление сайтами без затратных запросов.
Представьте, что у вас есть сотни текстовых документов, содержащих важную информацию, и вам нужно их унифицировать — одинаковый шрифт, одинаковый стиль заголовков и так далее. Если вы напишете программу, которая автоматически отформатирует любой файл нужным образом (вместо того чтобы вносить изменения вручную), это сэкономит вам уйму времени.
Именно так и поступает Jekyll с веб-страницами. Запустите одну команду — и программа создаст законченный сайт, используя те файлы на вашем компьютере, которые содержат нужную информацию и шаблоны. Если необходимо изменить дизайн или содержание страницы, вы просто снова запускаете Jekyll, и изменения автоматически вносятся в весь сайт, экономя ваше время и силы.
Jekyll предлагал многообещающие возможности. Теоретически я мог заменить WordPress просто папкой текстовых файлов на своем компьютере. Мой сайт будет быстрым, как молния, необыкновенно стабильным, и я сэкономлю больше ста часов в год, которые трачу на поддержание сервера.
Однако тут меня поджидала одна ловушка: система Jekyll написана на языке программирования Ruby, которого я не знаю. Я понятия не имею, как писать программы на Ruby или запускать приложения Ruby, предназначенные для пользователей. Кое-что из того, что мне необходимо для управления сайтом PersonalMBA.com, требует большего, чем простое форматирование.
Чтобы управлять сайтами с помощью системы Jekyll, мне нужно научиться программировать, а также запускать программы веб-приложений, написанные на Ruby.
Похоже, я нашел привлекательную задачу.
Научиться программированию
Я уже довольно давно хотел научиться писать программы, однако на первый план всегда выходили другие проекты. Если я научусь программировать, то мои возможности в бизнесе существенно расширятся, поскольку весь мой бизнес связан с интернетом.
Важно отметить, что все, чем я занимался до сих пор, — это не программирование. Языки HTML и CSS, которыми я пользовался для разработки веб-страниц, называются «языками разметки». Коды HTML и CSS просто указывают компьютеру, в каком виде отобразить текстовый файл (то есть «этот текст отобразить жирным шрифтом» или «данный раздел — основной заголовок, шрифт 24 пункта»).
То же самое можно сказать о моих упорных попытках усовершенствования сервера. Конечно, я составлял какие-то программы, но настоящим программированием это назвать нельзя. Я просто устанавливал готовое программное обеспечение, а затем изменял его настройки. Приложения, которые я использовал, писали профессиональные программисты, и для того чтобы их применять, мне не нужно было уметь программировать. Конфигурирование сервера и его поддержка — полезные навыки, но это не программирование.
Что же такое программирование?
Первое, что мне пришло в голову: программирование — это указание, какие вещи должен делать компьютер. Однако такое определение было слишком расплывчатым и бесполезным. Что делать? Какие «вещи»?
10 лет назад в колледже я прослушал два курса по основам программирования и поэтому немного смутился, когда понял, что не могу дать четкого определения этой дисциплине. Я помню некоторые из основных терминов, например переменная, цикл, ввод, вывод, функция, объектная ориентация, а также нечто под названием пузырьковая сортировка. Вот, пожалуй, и все.
Я должен был научиться писать программы на языке C++ и помню, как расстраивался, когда много часов искал пропущенную точку с запятой, из-за которой не работала моя программа. Я также помню слова преподавателя: «Вы никогда не будете использовать пузырьковую сортировку в реальных приложениях, но мы все равно будем ее изучать».
В процессе учебы я написал несколько простых программ, по необходимости: цель состояла в том, чтобы получить хорошую оценку, и я ее получил. К сожалению, программы, которые мы писали, были неприменимы в реальной жизни, а с тех пор я не имел дела с программированием. Несмотря на то что в моей памяти застряли несколько терминов, начинать придется с самого начала, с понимания основ.
Поскольку я не могу точно описать свои намерения, когда выражаю желание «научиться программировать», то предвижу трудности с определением целевого уровня мастерства. «Написать компьютерную программу» — это уже чуть конкретнее, но все равно бесполезно.
Пришла пора суммировать все, что я в данный момент знаю о программировании.
● Я знаю, что программисты «пишут» программы, что предполагает творческую задачу, которую можно решить разными способами.
● Программы часто называют «приложениями», и эти термины взаимозаменяемы.
● Когда компьютерные программы «запускаются» или «выполняются», то делают то, для чего они были написаны.
● Термины «вход» и «выход» запомнить легко, поскольку это обычные слова. Под входом понимают информацию или данные, которые использует программа, а под выходом — результат, получаемый по завершении ее работы.
● «Переменная» — это место для заполнения тем, что меняется. Вы можете создавать сколько угодно переменных, по своему желанию, и обозначать ими все что угодно.
● Сама «программа» представляет собой подробный набор инструкций и правил, которые указывают компьютеру, что нужно делать с входными данными. Когда программа заканчивает свое выполнение, вы получаете выходные данные.
● Программа «виснет» или выдает сообщение об ошибке, когда что-то идет не так и компьютер не может понять, что делать дальше.
Ну вот, уже кое-что. Получилось довольно грубое разбиение на элементы: вместо «программирования» мы теперь имеем три подчиненных понятия.
● Вход — информация, которая используется для выполнения процесса.
● Процесс — последовательность шагов, предпринимаемых программой в соответствии с входными данными.
● Выход — конечный результат выполнения программы.
Такое разбиение очень полезно. «Написать компьютерную программу» означает следующее: определить информацию, с которой вы хотите начать, установить последовательность шагов, точно описывающую действия компьютера с входными данными, а также определить выходные данные, предоставляемые вам компьютером «на выходе».
Представьте себе блок-схему, которая может служить полезной мысленной зацепкой, помогающей понять работу программы. Вы начинаете процесс с входных данных. Затем производите определенные действия в зависимости от выполнения тех или иных условий. Процесс заканчивается по достижении конца блок-схемы. Вы остаетесь с выходными данными: конечным результатом процесса, описанного блок-схемой.
Создание компьютерной программы аналогично разработке блок-схемы. Вы задаете те же вопросы:
● С чего я начинаю?
● С чего начинается процесс?
● Что происходит после этого? А дальше?
● Когда процесс заканчивается?
● Что я получу, когда процесс закончится?
Блок-схемы описывают ответы на эти вопросы в визуальной форме. Программы описывают то же в виде текста, однако суть от этого не меняется.
Аналогия с блок-схемой полезна также потому, что помогает объяснить и другие важные понятия.
Условные операторы — это выражения такого вида.
● Если X истинно/ложно, то делать Y.
● Если X не Y, то делать Z.
● Когда X истинно/ложно, то делать Y.
● Когда X не Y, то делать Z.
● Пока X истинно/ложно, делать Y.
● Пока X не Y, делать Z.
В данном случае X, Y и Z — это переменные, которые могут обозначать все что угодно. Переменные могут обозначать числа, как в элементарной алгебре, или слова. Иногда переменные — это отдельные буквы или символы, а иногда целые слова. В любом случае они обозначают объекты, с которыми мы работаем.
Условные операторы (ЕСЛИ, ТО, КОГДА И ПОКА — IF, THEN, WHEN и WHILE) подобны стрелкам с вопросами на блок-схеме. Представьте себе, что вы за рулем автомобиля: ЕСЛИ (IF) сигнал светофора красный, ТО (THEN) вы останавливаетесь. КОГДА (WHEN) сигнал светофора сменяется на зеленый, ТО (THEN) вы едете. КОГДА (WHEN) сигнал светофора желтый, ТО (THEN) вы тормозите, готовясь остановиться.
Имеет смысл остановиться на этих условных операторах немного подробнее, поскольку здесь есть несколько общих закономерностей. Условие истинно/ложно встречается довольно часто, а оператор ПОКА (WHILE) указывает не на одно конкретное действие, а на продолжение тех или иных действий.
Во всех случаях условный оператор содержит высказывание, которое определяет, нужно ли предпринимать какие-либо действия. Это высказывание называется условием и может принимать разные формы. Иногда условие представляет собой простое сравнение типа истинно/ложно (Сигнал светофора красный?), иногда математическое сравнение (Х больше 100?), а иногда содержит логическую конструкцию (Сигнал светофора НЕ красный?).
Назначение условия — определить, будет ли выполняться соответствующий процесс. Если условие истинно или достоверно, программа выполняет определенную команду. Если нет, то эта команда пропускается, и программа переходит к следующей.
Переменные типа истинно/ложно называются булевыми переменными — это красивое название обозначает то, что может принимать всего два значения. Да/нет и включено/выключено тоже относятся к булевым переменным. Булевы переменные играют большую роль в программировании, поскольку являются основой как простейших процессов (подобно истинно/ложно в блок-схемах), так и для включения/выключения крошечных электронных переключателей, из которых состоит компьютер.
В данном случае ПОКА (WHILE) — это особый тип условного оператора, который называется циклическим. Циклический оператор заставляет процесс повторяться до тех пор, пока не будет выполнено условие. Вернемся к аналогии управления автомобилем: ПОКА (WHILE) сигнал светофора красный, ехать нельзя.
Все очень просто, правда? Если провести аналогию между написанием компьютерной программы и составлением блок-схемы, этот процесс будет довольно легко представить.
И еще одно, последнее замечание: что будет, если компьютер зайдет в тупик, не зная, что ему делать, или команды, которые компьютер пытается выполнить в какой-то момент, не работают или не имеют смысла? Что произойдет?
В таком случае программа «вылетает» — останавливается и нередко вместо ожидаемого результата выдает сообщение об ошибке. Мы все знакомы с внушающим страх «синим экраном смерти» Windows или с сообщением «Ошибка 404: веб-страница не найдена» при поиске в интернете. Иногда происходит непредвиденное, компьютер «сходит с ума» и зависает.
Ваша задача как программиста предотвратить зависание и ошибки программы. Лучший способ — убедиться, что программа всегда имеет информацию, чтобы завершить процесс так, как планировалось, но это не всегда возможно. В тех случаях, когда неопределенности не избежать, полезно предусмотреть способ восстановления, если программа не может завершить процесс.
Эти операторы восстановления после ошибки называются исключениями, и они очень полезны. Их можно считать условными операторами, связанными с ошибкой: ЕСЛИ (IF) программа вылетает по ветке Х, ТО (THEN) делать Y вместо Х.
Исключения немного похожи на резервный генератор для больничного оборудования. Бо2льшую часть времени генератор просто присутствует, но не работает. Но если электроснабжение прервется, генератор включится, и больница будет использовать электроэнергию, вырабатываемую генератором, а не погрузится в полную темноту. Это спасет жизнь пациентам, подключенным к аппаратуре поддержания жизнедеятельности, которой требуется бесперебойное электропитание. Полный отказ опасен, и потому резервные планы очень важны.
Это и есть основы программирования. Определить входные данные. Ввести переменные. Создать процессы, которые ведут к желаемому результату. Рассмотреть эти процессы как блок-схему, добавив при необходимости условные операторы и исключения. Если все идет хорошо, ввести входные данные, запустить программу и получить желаемый результат.
Это сильное упрощение чрезвычайно сложного занятия, но достаточно подробное для того, кто впервые сталкивается с программированием. Разбив процесс создания программы на составляющие, легче понять, с чего нужно начинать.
Языки программирования
Тут возникает еще одна трудность: компьютер не разговаривает так, как люди. В сущности, работа компьютера основана на переключении крошечных электронных переключателей. Если у компьютера нет какого-либо способа перевести наш человеческий язык в команды переключения электронных элементов, он не сможет выполнить нашу команду.
Именно для этого и предназначены языки программирования: они предлагают программисту конкретный способ объяснить компьютеру, когда нужно начинать работу, что делать и когда остановиться. Они также позволяют программисту определить входные данные, процессы, выходные данные и действия по завершению программы.
В каждом языке программирования определен свой способ написания команд, который называется синтаксисом. Синтаксис языка включает правила, которые компьютер использует для перевода строк программы в команды крошечным электронным переключателям.
Практически в каждом языке предусмотрен способ описания переменных, условных операторов и исключений. Детали разнятся, но суть одна и та же.
Думать как программист
Программисты часто обдумывают проблемы с помощью так называемого псевдокода: языка, напоминающего язык программирования, но недостаточно конкретного, чтобы его команды исполнял компьютер. Его можно рассматривать как эскиз. Псевдокод помогает обдумать процесс решения задачи.
В примере, описывающем поведение водителя за рулем, я использовал псевдокод. Если сесть в машину и вслух произнести: «КОГДА я поверну ключ зажигания, ТО двигатель запустится», — ничего не произойдет. Но это не значит, что мое утверждение бессмысленно. Оно представляет собой способ обдумать шаги, необходимые для разрешения проблемы или получения желаемого результата.
Вы можете использовать основные понятия программирования, которые мы только что рассмотрели, для создания набросков программ, позволяющих решить повседневные задачи.
Вот забавный способ проверить это на себе. Попросите приятеля помочь вам решить простейшую задачу под названием «сделать сэндвич». Единственное правило — приятель должен лишь точно выполнять ваши инструкции, не больше и не меньше. Он ничего не знает и все ваши указания воспринимает буквально.
Вы: Возьми хлеб.
Приятель: Я не понимаю, что такое «возьми».
Вы: Протяни руку туда, куда я скажу, и схвати его.
Приятель: Я не понимаю, что такое «рука».
Вы (вздыхая): Вот эта штука. (Вы указываете на руку приятеля.)
Приятель: Понял.
Вы: Протяни руку туда, куда я скажу, и схвати его.
Приятель: Я не понимаю, что такое «схвати».
Вы: Согни пальцы вот так. (Вы демонстрируете, сгибая и разгибая пальцы.)
Приятель: Понял.
Вы: Протяни руку к хлебу и схвати его.
Приятель: Я не понимаю, что такое «хлеб».
Вы: Вот эта штука, вот здесь! (Вы указываете на хлеб.)
Приятель: Понял.
Вы: Протяни руку к хлебу и схвати его.
Приятель: (Протягивает руку к хлебу, сжимает пальцы и разжимает. Хлеб остается на месте.)
Вы: ИДИОТСКАЯ ИГРА!!!
Это глупый пример, но именно так выглядит программирование, особенно в самом начале.
Компьютер, подобно вашему приятелю, не может понять то, что вы в точности не определили. Любой сложный процесс, который вы пытаетесь описать, нуждается в полном и однозначном определении.
Именно в этом и заключается сложность программирования: одна-единственная неточная или ошибочная команда делает всю программу нерабочей. В этом отношении программирование не терпит компромиссов — ваша программа либо корректная, либо некорректная. Точность нужна в каждой детали.
Компьютеру безразлично ваше очарование и чувство юмора. Если программа неполная или плохо написана, то ваше приложение зависнет, и вы потеряете данные. Или вы напишете баг: фрагмент неверного кода, который вызовет неожиданные и непредсказуемые последствия. Тут как в математике — либо работает, либо нет. Никто не поставит вам высокую оценку за усердие.
При всем при том в программировании не существует единственного, универсального решения поставленной задачи — так же как и в математике. Есть тысячи способов получить из ваших входных данных желаемый результат. Программист должен выработать конкретный подход на основании имеющихся в его распоряжении средств.
Привыкнув к тому факту, что компьютер не способен читать ваши мысли, вы постепенно учитесь давать инструкции, которые система может понять — точно так же, как вы учились точно определять термины и описывать простейшие действия приятелю в игре «Сэндвич», прежде чем отдавать сложные команды.
В чем особенность программирования интернет-приложений?
Теперь у нас есть рабочее определение программирования. Оно предельно упрощено, однако позволяет понять, что мы пытаемся сделать.
Как бы то ни было, меня не интересуют все разновидности программирования — я хочу писать программы работы с сайтами. Если вы когда-либо пользовались программами электронной почты, например Gmail, Hotmail, Yahoo Mail или любой другой, то понимаете, о чем идет речь. Эти программы выполняются в вашем интернет-браузере. Чтобы использовать их, не нужно загружать программное обеспечение в компьютер. Вы просто указываете нужный сайт в браузере и регистрируетесь. Можно приступать.
Это очень важное отличие программного обеспечения, которое выполняется локально, от того, что выполняется удаленно на интернет-сервере. Чтобы разработать интернет-приложение, необходимо сначала написать его, а затем протестировать, убедившись в его работоспособности. Весь процесс разработки и тестирования выполняется на вашем компьютере.
После того как программа заработала, вы посылаете ее на «рабочий» интернет-сервер, где к ней получают доступ другие люди. Пользователи интернета не могут зайти на ваш компьютер из сети, поэтому загрузка программы на интернет-сервер открытого доступа является необходимым условием, чтобы вашим приложением могли пользоваться другие.
Это значит, что процесс разработки делится на два основных этапа: локальное программирование плюс тестирование — и загрузку программы на удаленный рабочий сервер для реального применения. Я должен выяснить, что представляют собой оба этих этапа.
Из предыдущего опыта работы с HTML и CSS я сделал один вывод: эти языки «немые» в том смысле, что вы не можете заставить главную веб-страницу хранить какую-либо информацию.
Допустим, у вас есть файл веб-страницы, содержащий приветствие «Привет всем!» [6]Холмс Ч. Совершенная машина продаж. 12 проверенных стратегий эффективности бизнеса. — М.: Альпина Паблишер, 2013.
, и вы хотите заменить слово «всем» именем пользователя, который посещает страницу. Отличная идея, но главные веб-страницы не способны хранить информацию, которую можно впоследствии воспроизвести. Они просто воспроизводят текст из файла, а этот файл не позволяет себя изменять.
Это свойство описывается таким техническим термином, как состояние. Главные веб-страницы, созданные с помощью HTML и CSS, не запоминают состояние и поэтому называются ресурсами «без запоминания состояния». На веб-странице вы можете создать окно для ввода имени пользователя с кнопкой «Сохранить», но для сохранения этой информации необходимо предусмотреть для нее специальное место.
Вот почему интернет-приложения используют для сохранения информации два подхода: базы данных и куки-файлы.
Понятие базы данных лучше всего иллюстрирует стопка учетных карточек. Предположим, вы хотите создать адресную книгу, в которой указаны имя, номер телефона, адрес электронной почты, пол и возраст всех ваших друзей.
Каждый друг получает свою учетную карточку, в которой записывается информация о нем. Если кто-то из друзей, к примеру, меняет адрес электронной почты, вы можете стереть старую информацию с карточки и заменить ее новой. Взглянув на любую учетную карточку, вы видите всю информацию сразу.
Стопка учетных карточек аналогична базе данных. Каждая карточка в стопке называется записью. В базе данных у вас может быть столько записей, сколько вам нужно, однако в какой-то момент стопка может вырасти до таких размеров, что пользоваться ею будет неудобно. Нередко имеет смысл разделить стопку на несколько частей: например, друзья и родственники в одной части, коллеги — в другой.
Пока понятно? А вот теперь самое интересное. Представьте, что ваша стопка учетных карточек стала волшебной. Вы можете разговаривать с ней, приказывая показать вам карточки, отвечающие определенным условиям, например:
● покажи мне карточку Джона Смита;
● покажи мне все карточки женщин;
● покажи мне все карточки людей, которым больше пятидесяти лет.
Очень удобно, правда? В сущности, именно для этого и служат базы данных — предоставляют вам способ хранения структурированной информации, а также способ ее извлечения в любой удобной форме.
Каждая разновидность данных, которую мы заносим в карточку, называется полем. Чем больше полей в базе данных, тем больше потенциальных способов извлечения информации, когда она вам потребуется.
Базы данных — самый распространенный способ хранения информации в интернет-приложениях. Если вам нужно хранить такие данные, как имя пользователя, адрес электронной почты, и другие подобные сведения, для этого прекрасно подойдет база данных. После того как Джон Смит войдет в ваше приложение, вы можете извлечь его имя из записи в базе данных, а затем вывести на экран: «Привет, Джон Смит!»
Другой распространенный способ хранения информации в интернет-приложениях — куки-файл. Это очень маленький текстовый файл, сохраняемый на компьютере пользователя. Куки-файлы удобны для хранения небольшого объема данных непродолжительное время.
В случае нашей программы для адресной книги можно хранить куки-файл, созданный в тот момент, когда Джон Смит входит в систему. Куки-файл Джона содержал бы такую информацию: username = johnsmith и loggedin = true. Если Смит покинет приложение, а затем снова вернется, программа распознает куки-файл и откроет доступ без повторной регистрации. Можно сделать так, чтобы куки-файлы хранились определенное время, что удобно для этого типа программирования. (Если вы увидите на сайте сообщение «Запомнить этот пароль», то происходит именно запись куки-файла.)
В данном случае мы производим разбиение на основные элементы. Это ни в коем случае не исчерпывающий список уникальных характеристик веб-программирования, однако его вполне достаточно, чтобы получить представление, чему мне нужно научиться. Это переменные, условные операторы, исключения, локальная/рабочая среда, базы данных и куки-файлы.
Видите, насколько полезным оказалось подобное разбиение? Я начал с туманного представления о том, чем я хочу заняться, а теперь у меня есть конкретный список навыков, которые нужно освоить.
Тем не менее я еще не готов приступать к работе. Помните, я говорил о том, что компьютеры не понимают человеческого языка? Мне нужно выбрать язык программирования, чтобы писать команды программы, а для этого потребуются дополнительные исследования.
Выбор языка для программирования интернет-приложений
В нашем распоряжении есть тысячи самых разных языков программирования, и каждый день появляются новые. У этих языков свой синтаксис, который по большей части определяется тем, для каких задач создавался язык. Каждый язык оптимизирован для решения определенного класса задач.
Прежде чем приступать к изучению программирования, я решил потратить час на просмотр самых популярных сайтов для программистов и выяснить, какие языки рекомендуются разработчикам интернет-приложений. Эти предварительные исследования помогут мне решить, какой язык мне нужно освоить и какие начальные навыки мне потребуются для практических занятий.
Два самых популярных сайта для программистов — это Stack Overflow [7]Аллен Д. Как привести дела в порядок. Искусство продуктивности без стресса. — М.: Манн, Иванов и Фербер, 2013.
и Hacker News [8]Бейлс Д., Орланд Т. Искусство и страх. Гид по выживанию для современного художника. — СПб.: Питер, 2011.
, и поэтому за советом в выборе языка я обратился именно к ним.
Stack Overflow представляет собой диалоговый сайт, место, на котором задают вопросы типа: «Как мне сделать Х?» Опытные и знающие программисты обычно отвечают на вопросы — дают конкретные советы, излагают подходы, указывают, как исправить ошибку, — что делает сайт лучшим помощником в решении сложных задач программирования.
Hacker News — это социальная сеть, собрание ссылок на соответствующие обсуждения. Темы на Hacker News меняются ежеминутно, но все они обычно связаны с новыми достижениями в программировании, технологии и бизнесе, что делает этот сайт идеальным местом для поиска хотя бы первичной информации о новостях программирования.
Программисты всего мира ежедневно создают новые языки, библиотеки и методы. Одни сочетания технологий и подходов годятся для конкретной задачи, другие нет. Зачастую убедиться в этом можно только методом проб и ошибок.
С точки зрения программирования термин «лучший» применим лишь по отношению к задаче, которую вы пытаетесь решить, и к вашим приоритетам. В общем случае рекомендуется 1) выбирать инструменты, позволяющие эффективно решить задачу, а 2) при наличии нескольких вариантов выбирать те, которые вам больше нравятся. Вполне справедливо.
Просмотр архивов Stack Overflow и Hacker News привел к перегрузке информацией: ее было слишком много, особенно для того, кто не знаком с терминологией. Мне требовалось избавиться от ненужной информации, чтобы получить конкретный совет.
Тут помогла одна тактическая уловка, о которой многие не знают: популярные поисковые машины позволяют ограничить поиск конкретным сайтом, чтобы не просеивать всю сеть. Соответствующая команда в Google выглядит следующим образом:
"search phrase" site: example.com
Замените "search phrase" термином, который нужно найти, а "example.com" — адресом сайта, где вы ищете этот термин. Кавычки означают поиск точного соответствия указанной фразе. Если опустить кавычки, Google покажет страницы, содержащие все слова из фразы, но не обязательно в указанном порядке.
Используя этот прием, я задал поиск нескольких фраз: «программирование интернет-приложений», «обучение программированию», «программирование для начинающих», — и потратил еще около часа на просмотр результатов.
И вот что мне удалось выяснить: опытные создатели интернет-приложений советуют начинать с одного из двух распространенных языков программирования, Ruby или Python. Судя по всему, Ruby и Python относительно легко освоить, они достаточно мощные и служат хорошей основой для важных концепций программирования. Ruby более популярен у программистов, специализирующихся на веб-приложениях, а Python предпочитают ученые, в частности математики, из-за большого количества научных библиотек, позволяющих производить вычисления и строить графики.
У обоих языков, Ruby и Python, есть свои активные сообщества разработчиков, огромное количество бесплатных ресурсов, хорошо написанные книги, а также программы и инструменты, облегчающие применение основных функций. Выбор одного из двух языков, похоже, определяется в основном личными вкусами.
Познакомившись с несколькими примерами программ, написанных на обоих языках, я решил изучать Ruby. Для меня как для новичка программные строки на Ruby выглядели аккуратными, удобочитаемыми и казались относительно понятными. Поскольку основные понятия и приемы, которые я освою при помощи Ruby, будут применимы к другим языкам, которые возможно, заинтересуют меня впоследствии, то почему бы не сделать процесс начального обучения приятным?
Кроме того, я собираюсь использовать программы и инструменты, которые либо поддерживают, либо требуют Ruby. В частности, Jekyll написан на Ruby, и поэтому изучение Ruby поможет мне решить мою насущную проблему. Аналогичные инструменты существуют и для Python, но мне кажется, что пользоваться ими сложнее.
Выбор среды разработки
Помимо советов относительно языков программирования, разработчики интернет-приложений делятся сведениями о среде разработки: библиотеках программ, которые облегчают решение задач, встречающихся в каждом приложении.
Библиотеки очень важны потому, что компьютер делает в точности то, что вы ему говорите. Не больше и не меньше.
Это сложно, потому что с точки зрения компьютерной программы существует только код, который вы написали. Как выразился знаменитый физик Карл Саган: «Если вы хотите приготовить яблочный пирог с нуля, вы должны сначала создать Вселенную».
«Вселенная» для вашей программы определяется 1) инструкциями и командами кодовой базы; 2) библиотеками, которые импортирует ваша программа, и 3) системой, в которой выполняется программа. Если код, необходимый для выполнения данной операции, отсутствует в системе, то ваша программа зависнет или выдаст сообщение об ошибке.
Большинство языков программирования включают библиотеки, необходимые большинству программистов, но совсем немного специальных инструментов. Здесь на помощь приходит среда разработки. Вместо того чтобы программировать все с нуля, что займет много времени, вы задействуете среду разработки, которая позволит импортировать и использовать проверенные и надежные библиотеки для решения специальных задач, и сосредоточиваетесь на своем приложении, а не создаете Вселенную.
Среда разработки может иметь разный объем. Некоторые среды включают множество функций и команд в попытке сэкономить программистам время, другие же обходятся минимумом, охватывая лишь несколько основных функций.
В настоящее время у языка Ruby имеется несколько основных сред разработки интернет-приложений. Самые популярные из них — это Ruby on Rails [9]Перевод на русский язык издательства «Питер».
и Sinatra [10]Лоэр Дж., Шварц Т. Жизнь на полной мощности! Управление энергией — ключ к высокой эффективности, здоровью и счастью. — М.: Манн, Иванов и Фербер, 2009.
.
Ruby on Rails (ее часто называют просто Ruby) была одной из первых больших сред разработки интернет-приложений, предназначенных для Ruby. Созданная в 2004 году Давидом Хейнемейером Ханссоном, Rails использовалась для создания нескольких популярных приложений компании 37signals [11]Каминофф Л., Мэтьюз Э. Анатомия йоги. — М.: Попурри, 2012.
, одним из владельцев которой был Ханссон. В настоящее время тысячи компаний разработали серьезные интернет-приложения для бизнеса на основе Rails.
Программный каркас Rails основан на «генераторах», встроенных программах, которые в ответ на одну команду генерируют большой объем стандартного кода. Затем стандартный код модифицируется в соответствии с конкретными требованиями программиста. Rails помогает разработчику сэкономить время и создать работоспособное приложение без необходимости писать программу с нуля — при условии, если он знает, что ему нужно.
Среда разработки Sinatra, наоборот, является минимальной. Sinatra не использует генераторы, а предоставляет в распоряжение разработчика несколько простых функций, необходимых практически в каждом интернет-приложении, а затем самоустраняется.
Приложения Sinatra выглядят простыми по сравнению с приложениями Rails. Одна-единственная команда в Rails может сгенерировать больше десяти папок и больше 20 файлов. Приложение Sinatra во многих случаях состоит всего лишь из одного файла. Sinatra не генерирует большой массив кода, который затем может быть удален, а поддерживает простоту проекта, добавляя ровно столько кода, сколько нужно для работы.
Подобно выбору языка программирования, выбор среды разработки определяется в основном личными предпочтениями и характером задачи. Rails больше подходит для крупных проектов, над которыми работают несколько программистов, а Sinatra — для небольших. У этих двух сред разработки много общего, и недавнее исследование на RubySource.com показало, что выбор между ними по большей части определяется субъективными причинами [12]Дж. Мартин «Песнь Льда и Пламени», перевод Н. Виленской.
.
GitHub — это источник программ с открытым кодом, который используют многие программисты для разработки и поддержки своих проектов. Там легко найти примеры приложений, написанных в Rails и Sinatra, чтобы получить представление о каждой среде разработки, и я потратил еще один час на изучение открытых проектов.
Тут существует нетривиальный риск: чтобы изучить программирование, требуется сделать выбор. После того как вы отдали предпочтение определенному языку программирования и среде разработки, гораздо легче приступить к изучению всего, что необходимо знать для написания программы. Однако, не сделав этого выбора, можно потратить годы на поиски «идеальных» средств программирования.
Лучше выбрать язык и среду программирования, которые кажутся вам привлекательными, потратить какое-то время на знакомство с ними и согласиться на неизбежные компромиссы, чем годами заниматься «исследованиями», не продвинувшись ни на шаг. Целый день просидеть в Stack Overflow и Hacker News — это не программирование.
В конечном итоге я решил начать со среды Sinatra. Генераторы Rails могут сэкономить уйму времени, если знать, что ты делаешь, — но я этого не знаю.
Интуиция подсказывает мне, что в такой ситуации лучше выбрать Sinatra. В этой среде программирования ясный, простой и понятный синтаксис. Единственный код, который существует в приложении Sinatra, — это код, созданный разработчиком. Среда разработки хорошо задокументирована, примеры рабочих приложений можно без труда найти на GitHub, а за помощью обратиться к Stack Overflow.
Когда-нибудь я, возможно, поэкспериментирую с Rails. Но теперь лучше начать со среды разработки Sinatra.
Анализ конечного результата
Потратив около пяти часов на предварительные исследования, я сделал все, что требуется для начала работы: разбил интернет-программирование на элементы, выбрал язык, среду разработки и конкретный проект. Пора приступать к делу.
«Разработать приложение в среде Sinatra, которое обслуживает сайт Jekyll» — так выглядит целевой уровень мастерства, однако мне нужно проанализировать это заявление, чтобы спланировать следующий шаг. Чему я должен научиться?
Еще час исследований, и я получаю вот какой результат.
1. Jekyll создает рабочий сайт из локальных статических файлов. Мне нужно сделать шаблон HTML для сайта при помощи специальных форматирующих тегов и экспортировать архив публикаций с сайта PersonalMBA.com, как описывается в инструкции, написанной Полом Стаматиу[13]Гильбо К. Стартап за $100. Создай новое будущее, делая то, что ты любишь. — М.: Манн, Иванов и Фербер, 2013.
.
2. Приложение, созданное в среде Sinatra, обрабатывает запросы от посетителей сайта, предоставляя им запрошенные файлы. Это приложение я должен написать с нуля.
3. Готовый сайт Jekyll и серверное приложение Sinatra требуется загрузить на сетевой хост.
4. Для решения всех этих задач мне нужно понять, как установить на мой компьютер последнюю версию языка Ruby, а также среду Sinatra и другие необходимые программы.
Последнее требование может служить превосходным примером подготовки необходимых условий для занятий. Если я не смогу понять, как установить Ruby на свой компьютер, то буду не в состоянии перейти к следующим этапам. Так что начинать нужно с этого.
Важно отметить, что интернет-технологии меняются ежедневно. Вполне вероятно, что какие-то последовательности команд, приведенные в данном разделе, уже устареют к тому времени, когда вы будете читать книгу. Не переживайте: важен метод, а не команды.
Аналогичным образом, у вас возникнет искушение лишь бегло просмотреть приведенные фрагменты программы. Это естественное желание: строки кода выглядят слишком сложными, и вы, скорее всего, не сразу поймете, что они означают.
Я бы советовал вам не поддаваться искушению. Эти имена, команды и символы казались мне такими же чужими, как сейчас кажутся вам. Эта глава посвящена процессу, с помощью которого вы разберетесь в том, что они значат и как их использовать. Если вы попытаетесь прочесть строки программы, то извлечете гораздо больше пользы из этой главы.
Вперед!
Обновление Ruby
Компьютер у меня уже есть, и это хорошее начало: без него писать программу невозможно.
В настоящее время я пользуюсь Apple MacBook Air с операционной системой Mac OS X 10.6. Недолгий поиск в Google позволяет выяснить, что операционная система поставляется с уже установленной программой Ruby версии 1.8.7. И это тоже хорошо: я могу запускать написанные на языке Ruby программы без дополнительных усилий.
Но проблема в том, что Ruby 1.8.7 не самая последняя версия программы. Когда я пытаюсь установить Jekyll, система сообщает, что программа требует версию Ruby не ниже 1.9.1, и это значит, что мне нужно выяснить, как обновить программу. Придется вновь прибегнуть к помощи Google.
Поиск выявил две программы, предназначенные для облегчения установки Ruby: rbenv и ruby-build. Обе программы поддерживаются Сэмом Стефенсоном, разработчиком Ruby из компании 37signals. Вместе они помогают устанавливать новые версии Ruby и указывать компьютеру, какую версию использовать.
Инструкция на странице документации [14]Крис Гильбо. Искусство нонконформизма. — М.: Попурри, 2012.
rbenv показывает, как установить программы на компьютер. Вот что представляют собой команды установки:
$ cd ~
$ git clone git://github.com/sstephenson/ruby-build.git
$ cd ruby-build
$ sudo./install.sh
$ cd..
$ git clone git://github.com/sstephenson/rbenv.git.rbenv
$ mkdir — p ~/.rbenv/plugins
$ cd ~/.rbenv/plugins
$ git clone git://github.com/sstephenson/ruby-build.git
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashprofile
$ echo 'eval "$ (rbenv init — )"' >> ~/.bashprofile
$ exec $SHELL
$ rbenv install 1.9.3-p125
$ rbenv rehash
$ rbenv global 1.9.3-p125
Выглядит устрашающе, но это всего лишь список команд. Давайте проанализируем его.
Эти команды водятся в программе Terminal, которая предустановлена на компьютерах Apple. В кинофильмах часто показывают хакеров, которые лихорадочно набирают длинные строчки команд, отображающиеся на экране. Так вот — их компьютеры работают в программе Terminal [15].
Я открываю программу и ввожу первую команду:
$ cd ~
Эту команду понять нетрудно. Символ $ программа Terminal выводит на экран, когда готова к приему новой команды. cd — это сокращение от «сменить каталог» (change directory). Не составляет труда выяснить, что символ ~ обозначает «корневой каталог пользователя», то есть папку на моем компьютере, где хранится мой профиль пользователя.
Я набираю команду и нажимаю клавишу «Ввод». Теперь программа Terminal выводит на экран следующую строчку:
joshkaufman $
Это хорошая новость: я перешел в корневой каталог. Пока все в порядке. Я набираю следующую команду:
$ git clone git://github.com/sstephenson/ruby-build.git
Компьютер отвечает:
git: command not found
Похоже, программа git не установлена на моем компьютере. Я должен выяснить, как это сделать.
Что такое git?
Занявшись поиском инструкций о том, как установить git в операционную систему Mac OS X, я наткнулся на Heroku Toolbelt [16]. Heroku [17] — это компания, предоставляющая хостинг для интернет-приложений, следовательно, они заинтересованы в том, чтобы облегчить создание этих самых интернет-приложений.
Heroku Toolbelt представляет собой программу, которая устанавливает несколько распространенных инструментов разработки программного обеспечения, необходимых для создания приложений на Heroku. Среди них есть и git [18].
Я скачал загрузочный пакет, запустил его и получил подтверждение, что все установлено правильно. Теперь попробую еще раз ввести команду:
$ git clone git://github.com/sstephenson/ruby-build.git
Ответом мне стали следующие строки:
Cloning into ruby-build…
remote: Counting objects: 1004, done.
remote: Compressing objects: 100 % (453/453), done.
remote: Total 1004 (delta 490), reused 937 (delta 431)
Receiving objects: 100 % (1004/1004), 108.77 KiB, done.
Resolving deltas: 100 % (490/490), done.
Успех! «Done» (готово) — это хороший признак. Кроме того, сообщения об ошибке не было. Идем дальше.
Я продолжаю вводить остальные команды. Судя по информации в инструкции по загрузке, я загружаю необходимые файлы и при помощи команды echo добавляю фрагменты текста в файлы конфигурации, а затем перезапускаю программу под названием SHELL, чтобы сохранить изменения. После перезагрузки SHELL программы rbenv и rubybuild установлены на моем компьютере. Ура!
Теперь пора установить последнюю версию Ruby:
$ rbenv install 1.9.3-p125
Программа автоматически загружает исходный код Ruby и делает сборку, выводя впечатляющее количество информации в окне программы Terminal. (Теперь я чувствую себя как настоящий голливудский программист.) [19]
$ rbenv rehash
Судя по документации, эта команда помогает компьютеру распознать, что установлена новая версия Ruby.
$ rbenv global 1.9.3-p125
Эта команда устанавливает, что версия 1.9.3-p125 является версией Ruby по умолчанию на данном компьютере. В руководстве сказано, что запуском следующей команды я указываю компьютеру необходимость использовать новую версию:
$ ruby — v
Вот что я получаю в ответ:
ruby 1.9.3p125 (2012–02–16 revision 34643) [x8664-darwin11.3.0]
Ура! Именно такое сообщение и должен вывести на экран компьютер.
В руководстве сказано, что если я захочу установить новую версию Ruby на этот компьютер, то должен снова запустить выполнение команд rbenv install, rbenv rehash и rbenv global. Достаточно просто.
Несмотря на то что поначалу эти команды вызвали у меня испуг, на самом деле они элементарны. То, что кажется невнятицей, — всего лишь сокращения. После расшифровки этих сокращений понять команду легко.
Полезно помнить, что никто не знает этих тонкостей с рождения. В большинстве случаев нужно потратить несколько минут на чтение документации, а затем попробовать ввести то, что там написано [20].
Установка библиотек Ruby (Gems)
Теперь, когда на компьютере есть последняя версия Ruby, настало время выяснить, как установить нужные мне библиотеки, в том числе Sinatra.
Библиотеки языка Ruby называются gems, и, как оказалось, установить их очень легко. Вот команда, которая устанавливает библиотеку Sinatra:
$ gem install sinatra
Для обновления Sinatra до последней версии нужно ввести следующую команду:
$ gem update sinatra
Что может быть проще?
Однако, прежде чем устанавливать остальные библиотеки, я хочу убедиться, что программа gem у меня тоже обновлена. Поскольку мой компьютер поставлялся со старой версией Ruby, то вполне вероятно, что все связанное с этим языком программное обеспечение тоже нуждается в обновлении.
Потратив немного времени, я нахожу команду для обновления gem для Ruby.
$ gem update — system
Довольно просто.
Запуская команду gem install, я замечаю, что она устанавливает и другие библиотеки, такие как rack, rack-protection и tilt. Эти дополнительные библиотеки называются средствами поддержки зависимостей. Они нужны для работы Sinatra и поэтому автоматически загружаются по команде gem install.
Книги
Теперь, будучи готовым приступить к программированию приложений на языке Ruby, я решил обратиться к двум справочникам по Ruby, которые чаще всего рекомендуют на Stack Overflow: «Программирование на языке Ruby» («The Well-Grounded Rubyist») (2009) Дэвида А. Блэка и «Красноречивый Ruby» («Eloquent Ruby») (2011) Расса Олсена. Обе книги представляют собой вводные пособия, предназначенные для того, чтобы познакомить читателя с основными концепциями и приемами Ruby, а также справочники.
Я также купил книгу «Sinatra: к работе готов» («Sinatra: Up and Running») (2011) Алана Харриса и Константина Хассе. Эта книга представляет собой вводный курс в среду программирования Sinatra. Подробная документация на Sinatra имеется в Сети, но книга содержит множество примеров, которые поясняют, как использовать Sinatra для решения стандартных задач.
Просматривая эти книги, я нашел несколько ссылок на сайты, которые могут служить справочниками по синтаксису Ruby.
● The Official Beginner’s Guide to Ruby [21].
● The Ruby Refresher [22].
● Ruby Security Reviewer’s Guide [23].
Для начала этого справочного материала вполне достаточно, и я выделил полтора часа для быстрого просмотра всего, что у меня есть.
Я брал каждую книгу, изучал содержание и указатель, отмечая термины и понятия, которые казались мне важными. Я также выделял концепции, упоминаемые многократно, и обращал внимание на порядок их появления. Я читал заголовки и врезки. Закончив с книгами, я проделал то же самое с сайтами.
Вот что мне удалось выяснить. Помимо переменных, условных операторов, исключений и других основных понятий программирования, язык Ruby строится на двух основных концепциях: объектах и методах.
Объекты — это существительные мира программирования; с ними мы можем что-то делать. Допустим, я хочу создать в Ruby новую переменную под названием firstname (имя) и хочу, чтобы она содержала мое имя. В Ruby эта команда имеет вид:
firstname = "Josh"
Довольно просто. Помещая имя Josh в кавычки, я указываю Ruby, что имя — это строка, то есть последовательность букв и цифр. Это делает firstname объектом класса «строка». (Класс — это особый тип объектов с определенными характеристиками.)
Строки не единственный класс объектов. Вот пример класса целых чисел:
million = 1000000
Если объекты — это существительные языка программирования, то методы являются аналогом глаголов: то, что мы можем делать с объектами.
Предположим, у меня есть два строковых объекта, содержащих мои имя и фамилию:
firstname = "Josh"
lastname = "Kaufman"
Я могу использовать символ сложения (+), чтобы объединить эти строки, то есть соединить вместе:
fullname = firstname + lastname
Контрольный вопрос: что содержит переменная fullname? Если вы скажете «Josh Kaufman», то ошибетесь.
Не забывайте, что компьютер делает только то, что вы ему говорите. Вы не указывали, что нужно добавить пробел между «Josh» и «Kaufman». Поэтому переменная fullname будет содержать «JoshKaufman».
Поэтому если мы хотим исправить эту маленькую ошибку, то нужно изменить команду, добавив в нее пробел:
fullname = firstname + " " + lastname
«+» — это метод, и его действие зависит от того, к каким объектам он применяется. Если мы применим его к целым числам, а не строкам, то получим операцию сложения, а не объединения.
sum = million + million
Чему будет равна сумма? «2000000».
Встроенные методы Ruby помогут вам сразу же осуществить много интересных операций. Допустим, я хочу написать свои имя и фамилию задом наперед. Вместо того чтобы записывать это сочетание букв вручную или сочинять маленькую программу для расстановки букв в обратном порядке, я могу использовать метод reverse, доступный для каждого строчного объекта:
fullname.reverse
Вот что получится в результате: namfuaKhsoJ
Можно использовать одновременно несколько методов. Если я хочу расположить буквы имени и фамилии в обратном порядке и сделать все буквы строчными, то могу написать команду:
fullname.reverse.downcase
Результат: namfuakhsoj. В точку!
Похоже, научиться программированию на Ruby — это научиться использовать встроенные и создавать новые объекты, классы и методы, а также манипулировать ими. Помимо встроенных, вы можете при необходимости сами создавать, изменять и удалять объекты, классы и методы, что делает язык мощным и гибким средством программирования [24].
Документация на Ruby [25] содержит стандартный список объектов и методов, доступных для пользователя. Этот список впечатляет, но пугаться вы не должны — применять их все совсем не обязательно. Наоборот, большинство из них на первых порах безопаснее не трогать. Это опции, которые вы можете использовать при необходимости.
Документация служит еще одной цели: когда вы пытаетесь дать команду, которую Ruby не понимает, сообщение об ошибке подскажет вам, в каком месте произошел сбой.
Допустим, мы хотим выполнить следующую программу:
animal = "Zebra"
number = 7
puts animal + number
Команда puts означает «печать». Мы просто хотим, чтобы программа вывела на экран то, что она понимает под animal + number.
Вот что я получил в ответ, когда пытался запустить эту программу:
TypeError: can’t convert Fixnum into String from program.
r b:3: in '+'
В переводе на понятный человеку язык: нельзя складывать числа со словами, и поэтому компьютер указывает на ошибку. Похоже на деление на ноль: это невозможно, и программа прекращает работу.
Для исправления ошибки в программе нужно либо преобразовать цифру в строку, и тогда метод «+» объединит две переменных, либо изменить программу, чтобы она делала что-то другое.
Вот исправленная программа:
animal = "Zebra"
number = 7.to_s
puts animal + number
Запуская эту программу, мы получаем результат «Zebra7». Встроенный метод .to_s преобразует цифру 7 в строку, чтобы Ruby мог использовать объединение переменных.
Можно также сделать нечто совсем другое, например:
animal = "Zebra"
number = 7
number.times {puts "# {animal}"}
Результат на экране компьютера:
Zebra
Zebra
Zebra
Zebra
Zebra
Zebra
Zebra
Тут мы просто использовали условный цикл, встроенный в Ruby: number.times означает «выполнять это Х раз, где Х равняется значению числовой переменной». Изменив значение animal или number, мы изменим результат. (Да, вы можете модифицировать эту программу так, что она выведет на экран слово «вомбат» миллиард раз.)
Комментарии и отладка
Знакомясь с литературой, я обратил внимание на еще одно фундаментальное свойство языка Ruby — комментарии. Каждую строку программы, начинающуюся с символа #, Ruby интерпретирует как строку комментария и пропускает при выполнении.
Комментарии к программе делают ее понятной, потому что в них вы простым языком объясняете свои действия. Вот как будет выглядеть программа «Животные» с комментариями:
# Назначение переменных
animal = "Wombat"
number = 1000000000
# Цикл вывода
number.times {puts "# {animal}"}
Комментарии также очень полезны для устранения ошибок: вы можете обозначить как комментарии несколько строк программы, чтобы устранить проблемы или ошибки. В сочетании с командами print или puts это позволяет следить за выполнением программы и убедиться, что она работает так, как и планировалось.
Потратив восемь часов на исследования и установку программ, я получил следующий результат: у меня на компьютере последняя версия Ruby, я имею возможность загрузить любую нужную мне библиотеку, и я понимаю, как работают программы, написанные на Ruby.
Теперь давайте разберем более сложные программы.
Тестируем с помощью IRB
Изучая Stack Overflow, я обнаружил онлайновое пособие по Ruby под названием «Сложный способ выучить Ruby» («Learn Ruby the Hard Way») [26], написанное Робом Соберсом и Зедом Шоу. Это пособие иллюстрирует работу Ruby на примерах простых программ, предлагая вам изменить их для получения тех или иных результатов. Если нужный результат не получается, вы должны продолжить эксперимент, пока не решите задачу.
Этот метод — кодируем, тестируем, запускаем, отлаживаем — представляет собой превосходный пример быстрой обратной связи. Когда вы запустите программу, компьютер уже через несколько миллисекунд даст знать, работает она или нет. Если в коде есть ошибка, вы можете исправить ее и запустить программу снова, в течение минуты проверив несколько вариантов.
Первые главы пособия посвящены настройке Ruby, установке текстового редактора и обучению работы с IRB — программой, которая запускает на вашем компьютере программы, написанные на Ruby.
Вот как это делается. Вы набираете программу в текстовом редакторе и сохраняете ее в файле. (Пусть имя файла будет program.rb.) Чтобы запустить ее, нужно набрать команду в окне программы Terminal:
$ irb program.rb
IRB запустит вашу программу и выдаст результат, а также покажет действия, предпринятые компьютером для получения этого результата, что очень удобно для отладки. Если программа некорректна, IRB выведет на экран подробное сообщение об ошибке.
«Сложный способ выучить Ruby» начинается с назначения переменных, выполнения основных арифметических действий, манипулирования строками и составления стандартных условных циклов — аналогично примерам, которые приводились выше.
Первоначально я собирался прочесть «Красноречивый Ruby» и «Программирование на Ruby», выполнить упражнения из «Сложного способа выучить Ruby», а затем попытаться написать первую «настоящую» программу. Однако к десятому уроку я заметил кое-что важное: мне становится скучно, и я теряю интерес.
Причина проста: я копирую чужие программы и решаю задачи, поставленные другими людьми. Иногда эти программы довольно интересны, однако они не решают моих проблем. Программирование из полезного навыка начинает превращаться в научную дисциплину. Мне нужно заканчивать с исследованием и приступать к практике.
Мне не нужно читать все эти книги, инструкции, пособия и другие источники информации, чтобы приступить к программированию. Я должен писать реальные программы, а если возникнут трудности, обращаться к источникам информации.
Пора замарать руки…
Приложение № 1: статический сайт в среде Sinatra
Я уже придумал свою первую интернет-программу: приложение в среде Sinatra, которое служит основным HTML-сайтом. Вот мой целевой уровень мастерства для этого приложения.
1. Создать рабочее приложение в среде Sinatra, способное предоставить простой сайт пользователю (читателю).
2. Проверить приложение на своем компьютере и убедиться в его работоспособности.
3. Разместить это приложение на сервисе Heroku, сделав «живым», чтобы им могли пользоваться реальные читатели.
Вот и все. Никаких изысков. Простое приложение в среде Sinatra, запущенное на сервере общего пользования.
С чего я должен начинать? Обратимся к списку десяти основных принципов приобретения навыка.
1. Выберите привлекательный проект.
2. Сосредоточьтесь на каком-то одном навыке.
3. Определите целевой уровень мастерства.
4. Разбейте навык на элементы.
5. Приготовьте все необходимое для занятий.
6. Устраните препятствия для занятий.
7. Выделите специальное время для занятий.
8. Создайте быстрые петли обратной связи.
9. Занимайтесь по расписанию, короткими интенсивными интервалами.
10. Уделяйте внимание количеству и скорости.
У меня есть один четко описанный проект. Я разбил навык на составляющие и знаю, как будет выглядеть моя программа, когда я закончу работу. Теперь перейдем к необходимым инструментам: нужно ли мне что-то еще для успешного осуществления проекта?
Как выяснилось, нужно. У меня нет учетной записи на Heroku. Но это легко исправить: я захожу на сайт Heroku.com, щелкаю на кнопке Sign Up, ввожу адрес своей электронной почты и придумываю пароль.
Поскольку я уже установил на компьютере Heroku Toolbelt (программу, использовавшуюся для установки git), то библиотека Heroku загружена в мой компьютер, и с этим проблем не будет.
Судя по инструкции, мне нужно сделать еще одну вещь, чтобы связать мой компьютер с Heroku: сгенерировать «SSH key», специальный файл, который, по всей видимости, служит паролем. Получив этот ключ, я должен сообщить его Heroku, чтобы система могла распознать мой компьютер и открыть ему доступ.
К счастью, в Heroku есть указания на то, как это сделать [27]. Я ввожу команду для генерации ключа:
$ ssh-keygen — t rsa
…команду для входа в Heroku:
$ heroku login
…и команду, которая добавляет ключ к моей учетной записи в Heroku:
$ heroku keys: add
Отлично: я в системе. Как мне теперь приступить к написанию программы?
Создание простого приложения
Пришло время просмотреть документацию по сервису Heroku. Отлично: там есть два руководства, которые представляются мне полезными:
● «Ruby на Heroku для начинающих» («Getting Started with Ruby on Heroku») [28];
● «Развертывание приложений на основе Rack» («Deploying Rack-Based Apps») [29].
Судя по тому, что написано в этой документации, я должен сделать следующее.
1. Создать файлы с программами на своем компьютере.
2. Добавить их в «репозиторий git». (Понятия не имею, что это…)
3. Использовать команду git push heroku master, чтобы отправить готовое приложение на Heroku.
К счастью, в руководстве есть пример, и это приложение, написанное в среде Sinatra! Похоже, все проще, чем я думал…
Я создаю на своем компьютере новую папку. Эта папка называется «корневой», и в ней будут храниться все файлы программы.
Далее я открываю текстовый редактор (я пользуюсь редактором TextMate [30]) и, следуя инструкции, создаю три файла:
application.rb
config.ru
Gemfile
Ядро программы будет находиться в application.rb. Приложения, написанные на языке Ruby, всегда оканчиваются расширением. rb.
В файле config.ru будут храниться параметры конфигурации Rack. Не забывайте, что Sinatra построена над интерфейсом Rack, и поэтому вполне логично, что у него есть отдельный файл конфигурации. Эти файлы оканчиваются расширением. ru.
Gemfile — это место, где указываются библиотеки, используемые программой. Ваша программа может иметь только один такой файл, и поэтому он всегда называется одинаково — «Gemfile». Все довольно просто.
Документация по Heroku рекомендует после создания этих файлов написать простейшую программу «Hello, World!», чтобы проверить настройки. Вот что должно быть в файле application.rb:
require 'sinatra'
get '/' do
"Hello, World!"
end
А так выглядит файл config.ru:
require './application.rb'
run Sinatra:: Application
И наконец, Gemfile:
source 'http://rubygems.org'
gem 'sinatra'
Программа совсем короткая, и понять ее нетрудно.
● Gemfile указывает серверу включить библиотеку Sinatra, которая требуется для работы приложения. Библиотека будет загружена с сайта RubyGems.org.
● Файл config.ru указывает основное приложение, затем выполняет программу.
● После запуска программа будет отображать на экране «Hello, World!», когда кто-либо нажмет «/», что указывает на возврат на главную страницу сайта.
Неужели все так просто?
В руководстве говорится, что я должен сделать еще одну вещь: сохранить файлы в репозитории git (иногда его называют просто «репо»). Я не могу сказать, что означает этот термин, но знаю, что git уже установлен, а необходимые команды есть в руководстве:
$ git init.
$ git add — A
$ git commit — m "Initial Commit"
Первая команда создает новый репозиторий git в папке корневого каталога. Команда add — A добавляет все файлы в папку репозитория. Команда commit — m фиксирует файлы в репозитории вместе с сообщением программиста, что именно фиксируется. (Я пока не очень понимаю разницу между «добавлять» и «фиксировать» и беру этот вопрос на заметку, решив разобраться с ним позже.)
После ввода этих команд компьютер отвечает:
[master (root-commit) 8ed1099] Initial commit
3 files changed, 9 insertions (+), 0 deletions (-)
create mode 100644 Gemfile
create mode 100644 application.rb
create mode 100644 config.ru
Похоже, все получилось! Осталось одно действие: создать новый пустой сервер на Heroku, а затем «поместить» мою программу на этот сервер:
$ heroku create
Я получаю ответ:
Creating shielded-springs-2049… done, stack is stack
is bamboo-ree-1.8.7
http://shielded-springs-2049.heroku.com/ | git@heroku.
com: shielded-springs-2049.git
Git remote heroku added
Получилось! «Stack» указывает программное обеспечение, выполняемое на сервере, и в сообщении прописывается общедоступный URL сервера.
И последняя команда:
$ git push heroku master
Если все пройдет хорошо, то я официально помещу свое первое приложение для выполнения на Heroku.
Вот что я получаю в ответ:
Heroku receiving push
Ruby/Sinatra app detected
Gemfile detected, running Bundler version 1.0.7
Unresolved dependencies detected; Installing…
Using — without development: test
! Gemfile.lock will soon be required
! Check Gemfile.lock into git with `git add Gemfile.lock`
! See http://devcenter.heroku.com/articles/bundler
Fetching source index for http://rubygems.org/
Installing rack (1.4.1)
Installing rack-protection (1.2.0)
Installing tilt (1.3.3)
Installing sinatra (1.3.3)
Using bundler (1.0.7)
Your bundle is complete! It was installed into./.bundle/gems/
Compiled slug size: 500K
Launching… done, v4
http://shielded-springs-2049.heroku.com deployed to Heroku
И теперь. момент истины… Я открываю веб-браузер, перехожу на http://shielded-springs-2049.heroku.com и вижу вот что:
«Hello, World!»
ПОБЕДА!
Внимание! Внимание!
Программа заработала, но я также получил предупреждение. Что такое Gemfile.lock?
В документации Heroku’s Ruby указано, что для установки библиотек на Heroku система использует библиотеку под названием bundler [31]. Это библиотека, и поэтому я могу установить ее при помощи следующей команды:
$ gem install bundler
Библиотека bundler необходима потому, что Heroku по умолчанию не устанавливает библиотеки из вашего приложения. Из соображений безопасности Heroku не присваивает мне такой уровень доступа к серверу, какой есть у меня на моем компьютере, и я не могу выполнить команду gem install sinatra прямо в моей учетной записи.
Вместо того чтобы предоставить мне (и другим пользователям) небезопасный уровень доступа к системе, Heroku использует bundler для установки библиотек, указанных в Gemfile. Отметив, какие библиотеки вы хотите установить в своем приложении, вы набираете команду:
$ bundle install
Эта команда создает в вашей программе новый файл под названием Gemfile.lock. Когда вы загружаете свои файлы в Heroku, система просматривает Gemfile и Gemfile.lock, проверяет их идентичность, после чего загружает библиотеки, а затем устанавливает их для вас.
Если вы посмотрите на ответ системы, когда я размещал программу на Heroku, то увидите, что система устанавливала bundler автоматически, как средство поддержки зависимостей. Вместо того чтобы предусмотреть сообщение об ошибке, инженеры Heroku добавили в программу исключение — вместо аварийного завершения автоматически загрузить отсутствующую программу и отправить предупреждение.
На этот раз система сработала, но в будущем я должен добавить файл Gemfile.lock в репозиторий git, прежде чем размещать приложение. Полезная информация!
На сцену выходит Sinatra
Теперь, когда мое простейшее приложение создано и запущено, я могу наконец начать разбираться, как работает Sinatra. Документация среды программирования Sinatra [32] очень подробна и включает множество примеров, и поэтому я решил начать именно с нее.
Основа приложений Sinatra называется маршрут. Лучше всего объяснить это понятие на примере.
Наше простое приложение Sinatra имеет один маршрут, который содержит «корень» сайта. Пользователи интернета обычно указывают корень сайта как начальную страницу сайта.
Если вы заходите на google.com или на yahoo.com, то браузер посылает запрос на сервер Google или Yahoo. Этот запрос называется GET-запросом, и он просит сервер показать вам, что находится в корневом каталоге сайта. Протокол, или формат, который использует компьютер для отправки запроса, называется HTTP, что расшифровывается как «протокол передачи гипертекста». Именно с этой аббревиатуры начинаются адреса в интернете — «http://».
GET — это самый распространенный из запросов HTTP, но не единственный. Существуют три дополнительных «глагола» HTTP:
● POST — отправить ресурс на сервер;
● PUT — обновить ресурс на сервере;
● DELETE — удалить ресурс с сервера.
Если вы оставляете на сайте комментарии, то ваше остроумное замечание отправляется на сервер командой POST. Если вы сделали ошибку и редактируете комментарий, то обновление выполняется с помощью команды PUT. А если вы решили, что комментарий неудачный и его нужно удалить, браузер посылает команду DELETE.
Маршруты GET, POST, PUT и DELETE — это основа работы приложений Sinatra. Каждый создаваемый вами маршрут является условным: «Делать Х, если команда GET/POST/PUT/DELETE получена на маршруте Y».
Маршруты Sinatra также содержат переменные, которые называются параметрами. Приложения Sinatra обычно используют параметры в качестве входных данных для процесса, содержащегося в каждом маршруте.
Давайте модифицируем наше простое приложение Sinatra «Hello, World!», чтобы оно приветствовало пользователя по имени. Вот маршрут, который это делает:
get '/hello/: name' do
"Hello, # {params [: name]}!"
end
Вы можете увидеть результат на http://first20hours.com/hello/name. Попробуйте заменить «name» своим именем. Работает!
Это приложение позволяет серверу посмотреть, что содержится в параметре маршрута «name», и использовать это значение. Команда маршрута представляет собой простую инструкцию — показать параметр «name» пользователю.
Sinatra позволяет вам дать название параметру (например, name), но также имеет «универсальный» параметр (его также называют «решеткой» (splat)), который может содержать все что угодно. Вот как можно использовать его в нашем модифицированном приложении «Hello»:
get '/hello/*' do
"Hello, # {params [: splat]}!"
end
Это очень удобно. С помощью обычных и универсальных параметров можно прописывать самые замысловатые маршруты. Создаваемые вами маршруты определяют работу приложения Sinatra.
Этих сведений достаточно, чтобы понять, как написать программу, которая удовлетворяет моему целевому уровню мастерства. Поскольку Jekyll создает файлы, которые приложение предоставляет по запросам пользователей GET, мне остается лишь написать несколько маршрутов, которые принимают эти запросы, находят в системе нужные файлы и предоставляют их читателю.
Как указывается в документации на Jekyll, программа помещает законченные веб-страницы в папку под названием «site» в корневом каталоге. Маршрут к этой странице автоматически генерируется Jekyll. Если мы хотим, чтобы наша страница About была доступна на http://example.com/about, мы ставим маршрут /about в файлах Jekyll, и программа создаст файл в _site/about/index.html в корневом каталоге нашего сайта.
Это означает, что я должен создать новый маршрут в Sinatra, чтобы прочесть файл в ответ на запрос пользователя GET. Вот как он будет выглядеть:
# Index handler
get '/?' do
## File.read ("_site/index.html")
end
# Post handler
get '/*/?' do
## File.read ("_site/# {params [: splat]} /index.html")
end
Команда File.read (“”) встроена в Ruby. File — это объект, read — метод. Используется она очень просто: содержимое (“”) указывает на расположение файла, который должна прочитать программа, относительно корневого каталога приложения. Легко.
А что если такого файла нет? В этом случае необходимо исключение, и в Sinatra встроены два основных маршрута ошибок: not_found и error. Давайте сделаем так, чтобы оба маршрута вызывали одну и ту же страницу с сообщением об ошибке:
not_found do
## File.read ("_site/error/index.html")
end
error do
File.read ("_site/error/index.html")
end
Все остальное остается таким же. Я не собираюсь вносить изменения в config.ru или Gemfile. Я просто добавляю новые маршруты в программный репозиторий Git, внося изменения, а затем размещаю исправленные программы на Heroku. Готово.
Хотите посмотреть, как работает модифицированная программа? Зайдите на сайт PersonalMBA.com: в настоящее время сайт работает на Jekyll вместо WordPress, используя именно эту программу. При помощи программы нагрузочного тестирования, которая называется seige, мой сайт теперь способен без труда обслуживать две тысячи посетителей одновременно. Большинство запросов страниц обрабатываются за 18–20 миллисекунд, так что мой сайт полностью защищен от падения при большом трафике.
Мое первое рабочее интернет-приложение завершено. Мне потребовалось около часа, чтобы разобраться, что я должен делать, и еще час, чтобы понять, как перенести информацию и дизайн моего сайта с WordPress на Jekyll.
Общее время составило около десяти часов, включая исследования и обзор концепций программирования. Не так плохо!
Приложение № 2: Codex, персональная база данных
Мое первое приложение работает, и работает хорошо. Оно простое, и в данном случае это его главное преимущество. Чем меньше движущихся деталей, тем меньше вероятность поломки — это справедливо и для программы.
Давайте займемся чем-нибудь чуть более сложным.
Помните наш разговор о базе данных? Главные веб-страницы не могут обновляться, а значит, не могут хранить информацию. Мое первое приложение работает только потому, что файлы статичны: они не изменяются. Любые изменения в файлы вносятся посредством Jekyll, отдельной программы. Приложение получилось быстрым и стабильным потому, что не использует базу данных.
А как быть с программами, использующими базы данных? Базы данных обычно являются важной частью большинства приложений, и поэтому я должен понять, как они устроены. А для этого нужно начать работу над проектом, основанным на базе данных.
Одно из приложений, которым я пользуюсь, называется Backpack [33] и разработано компанией 37signals. Основное преимущество Backpack — возможность создавать страницы, содержащие все что угодно: текст, списки, изображения, файлы и так далее. Сохранив информацию о странице в Backpack, впоследствии вы можете получить к ней доступ с любого компьютера, поскольку вся информация хранится в базе данных приложения.
Я спрашиваю себя: могу ли я сам создать нечто подобное? Попробовать стоит… но с чего начать?
Изучая Jekyll, я прочел статью программиста Тома Престона-Вернера, создателя Jekyll, под названием «Начни разработку с Readme» («Readme Driven Development») [34]. Идея статьи заключалась в том, что вопреки волнам увлечения проектным менеджментом, которые каждые несколько лет захлестывают индустрию программного обеспечения, лучший способ создать приложение — начать с написания ознакомительного документа Readme.
Файл Readme программисты включают в корневой каталог приложения вместе с программным кодом. В нем содержится информация по установке, настройке и использованию программы.
Файлы Readme очень важны, поскольку многие программы требуют пояснений. Без этого документа зачастую бывает трудно понять, как пользоваться программой. Самостоятельный просмотр кода не так эффективен, как чтение подробного объяснения, написанного создателем программы.
Том утверждает, что сначала нужно написать файл Readme, а уж затем браться за саму программу. Большинство программистов поступают с точностью до наоборот: сначала пишут программу, а затем (возможно) ознакомительный файл. И упускают благоприятную возможность: разработка документации помогает понять, как именно будет работать программа. Файл Readme может быть не только полезным документом, но и средством разработки.
Такой подход мне нравится. Один из приемов, которые я освоил в процессе работы над «Сам себе MBA», заключался в написании рекламных материалов до, а не после создания коммерческого предложения. Выясняя, что требуется потенциальным покупателям, и включая это в рекламный материал, вы получаете более полное представление о том, каким должен быть продукт, чтобы привлечь внимание клиентов. Разработку самого предложения определяет маркетинговое исследование.
Я взял блокнот и составил список функций, которые я хотел бы иметь в своем приложении, а также характеристик программы.
● Программа представляет собой простое приложение, предназначенное для создания заметок.
● Приложение предназначено для одного пользователя.
● Приложение использует среду Sinatra и базу данных для создания, сохранения, обновления и удаления записей на странице.
● Приложение позволяет пользователю создавать страницы со сложным форматированием, таким как жирный шрифт, курсив, подчеркивание и тому подобное.
● Приложение требует пароль доступа и обеспечивает сохранность базы данных, насколько это возможно.
● У приложения привлекательный внешний вид.
● Приложение может без труда размещаться на Heroku или любом другом ресурсе.
Я собираюсь назвать это приложение «Codex» — в старину так называли книги, — поскольку приложение будет применяться в основном для хранения справочной информации, списков и тому подобное.
В интернет-программировании подобные приложения называются «CRUD» — аббревиатура от английского «создание чтение обновление удаление». Стоит отметить, что эти функции совпадают с командами GET, POST, PUT, DELETE, и поэтому написать такое приложение можно и с использованием маршрутов Sinatra. Разница, причем существенная, заключается в использовании базы данных.
Какие возможности работы с базами данных предоставляет Heroku? Не знаю. Придется вновь заглянуть в документацию.
По умолчанию Heroku использует базу данных под названием Postgres [35]. Каждому новому приложению автоматически назначается маленькая база данных разработки. Мне это подходит, но как ею пользоваться и какими средствами протестировать программу на моем компьютере?
За ответами на эти вопросы я решил обратиться к Stack Overflow. Общее мнение: решение подобных задач значительно облегчает применение базы данных под названием DataMapper [36].
DataMapper относится к классу программ, получивших название «объектно-реляционного отображения», или сокращенно ORM [37]. Метод ORM решает насущную проблему программистов: базы данных зачаcтую используют собственный язык, отличающийся от языка, на котором пишется приложение. В большинстве баз данных используется язык SQL [38], однако существуют и сотни других языков.
Предположим, что мы пишем программу для сайта Amazon.com и хотим вывести на экран список книг Дж. К. Роулинг, автора серии о Гарри Поттере. Команда на языке SQL будет выглядеть так:
SELECT * FROM Book WHERE author = "J.K. Rowling" ORDER BY
title;
Данная команда извлекает из базы данных все записи, в поле «author» которых содержится «J.K. Rowling», и располагает их в алфавитном порядке по названию книги.
К сожалению, заставить SQL или любой другой язык запросов базы данных корректно работать с такими языками, как Ruby, — сложная задача. Непросто писать программу на одном языке, не говоря уже о нескольких языках одновременно.
Здесь на помощь приходит ORM: она позволяют программисту писать программу на одном языке, который ORM затем переводит на язык базы данных. Так гораздо проще.
Таким образом, DataMapper представляет собой библиотеку, облегчающую связь с базами данных, использующих Ruby. По умолчанию DataMapper содержит большое количество удобных функций для создания, чтения, обновления и удаления записей в базе данных. Поскольку программа DataMapper существует уже довольно давно и тщательно протестирована, в большинстве случаев надежнее пользоваться ею, а не пытаться писать собственную программу для базы данных.
DataMapper доступна в виде стандартной библиотеки, которая устанавливается следующим образом:
$ gem install data_mapper
Поскольку объем библиотеки DataMapper очень велик, ее можно устанавливать по частям. Этот принцип называется «модульностью», и он может служить признаком профессионального программирования. Вот как выглядит команда загрузки всех отдельных библиотек:
$ gem install dm-core dm-aggregates dm-constraints dm-migrations dm-transactions dm-serializer dm-timestamps dm-validations dm-types
Вместо установки всей библиотеки вы можете загрузить только те модули, которые будет использовать ваша программа, что гораздо эффективнее.
Использование DataMapper
Теперь, когда библиотека DataMapper установлена, я должен научиться с ее помощью 1) связываться с базой данных и 2) создавать базу данных для хранения и извлечения нужной мне информации.
В документации на Heroku указано, что следующая команда позволит приложению Sinatra связываться с базой данных:
DataMapper.setup (: default, ENV ['DATABASE_URL'] ||
"sqlite3://# {Dir.pwd} /database.db")
В данном случае || означает «или». ENV ['DATABASE_URL'] — это переменная, которую Heroku использует для вашей базы данных. Если эта база данных недоступна, то будет применен второй вариант, база данных под названием Sqlite [39].
Sqlite установлена на компьютерах Mac по умолчанию и уже готова к работе. DataMapper может связываться и с Postgres, и со Sqlite, если я установлю обе библиотеки:
$ gem install dm-sqlite-adapter dm-postgres-adapter
Это означает, что мое приложение будет использовать Postgres при запуске на сервере Heroku и Sqlite при запуске на моем компьютере. В обоих случаях моя программа остается одной и той же, несмотря на то что базы данных используют разные языки. Это действительно здорово.
Кстати, по поводу запуска такого приложения на моем компьютере… Как это сделать?
Pow!
Информацию о том, как запустить приложения такого типа на моем компьютере, я искал на Stack Overflow и Hacker News. К счастью, существует несколько вариантов. Похоже, я могу установить библиотеки (например, Foreman или Shotgun), которые выполняют приложение, когда я ввожу команду в Terminal, или программу, поддерживающую приложение все время.
Программа, использующая этот подход, называется Pow [40] — «Rack-сервер нулевой конфигурации для Mac OS X». Сайт обещает установить локальный хостинг для разработки приложений на моем компьютере меньше чем за минуту. Звучит привлекательно!
Установка Pow занимает меньше десяти секунд: для загрузки и установки приложения требуется всего одна команда в Terminal. После этого вы вводите команду, которая связывает вашу программу с Pow, и Pow позволит запускать ее на вашем компьютере.
Библиотека Ruby с названием Powder [41] еще больше облегчает этот процесс:
$ gem install powder
После установки библиотеки вы устанавливаете Pow:
$ powder install
Затем переходите в корневой каталог своего приложения и вводите следующую команду:
$ powder link
Вот и все. Мой корневой каталог называется «codex», поэтому теперь приложение выполняется на моем компьютере на http://codex.dev, и у меня появляется возможность протестировать свою работу.
Если я вношу изменения, следующая команда заново запускает программу:
$ powder restart
Все просто. Теперь я готов писать программу. Каждый вечер я буду выделять полтора часа на составление программы — пока работа не будет закончена.
Кодируем, тестируем, исправляем
Теперь я буду описывать, что я делаю, а не как. Полный текст программы вы, если захотите, сможете найти на https://github.com/first20hours/codex.
Вот как должно выглядеть приложение, когда работа будет завершена.
Вы, наверное, заметили, что дизайн страницы состоит из трех частей: верхней навигационной панели, области основного содержания и бокового поля. Я сконструировал эту структуру с помощью инструмента Bootstrap [42], созданного разработчиками Twitter Марком Отто и Джейкобом Торнтоном.
Веб-страницу не нужно разрабатывать с нуля, поскольку Bootstrap представляет собой библиотеку шаблонов HTML и CSS, находящихся в открытом доступе. Использование Bootstrap сэкономит вам уйму времени: вы сможете собрать прототип своего приложения за несколько минут вместо нескольких дней.
Основная единица этого приложения называется «Page», и она отображает запись, хранящуюся в базе данных. Специальная кнопка позволяет просматривать все записи базы данных. Внизу расположены еще две кнопки. Первая дает возможность редактировать текущую страницу, вторая — удалить.
В боковом поле реализованы три основные функции. Вверху расположена форма, позволяющая создать новую страницу, для чего нужно ввести ее название. Здесь также есть список страниц, добавленных пользователем, и этот список может служить указателем. И, наконец, справка по форматированию, помогающая пользователю вспомнить, как применять стандартные функции форматирования.
Верхняя навигационная панель очень проста. Она содержит ссылку на главную страницу, а также дополнительную ссылку на экран «Показать все страницы». Позже я могу добавить еще функции, если потребуется, но пока этого достаточно.
Каждое интернет-приложение имеет главную страницу, и я должен решить, что хочу видеть на своей главной странице. В данном случае мне просто нужно отобразить запись Home базы данных.
Что же содержится в Page? Поскольку каждая Page представляет собой запись базы данных с полями, в которых хранится информация, я должен указать DataMapper, какие поля требуется создать. Вот как это выглядит:
class Page
include DataMapper:: Resource
property: id, Serial
property: title, String
property: content, Text
property: lastupdated, DateTime
end
DataMapper.finalize
Данный фрагмент программы использует DataMapper для создания нового объекта под названием Page. Теперь Ruby может использовать Page подобно любому другому объекту, а я могу создавать и применять методы, которые формируют, изменяют и удаляют объекты Page. Изменения, внесенные в Page, сохраняются в базе данных при помощи DataMapper.
Команда DataMapper.finalize указывает приложению, чтобы оно создало эти поля, если они еще не существуют в действующей базе данных.
Теперь, когда база данных есть, пора выяснить, какие маршруты должна будет обслуживать среда разработки Sinatra. Вот какой у меня получился список:
# Show home page
g e t '/'
# Creates new note from "new page" form
p o s t '/'
# Displays requested note
get '/: url/'
# Edits requested note
get '/: url/edit'
# Saves user edits to note
p o s t '/: u r l /e d it'
# Deletes specified note
delete '/: url/'
# List all pages in database
get '/all/'
# Error handling
not_found
error
Это очень полезный список. Мое приложение будет строиться вокруг команд, которые я создам для каждого маршрута.
Слаги, везде слаги!
Помните, я сравнивал базу данных с магической стопкой учетных карточек, которую вы можете просматривать так, как вам удобно? Нам нужен способ поиска конкретных записей, и именно потому в этих маршрутах встречается url. Содержание параметра url указывает базе данных, какую запись следует извлекать.
В качестве параметра можно использовать заголовок страницы, но тут есть одна проблема: браузеры не любят в интернет-адресах такие вещи, как пробелы, заглавные буквы и специальные символы (например, $ и %). В заголовках такие символы встречаются достаточно часто, поэтому от них нужно избавиться.
Строка, однозначно определяющая страницу сайта, называется слагом [43]. Слаг моей страницы будет основан на заголовке и подчиняться правилам, приемлемым для интернет-адресов.
1. Все символы строчные.
2. Никаких специальных символов — только буквы и цифры.
3. Никаких пробелов — все пробелы должны быть заменены на подчеркивание.
Для этого нужно создать метод, который берет заголовок страницы и форматирует его в слаг. Сложные замены выполняются при помощи метода программирования, получившего название регулярных выражений, который преобразует или находит текст в строках в соответствии с установленными правилами [44].
Регулярные выражения могут быть очень сложными, но применяются они широко, и я смог найти подходящий шаблон. Вот как выглядит мой метод:
# Converts page name into post slug
def slugify (content)
content.downcase.gsub (/ /, '-'). gsub (/ [^a-z0–9-] /, "). squeeze ('-')
end
Теперь я могу использовать метод slugify для преобразования строк типа «Заголовок Страницы» в «заголовок_страницы», которые можно использовать в составе интернет-адреса.
Кроме того, если мы храним слаг вместе с заголовком страницы, то можем использовать его для извлечения записи страницы при помощи параметра url.
Я добавил это поле к классу DataMapper:
property: slug, String
Теперь при создании страницы мы можем превратить ее заголовок в слаг, сохранить его в базе данных и использовать для демонстрации страницы, когда потребуется ее извлечь. Именно так приложение узнаёт, какую страницу показывать.
Создание страниц
Я начал разрабатывать список необходимых маршрутов. «Главный» маршрут прост: я перенаправляю его к слагу /home/, поскольку хочу, чтобы главная страница отображала содержимое соответствующей записи.
Маршрут «создать страницу» связан с небольшим полем ввода в верхней части бокового поля. Пользователь вводит заголовок страницы в поле ввода и щелкает по кнопке. Система считывает заголовок страницы, преобразует его в слаг, затем сохраняет в базе данных заголовок, слаг и время создания. После этого система посылает запрос GET, содержащий слаг, и отображает новую страницу.
В маршруте «создать страницу» есть маленькая, но очень важная деталь: что если страница уже существует? Я не хочу переписывать ее заново, если она содержит данные. Случайная потеря данных недопустима.
К счастью, DataMapper разрешает эту проблему при помощи встроенного метода. first_or_create. Если страница уже существует, DataMapper не переписывает ее, а Sinatra перенаправляет браузер к существующей странице. Проблема решена.
Маршрут «отобразить страницу» считывает слаг в URL, извлекает запись из базы данных, а затем отображает информацию в области основного содержания. Позже я добавлю красивое форматирование, но теперь мне просто нужно, чтобы программа работала.
Редактирование страниц
Редактирование страниц включает два отдельных маршрута. Первый маршрут запросом GET вызывает страницу, которую хочет отредактировать пользователь, а затем отображает содержимое соответствующей записи базы данных в форме, удобной для редактирования.
Для отображения страниц приложение использует шаблон ERB, который обычно состоит из команд HTML + Ruby. ERB позволяет программисту писать HTML, включающий изменяемые элементы. Поскольку ERB обрабатывает страницу до того, как она появляется перед пользователем, текст на странице можно менять при каждой загрузке, основываясь на командах Ruby шаблона.
Кнопка «Сохранить» на экране редактирования посылает запрос POST приложению, которое обновляет запись Page.
Удаление страниц
Удаление страниц требует осторожности: нельзя забывать, что случайная потеря данных неприемлема. Собираясь удалить страницу, вы должны быть абсолютно уверены, что пользователь хочет именно этого.
Неправильно было бы напрямую связать кнопку «Удалить» с маршрутом DELETE приложения. При таком подходе страница удалится даже при случайном щелчке по кнопке.
Предпочтительнее разбить процесс на два этапа. Щелчок по кнопке «Удалить» на экране отсылает пользователя к окну подтверждения, где отображается заголовок страницы, которую пользователь намерен удалить. Если все правильно, пользователь щелкает по кнопке подтверждения, посылая запрос DELETE. Если кнопка «Удалить» нажата случайно, можно щелкнуть по кнопке «Отмена» или кнопке браузера «Назад».
Список всех страниц
Кнопка «Показать список страниц» направляет пользователя к слагу /all/, который отличается от слагов обычных страниц.
Вместо того чтобы извлечь одну запись, DataMapper извлекает все записи Page базы данных. Шаблон ERB для Page содержит условный цикл, который создает список всех извлеченных страниц. Каждый элемент списка содержит заголовок страницы, отображаемый в виде ссылки на соответствующий странице слаг. Щелчок по ссылке направляет пользователя на конкретную страницу.
Первый запуск приложения
Итак, у меня есть основные функции, однако есть и проблема: во время тестирования приложения попытка перейти к главной странице вызывает сообщение об ошибке. Программа пытается найти запись Home в базе данных, но ее не существует, поскольку я запустил приложение в первый раз!
Выход — создать «однократный процесс управления» при помощи программы под названием Rake. Программы Rake хранятся в папке Rakefile, которая находится в корневом каталоге приложения.
Файлы Rake работают как обычные приложения Ruby, но с одним исключением: они существуют вне вашей основной программы, и вы должны запускать их вручную.
Это делает Rake очень удобным средством для таких действий, как добавление начальной информации в базу данных перед запуском реальной программы. Я копирую необходимые фрагменты application.rb в Rakefile, затем пишу команду, которая создает новую запись для главной страницы в базе данных. Остается лишь один раз запустить следующую команду:
$ rake setup
Rake создает запись «Главная страница», и мое приложение перестает выдавать ошибку при запуске. Когда я размещу это приложение на Heroku, то запущу команду Rake удаленно, чтобы настроить базу данных перед первой попыткой использовать приложение.
Теперь все основные функции на месте. Пора добавить что-нибудь интересное.
Добавление поддержки бокового поля
Я только что сообразил, что не включил в боковое поле функцию добавления страниц, как планировал изначально. Это логическая функция, поскольку может иметь только два значения: страницу предполагается отобразить в боковом поле или нет.
Я добавил новый класс в DataMapper:
property: sidebar, Boolean, default => false
Я также добавил кнопку-флажок к экрану «Редактировать» рядом с вопросом «Включить в боковое поле?» и связал эту кнопку с соответствующим полем в базе данных. Затем написал простой цикл, чтобы найти записи в базе данных, когда sidebar = true, и вывести их в виде списка, аналогичного странице «Список всех страниц».
Я снова запускаю приложение, редактирую запись, и приложение вылетает. Проклятье!
Я снова и снова пытаюсь найти ошибку, но безуспешно. Перерыв документацию DataMapper и обратившись к Stack Overflow, я выясняю, что логические переменные плохо сочетаются с формами HTML. Нужен другой подход:
property: sidebar, Enum [: yes, no], default =>: no
Это другой способ сделать примерно то же самое. Enum, что означает «перечислять», создает список опций, и форма устанавливает, какую опцию сохранить в базе данных.
Добавление поддержки Markdown
Теперь я хочу, чтобы мои страницы могли иметь сложное форматирование, например жирный шрифт, курсив, заголовки.
В качестве форматирующего синтаксиса я выбрал Markdown, популярный и очень полезный язык разметки, разработанный Джоном Грубером [45]. Я уже знаком с работой Markdown, поскольку его использовали некоторые приложения, которые установлены на моем компьютере. Теперь мне нужно выяснить, как заставить мою программу понимать этот язык.
Довольно быстро мне удается найти несколько общедоступных библиотек Markdown. Я выбираю библиотеку rdiscount и включаю в application.rb:
require 'rdiscount'
Rdiscount преобразует текст из формата Markdown в HTML, а браузер пользователя затем отображает должным образом отформатированный текст. Файлы Markdown представляют обычные текстовые файлы, написанные по определенным правилам.
Это значит, что мне не нужно преобразовывать информацию моей страницы в Markdown, прежде чем добавлять в базу данных. Это ведь обычный текст. Если я хочу отобразить отформатированный текст, мне нужно лишь вызвать rdiscount.
Команда, которую я добавил в шаблоны ERB, отвечающие за отображение страниц, выглядит следующим образом:
<% markdown (@page.content)%>
Метод берет содержимое поля содержания страницы, преобразует в HTML, а затем отображает конечный результат у пользователя. Все просто.
Меры безопасности
А как насчет регистрации пользователей? Если я размещу приложение на Heroku, не запрашивая имени пользователя и пароля, то все смогут увидеть, что я помещаю в базу данных.
Как выяснилось, современные браузеры поддерживают безопасный протокол под названием «Базовая аутентификация HTTP» [46], который представляет собой простой способ потребовать у пользователя имя и пароль, прежде чем продолжить работу. Если пользователь не может предоставить полномочия доступа, его переправляют на страницу с сообщением об ошибке.
Вот фрагмент программы, обеспечивающий базовую идентификацию в Sinatra:
use Rack:: Auth:: Basic, "Restricted Area" do |username, password|
[username, password] == [ENV ['ADMIN_USER'], ENV ['ADMIN_PASS']]
end
В данном случае я храню имя пользователя и пароль в Heroku как переменные среды, которые я могу задать командой Terminal. Это позволяет мне использовать один и тот же код для разных приложений, а также показать вам этот код, не сообщая своего пароля!
Это также превосходная иллюстрация того, почему важно знать, что Sinatra построена над интерфейсом Rack. Дело в том, что существует много общедоступных библиотек типа Rack::Auth::Basic, и любую из них я могу использовать с Sinatra. Чем реже мне приходится изобретать колесо, тем лучше.
Кроме того, я хочу добавить еще одну меру безопасности — шифрование. Протокол SSL — его используют банки для обеспечения безопасности онлайновых банковских операций — добавится к моему приложению с помощью библиотеки rack-ssl-enforcer:
require 'rack-ssl-enforcer'
use Rack::SslEnforcer
Библиотека заставляет браузер использовать безопасное SSL-соединение для доступа к сайту. Heroku позволяет приложениям, размещенным на его доменах, использовать SSL по умолчанию, поэтому никакие дополнительные настройки не нужны [47].
Флэш-сообщения
Есть еще одна функция которую мне хотелось бы добавить. Я видел сайты, где в ответ на ваши действия появляются маленькие сообщения, например «Ваша страница создана/отредактирована/удалена». Как это сделать?
После недолгих поисков я обнаружил библиотеку под названием sinatra-flash, которая обслуживает эту функцию [48]. Такие сообщения называются флэш-сообщениями и работают следующим образом: перед переходом на новую страницу в куки-файле браузера пользователя сохраняется небольшой текст. При загрузке следующей страницы приложение читает куки-файл и показывает сообщение пользователю.
Я добавил библиотеку к Gemfile и application.rb, в соответствующих маршрутах написал сообщения, которые хотел бы видеть, затем добавил несколько строк программы в мои шаблоны ERB, чтобы показывать эти сообщения. Дело сделано. Мое приложение завершено.
Вот как начинается ознакомительный файл Readme приложения «Кодекс»:
«Codex» — это простое интернет-приложение, справочник для одного пользователя, написанное на языке Ruby. «Кодекс» использует Sinatra и DataMapper для того, чтобы создавать, сохранять, обновлять и удалять записи страниц в простой базе данных Postgres. Приложение готово для немедленного размещения на сервисе Heroku.
Форматирование Markdown доступно для всех страниц, что облегчает создание сложных страниц с простой разметкой. Сохранность информации обеспечивают аутентификация HTTP и принудительное SSL-шифрование для всего трафика. Дизайн Bootstrap делает страницы аккуратными и привлекательными.
Далее в файле Readme приводятся подробные инструкции по установке приложения на Heroku. Метод «Начни разработку с Readme» оказался весьма успешным.
Всего на разработку приложения «Кодекс» я потратил 10 часов. Таким образом, затраты времени на обучение программированию составили 20 часов. (Эту главу я писал дольше, чем программу.)
Когда приложение было готово, я присоединился к локальному форуму программистов, работающих на Ruby, и рассказал о том, как работает программа. Меня похвалили за то, каким ясным, компактным и понятным получился код. Один из участников форума заметил, что качество кода оказалось лучше, чем у многих проектов, выполненных профессиональными программистами.
Миссия завершена.
Ярость против машины
Хотелось бы кое-что прояснить: процесс, который я описал, выглядит линейным и прямым. Причина в том, что до сих пор я рассказывал о своих успехах, а не о трудностях и ошибках.
Создание полезного, рабочего интернет-приложения немного похоже на сборку пазла, но с дополнительными трудностями: вы не знаете, какие фрагменты существуют, некоторые фрагменты необходимо создавать самому, а в случае ошибки рушится вся картинка.
На самом деле процесс программирования выглядел так. Когда я приходил к выводу, что понял, как должна работать та или иная часть программы, то писал код, тестировал его — и программа вылетала. Я пытался исправить ошибку. Это иногда получалось, иногда нет, а порой изменения приводили к новым проблемам. Если я заходил в тупик, то искал объяснение ошибки или нужную библиотеку на Stack Overflow или в Google.
В процессе обучения созданное вами приложение чаще не работает, чем работает. Кроме того, вы узнаете много полезного, например что такое контроль версий, позволяющий вернуться к предыдущей, рабочей версии программы.
Помните, я говорил, что до конца не понимаю, для чего нужен git? Оказывается, вот для чего: если вы редактируете файлы и программа вылетает, то найти причину бывает не так просто. В такой ситуации спасением становится возможность отката к предыдущей, рабочей версии. В противном случае есть опасность запаниковать.
На этапе добавления бокового поля мое приложение перестало работать. Я пытался выявить свою ошибку, но ничего не получалось. Я был готов рвать на себе волосы — если бы они у меня были.
Именно тогда я осознал ценность git branch и git merge: они позволяют создавать экспериментальные копии своей программы, а затем вносить изменения. Если копия заработала, вы можете сохранить изменения в оригинале. В случае ошибки вы просто удаляете экспериментальную ветвь, не теряя всей предыдущей работы.
Программирование — сложный процесс, и существует миллион возможностей сделать ошибку. Компьютер ничего не прощает и не выполняет неправильно сформулированные команды. Точно так же легко пропустить какие-нибудь мелочи, что приведет к непредсказуемым результатам. Я долго бился над ошибкой во фрагменте, связанном с сохранением пустых записей в базе данных, которые появлялись в списке страниц.
При каждом просмотре возникали фиктивные страницы, и я никак не мог понять, откуда они берутся. В конечном итоге выявилась ошибка в маршруте «показать все»: я использовал некорректную команду для извлечения записей из базы данных.
Каждая моя ошибка меня чему-нибудь учила. В этом заключается одно из скрытых преимуществ программирования. Компьютер — самый быстрый из всех возможных типов обратной связи. Когда вы что-то делаете неправильно, то мгновенно узнаете об этом. А когда правильно, то мгновенно видите результат. Если вам удастся побороть желание швырнуть компьютер в стену, то мгновенная обратная связь может превратить программирование в весьма увлекательное занятие.
В начале этого эксперимента я совсем не умел писать программы. Теперь умею. Потребовалось потратить определенное время, чтобы сделать коды послушными, а также проявить упорство или выполнить кое-какие исследования, если я заходил в тупик.
Что же я приобрел, потратив столько сил? Очень много. Я узнал, что такое программирование, как оно выглядит и какая от него польза. Я научился с нуля создавать интернет-приложения на языке Ruby, а затем размещать их на рабочих серверах. Я познакомился с Sinatra, Heroku, Jekyll, DataMapper, Rake и другими универсальными инструментами, с помощью которых могу разрабатывать новые приложения. Я научился находить ошибки в программе и устранять их.
Применение метода
Давайте кратко опишем суть метода, который я использовал для обучения программированию.
● Я потратил время на получение общих представлений о программировании и интернет-приложениях, затем разбил эти навыки на более простые элементы, которые проще понять и которым легче научиться.
● Я определил целевой уровень мастерства, выбрав два конкретных проекта, а затем описал, как будет выглядеть конечный результат в каждом из них.
● Я разбил эти проекты на более мелкие этапы, а затем выделил из них самые значимые.
● Я убедился, что у меня есть все необходимые для работы инструменты (например, последняя версия Ruby) и что я смогу найти любые дополнительные инструменты, которые мне потребуются.
● Я нашел несколько надежных источников информации о программировании, но не стал читать заранее приобретенные учебные пособия, а решил сразу приступить к решению реальной задачи.
● Сначала я работал над самыми важными элементами, например выяснил, как протестировать программу на своем компьютере, как разместить готовое приложение на рабочем сервере и тому подобное.
● Я использовал примеры из справочных пособий, чтобы приступить к делу и приобрести некоторую уверенность, затем пробовал разные подходы, выясняя, как запрограммировать нужные мне функции.
● Если я что-то делал неправильно, программа прекращала работу, выдавая мне сообщение об ошибке, что обеспечивало быструю обратную связь.
● Сделав ошибку, я пробовал несколько способов ее исправления. Если я не мог решить проблему самостоятельно, то обращался за помощью.
● Я продолжал придерживаться подхода «кодирование/тестирование/отладка» до тех пор, пока программы не были окончательно готовы.
Общее время составило около 20 часов. 10 часов заняли исследования, а оставшиеся 10 — создание двух приложений, которые в данный момент закончены и используются.
Планы на будущее
Завершив эти два начальных проекта, я продолжил писать интернет-приложения, сосредоточившись на программах, которые могли облегчить мне ведение бизнеса.
Теперь я с гордостью могу заявить: весь мой бизнес использует программное обеспечение, созданное мной самим. Мои приложения способны принимать оплату с кредитных карт, оформлять подписку, отправлять письма по электронной почте и управлять доступом клиентов к интернет-сайту. Научившись программировать, я стал владельцем собственной маленькой армии роботов, выполняющих мои приказы.
Сколько времени у меня ушло на создание всех этих программ? Приблизительно 90 часов, включая те 20, которые подробно описаны в этой главе.
А вот еще дополнительное преимущество: когда я сталкиваюсь с каким-то повторяющимся или скучным аспектом своего бизнеса, то начинаю думать в терминах программирования. Как будет работать программа, решающая эту проблему? В большинстве случаев это помогает систематизировать процесс, что значительно облегчает мне жизнь.
Кроме того, я научился некоторым новым трюкам, например настраивать свой компьютер, чтобы ускорить процесс программирования. Я запомнил комбинации «горячих клавиш» текстового редактора, позволяющие сэкономить время, а также обновил программу Terminal до iTerm2 и Z-Shell, чтобы немного облегчить программирование.
Я все еще учусь, и меня ни в коем случае нельзя назвать специалистом. Мне приходится доходить до всего своим умом, и требуется определенное время, чтобы найти правильный путь и устранить ошибки. Зачастую это вызывает раздражение.
Тем не менее я пишу программы, которые решают реальные задачи, просто и надежно. И только это имеет значение.
Я сражался с компьютером и победил.