Статьи

Loccasions: парное программирование

В день, как и в любой другой, я просматривал свой канал в Твиттере в поисках знаний и вдохновения. Хотя я еще не знал этого, этот день Tweet Fishing будет плодотворным и навсегда изменит направление Loccasions . (Вы должны представить себе какую-нибудь драматическую музыку здесь, в комплекте с вырезом снимка экрана Loccasions, который становится черным.)

Твит , который изменит все, был о rubypair.com . RubyPair.com — это «каталог для разработчиков с возможностью поиска, которые хотят объединиться, лично или удаленно, по темам, в которых они проявили интерес через свой профиль». Другими словами, это способ найти кого-то для сопряжения программы на ваш (или их или какой-либо с открытым исходным кодом) проект Ruby. Я прочитал этот твит, и он ударил меня как удар молнии! Мне нужно создать парную программу на Loccasions! Я имею в виду, у меня был один (спорный) программист, мне просто нужно было найти другого. Где бы я нашел такую ​​душу? Ну, я думал, что создатель RubyPair.com наверняка будет заинтересован. Я бы предложил бесплатную рекламу на RubySource.com, THE (читай: а), где можно прочитать обо всех вещах Ruby.

Глядя на страницу « О нас» , я увидел имя Эвана Лайт. Я уже некоторое время следил за Эваном в твиттере ( @elight ), и я знаю, что у него есть « рабочие часы», на которые могут зарегистрироваться программисты, ищущие соединения. Я упустил возможность и поймал часы работы Эвана 20 сентября. Теперь все, что у меня было, — это сумасшедшее ожидание ожидания того дня, как будто это было мое собственное Рождество Руби.

Да будет (Эван) свет

Эван Лайт давно занимается разработкой программного обеспечения. Вы можете сказать, читая его очень информативный блог и его биографию здесь . Эван не всегда делал Ruby, и на самом деле очень рисковал, чтобы добраться до своей нынешней станции в жизни. Эван, на мой взгляд, иллюстрирует, почему сообщество Ruby, как вы говорите, супер-фантастическое. Он умный, доступный и увлеченный, помогая другим изучать Ruby. Если вам нужен потрясающий ресурс Ruby, его можно нанять (со всеми благословениями Rubysource) в TripleDogDare . Он один крутой кот (который любит кошек).

Достойна ли я?

Честно говоря, я немного опасался. Я никогда не был в паре раньше. Особенно не с незнакомцем. Особенно не с незнакомцем, который более опытен / умнее / лучше в этом рубиновом материале, чем ваш действительно. В моем мозгу была явная возможность, что сессия будет ему очень неприятна, и я, вполне возможно, заплачу. (Продолжая драматическую тему поста …) Я твердо стоял, хотя, зная, что жертвовать своим искусством является признаком величия.

День прибывает

В 9:50 вечера я начинаю трансовый взгляд «беспокоясь о моем экране», волнующийся о моем грядущем смущении, за моим столом. Десять минут спустя скайп-ринг возвращает меня к реальности. Это Эван. Я отвечаю: «Привет».

«Привет, Гленн. Вы готовы пойти? »- спрашивает он.
«Ну, вроде как. Я должен быть честным, здесь, я никогда не делал этого раньше.
«Какая? Запрограммирован? »- смеется он. «Все в порядке, я пойду с нами».

Ранее я рассказал Эвану о Loccasions, а он клонировал мой репозиторий github. Он сказал мне, что все, что ему нужно от меня, это мой открытый ключ SSH. Я послал ему ключ, и он сказал мне, чтобы я отправил ssh к своему ящику (он настроил меня, и у него есть классный домен типа DynDNS), что я и делаю. Моей следующей инструкцией было набрать tmux -S /tmp/glenn attach . tmux я не слышал о tmux , но бросил на ветер осторожность и набрал команду.

Revelations

Так что tmux безумно фантастичен. Команда, которую я ввел, подключила меня к сеансу tmux, который начал Эван. Окно терминала было разделено на командную строку и окно редактора (vim) с источником Loccasions. Кикер? Мы оба можем контролировать / печатать / и т.д. сеанс в режиме реального времени.

Окно сеанса TMUX

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

Чтобы сделать его еще круче, Эван перенаправил порт на свой сервер rails разработки на своем компьютере, поэтому, когда он запускал rails s , я мог открыть локальный браузер и увидеть наши изменения на сайте, опять же, в режиме реального времени. Я был потрясен. Эван, который, должно быть, привык видеть зрелищные аппетитные блинчики, похожие на меня в окне видеочата Skype, пожимает плечами, будто это не так уж и страшно. Сеанс сопряжения уже стоил того, и мы не коснулись ни одного кода. Я сказал ему, что он должен вести блог об этом подходе соединения. Массы должны быть информированы.

О да, мы должны программировать

С большим усилием Эван оторвал меня от моего облака и поставил перед нами задачу. Как я уже упоминал, он клонировал репозиторий, но еще не запускал bundle install . Вот где мы попали в наш первый выпуск. Я еще не обновил Loccasions до финальной версии Rails 3.1 (он начал жизнь на rc5), так что это был первый шаг. Эван открыл Gemfile и похвалил меня за использование «twiddle-waka» (~>) драгоценных камней в файле. Честно говоря, я всегда так делал, но не мог объяснить почему, но Эван может: Twiddle-waka обычно является безопасным выбором в Gemfiles, потому что крошечные выпуски (Z в XYZ) должны быть безопасными обновлениями, которые, как я понимаю, не вызовут поломки. Очевидно, это то, что нужно сделать с вашим Gemfile, и мое напряжение от того, что я идиот, немного ослабло. Может быть, поэтому Эван упомянул об этом, а может и нет. В любом случае, я перестал беспокоиться о возможности того, что мне скажут, что я бесполезен и слаб, и начал по-настоящему взволнован сессией.

(Я понимаю, что подход к версионированию гемов с помощью Bundler несколько спорен. Для другого подхода прочтите это .)

Эван изменил линию gem rails в Gemfile на gem rails ~>'3.1.0' , из-за чего Бандлер пожаловался на камень sass-rails . Чтобы снова порадовать Bundler, Sass-rails и coffee-rails также должны были указать свои соответствующие версии 3.1.0. Последним изменением версии для Rails 3.1.0 было Devise, переход с 1.4.2 на 1.4.6.

Mongoid недавно выпустила 2.2.0, поэтому мы тоже это изменили. Последнее изменение принесло сообщения о том, что bson_ext должен быть 1.4.0, а не 1.3.1. Вы должны luuuuuv Bundler (и я делаю). Быстрое изменение версии bson_ext и bundle install успешно завершена. Мы находимся на Rails 3.1.0 Final, прогресс в парном программировании.

Следующим предложением Эвана было использование гема guard_rspec (на основе guard ), чтобы тесты автоматически запускались при изменении файлов. Я думал об использовании автотеста, так что это было хорошее время. Никто из нас не был уверен, что spork и guard будут играть хорошо, и после нашей сессии я пошел и нашел guard_spork. Короче говоря, добавьте:

 gem 'guard-rspec', '~> 0.4.5' gem 'guard-spork', '~> 0.2.1' 

в группу разработки вашего Gemfile. Наконец, обновите spork до 0.9.0.rc9 ( gem 'spork', '~> 0.9.0.rc9') or you'll get a C error when spork builds and сборке spork gem 'spork', '~> 0.9.0.rc9') or you'll get a C error when spork builds and комплекта`. [Примечание: я не добавляю драгоценные камни для Mac OSX (fsevents и growl_notify) в Gemfile. Пожалуйста, прочитайте README в репозитории guard Github и установите события файловой системы для вашей системы.] Когда установлен guard, нам нужно рассказать ему о spork и rspec, и мы сделаем это с Guardfile в корне приложения:

 guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do watch('config/application.rb') watch('config/environment.rb') watch(%r{^config/environments/.+.rb$}) watch(%r{^config/initializers/.+.rb$}) watch('spec/spec_helper.rb') end guard 'rspec', :version => 2 do watch(%r{^spec/.+_spec.rb$}) watch(%r{^lib/(.+).rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { "spec" } # Rails example watch(%r{^spec/.+_spec.rb$}) watch(%r{^app/(.+).rb$}) { |m| "spec/#{m[1]}_spec.rb" } watch(%r{^lib/(.+).rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } watch(%r{^app/controllers/(.+)_(controller).rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] } watch(%r{^spec/support/(.+).rb$}) { "spec" } watch('spec/spec_helper.rb') { "spec" } watch('config/routes.rb') { "spec/routing" } watch('app/controllers/application_controller.rb') { "spec/controllers" } # Capybara request specs watch(%r{^app/views/(.+)/.*.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" } end 

Открытие нового терминала и печатание guard должны запустить сеанс охраны (и spork).

На страже!

Теперь, когда мы изменяем тестовые и прикладные файлы, спецификации должны запускаться автоматически. Мне нравится эта особенность — еще одна ступенька для парного программирования. (После нашей сессии я заметил, что мои тесты Selenium не смогли подключиться к Firefox 7, поэтому я обновил Capybara до версии 1.1.1 в Gemfile. Сделайте это тоже.)

Особенность дня

Как только мы настроили окружение и начали работать с охраной, Эван спросил меня, какую функцию я хочу добавить во время нашей сессии. У меня были очень амбициозные идеи о том, что мы могли бы сделать, но мы начнем с создания страницы для показа отдельного события. В терминах Rails я хотел создать последовательность событий # show (здесь я использую «sequence» для ссылки на представление controller =>, которое должно соответствовать отображению события). Итак, я перешел в каталог спецификаций и создал acceptence / show_event_spec.rb . Это был первый шанс Эвана увидеть, как я полностью полагался на приемочные тесты для тестирования приложения. Он рассказал мне, как он уходил от приемочных испытаний по причинам производительности и синтаксическим причинам. Эван хочет что-то вроде огурца, но не огурец. На самом деле он написал DSL, названный Couda, который подчеркивает подход к тестированию с учетом данных, когда, но не полагается на регулярные выражения, такие как Cucumber. Проверьте это.

Эван рассказал мне об опыте работы с сотнями спецификаций, когда ему приходилось использовать такие вещи, как parallel_tests, чтобы тесты запускались в течение 15 минут. На самом деле, мы говорили о всевозможных вещах, что, вероятно, является самым значительным выводом сессии. Конечно, мы добавили функцию в Loccasions, но это была болтовня о том, что мы делаем, и о Ruby / Rails, которые я нахожу захватывающими.

ОК, ОК, ФАКТИЧЕСКИЙ Код

Я не собираюсь переходить к фактической последовательности событий, которая привела к созданию страницы Show Event. Я опубликую код ниже, который должен быть у вас в рубке, если вы следите за серией Loccasions. На высоком уровне, Эван сделал немного кодирования, я сделал немного кодирования (он был действительно хорош в том, чтобы заставить меня делать часть работы, так как я был рад сидеть сложа руки и смотреть), и мы получили простую страницу. Вот спецификация для страницы:

 require 'spec_helper' feature 'Show Event', %q{ As a registered user I want to see an Event so I can see my Event Details } do background do @user = Factory(:user) @event = Factory(:event, :user => @user ) login_user @user end scenario "Show Event" do click_link "Show Details" page.current_path.should == event_path(@event) page.should have_content(@event.name) page.should have_content(@event.description) end end 

Добавьте ссылку «Показать подробности» в ** app / views / events / index.haml.html ** (Спасибо Alert Reader rsludge!) Вот новый ul и цикл для событий.

 %ul#events - for event in @events %li{:class => @event == event ? :selected : nil} %span.del_form =button_to "X", event, :confirm => "Are you sure?", :method => :delete %span.event_name = link_to event.name, edit_event_path(event) %span.event_details = link_to "Show Details", event_path(event) %span.event_description= event.description %div.clear 

Если вы прочитали последний пост, то вы знаете, что будет. Спецификация не выполняется, потому что нет метода events_controller # show:

 def show @event = current_user.events.find(params[:id]) end 

Затем он запросит шаблон представления ( app / views / events / show.html.haml ):

 %h2= @event.name .description= @event.description 

Да, я знаю, что это немного, но этого не произойдет, пока мы не добавим Occasions (следующий пост, обещаю!). Создание этого представления делает прохождение спецификации, и у нас появилась новая функция.

Время летит

В конце этой спецификации мы почти достигли часа. Я упомянул добавление «Случаев», и Эван (по понятным причинам) сказал, что мы были в хорошем месте, чтобы остановиться. Я согласился, и он прислал мне код. Вы можете увидеть все изменения здесь, которые на самом деле включают в себя некоторые незначительные изменения из комментариев предыдущих сообщений (спасибо Alert Readers!)

Go и Pair

В общем, мне очень понравилась парная сессия с Эваном. Я выучил тонну за час, и Loccasions лучше для этого. Эван увлечен тем, что помогает сообществу Ruby, и он нашел способ (tmux / Skype crazy-awesome) и сообщение ( RubyPair ). Я призываю вас зарегистрироваться на RubyPair, найти другого программиста и поработать. Эван всегда ищет партнеров для работы в RubyPair, поэтому подпишитесь на его часы работы и помогите. Наконец, я не могу адекватно выразить свою признательность Эвану за то, что он позволил мне задокументировать этот опыт и за то, что был добрым и понимающим. Хорошо, теперь пара!