<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Pervasive Code &#187; tools</title>
	<atom:link href="http://www.pervasivecode.com/blog/category/tools/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pervasivecode.com/blog</link>
	<description>Jamie Flournoy's Software Development Blog</description>
	<lastBuildDate>Wed, 01 Feb 2012 06:11:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to make Machinist and Autotest coexist</title>
		<link>http://www.pervasivecode.com/blog/2010/03/23/how-to-make-machinist-and-autotest-coexis/</link>
		<comments>http://www.pervasivecode.com/blog/2010/03/23/how-to-make-machinist-and-autotest-coexis/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 03:47:22 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[agile development]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/?p=189</guid>
		<description><![CDATA[If you&#8217;ve tried to use Machinist and autotest (part of ZenTest) you have probably seen this exception that prevented you from using it: 
`method_missing': No sham defined for name
It&#8217;s discussed in the machinist Google Group as well.
It&#8217;s because of a wacky hack that&#8217;s part of Machinist that overrides Module.name so you can do Sham.name, but [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve tried to use Machinist and autotest (part of ZenTest) you have probably seen this exception that prevented you from using it: </p>
<pre>`method_missing': No sham defined for name</pre>
<p>It&#8217;s discussed in <a href="http://groups.google.com/group/machinist-users/browse_thread/thread/9af4aa2243ae0368/4e9bba83113ace20">the machinist Google Group</a> as well.</p>
<p>It&#8217;s because of a wacky hack that&#8217;s part of Machinist that overrides Module.name so you can do <code>Sham.name</code>, but ZenTest expects Module.name to do what it does normally.</p>
<p>I have a fix for this.<br />
<span id="more-189"></span></p>
<p>I sent notahat a pull request via GitHub, so hopefully it&#8217;ll be merged by notahat into the official machinist gem, but until that happens you can try mine. I published the gem as JamieFlournoy-machinist to rubygems.org.</p>
<p>Try &#8216;gem install JamieFlournoy-machinist -v 1.0.6&#8242; and see if it works for you. It does for me with ZenTest 4.2.1, autotest-rails 4.1.0, and a Rails 2.3.5 project.</p>
<p><a href="http://github.com/JamieFlournoy/machinist">(my machinist fork on github)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2010/03/23/how-to-make-machinist-and-autotest-coexis/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Techniques for Exhaustively Testing a Rails App</title>
		<link>http://www.pervasivecode.com/blog/2008/08/23/techniques-for-exhaustively-testing-a-rails-app/</link>
		<comments>http://www.pervasivecode.com/blog/2008/08/23/techniques-for-exhaustively-testing-a-rails-app/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 22:55:12 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[coverage]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2008/08/23/techniques-for-exhaustively-testing-a-rails-app/</guid>
		<description><![CDATA[I subscribe to dozens of tech blogs (including but not limited to Ruby and Rails), and although I&#8217;ve seen quite a lot of commentary about TDD and BDD, I&#8217;m not sold on either of them yet. TDD is interesting, but BDD seems like a waste of time. But I am completely sold on automated testing [...]]]></description>
			<content:encoded><![CDATA[<p>I subscribe to dozens of tech blogs (including but not limited to Ruby and Rails), and although I&#8217;ve seen quite a lot of commentary about TDD and BDD, I&#8217;m not sold on either of them yet. TDD is interesting, but BDD seems like a waste of time. But I <em>am</em> completely sold on automated testing in general. I write lots and lots of tests and make sure using rcov that my tests cover all of the code. </p>
<p>Getting 100% coverage isn&#8217;t easy. In general it means you definitely can&#8217;t just write a single test case per method and declare victory when it passes. When the number of possible combinations of inputs (method arguments and/or mock objects) and expected outputs (return values, exceptions, and side effects) becomes large, then the potential for copy-and-paste errors in your test code becomes large, and legibility becomes an issue. This is the point at which I find the recent fascination with writing tests in a near-natural-language DSL to be a distraction. It&#8217;s orthogonal to the problem I&#8217;m dealing with, which is how to comprehensively test the code. In other words, the problem is not making a small number of tests more readable, but concisely expressing a large number of input/output combinations and a large number of different tests, and making it all readable.</p>
<p>I assume that there are others working on this problem too, so I&#8217;ll describe some of the things I&#8217;ve come up with, and hopefully if you have any good ideas you&#8217;ll post them in the comments section.</p>
<p><span id="more-78"></span></p>
<p><strong>Test Data Iterators</strong></p>
<p>If you express the set of inputs and outputs as a data structure, such as a Hash of input => expected ouput pairs, or an Array of [input, expected output] Arrays, you can easily do <code>test_data.each do |input,output| ... end</code> and drive tests that way.</p>
<p>(I considered pulling the data itself out of the test code and loading it from a YAML or CSV file or even including a data-only Ruby script, but that seemed like pointless added complexity. If I were working with a professional tester who didn&#8217;t want to touch Ruby code, I might change that to make it easier to dump from an Excel spreadsheet into a text file that the tests would use.)</p>
<p>One problem with this approach is that you may have a <code>test_frobnicate</code> method that invokes <code>frobnicate</code> dozens of times. This means that this one test can take a while to run if the tested method takes any amount of time, which is problematic if you just want to re-test that one input/output combo until it works. Your edit/test/debug loop should be ultra fast, and re-testing successful pairs gets in the way of testing the pair you&#8217;re not sure about.</p>
<p>More importantly, trying all those combinations in one test method means that if an assertion fails, the failure masks the outcome of the remaining combinations. If there are 25 combinations and combination #2 fails, then a <code>Test::Unit::AssertionFailedError</code> is thrown, and the other 23 of them go unchecked. That&#8217;s not ideal, since it can be useful in debugging if you can see that 24/25 failed vs. 1/25 failed.</p>
<p>To solve this, I changed the code so that it iterates over the test data inside the class definition, generating a new test method for each input/output pair:</p>
<pre>
class_eval do
  test_data_hash.each do |input, output|
    define_method("test_frobnicator_#{input.hash}") do
      check_frobnicator(input, output)
    end
  end
end
</pre>
<p>That gives you a bunch of test methods that each run the test once with different input and expected output values. Autotest integrates well with this technique, since it will not re-run the test methods which previously passed until after you have fixed all of the ones which failed.</p>
<p><strong>Test Setup Blocks</strong></p>
<p>I also use a <code>with_x_y_z do...end</code> idiom for mock setup when possible. So a test might contain:</p>
<pre>
def check_index(inputs, expected_outputs)
  if inputs[:logged_in]
    with_fake_login{|user| get :index, inputs[:params] }
  else
    get :index, inputs[:params]
  end

  # ... test outputs against expected output
end
</pre>
<p>Since this idiom uses blocks, you can nest them to create complicated setup scenarios, pass arguments to the <code>with_blah</code> method to control the behavior of the mock objects, and so on. (You could do this with regular <code>set_up_blah</code> methods but I think this is easier to read.)</p>
<p><strong>Calculated Outputs</strong></p>
<p>Despite their shortcomings, I still use Fixtures (with the PreloadFixtures plugin) and I write unit tests for my models. That means that I can then assume that the models&#8217; behavior is correct in other tests (provided that those unit tests pass). So I try not to put any data that&#8217;s already expressed in fixture files into my test method inputs or expected outputs. Instead, I ask for the fixture by its label (<code>widgets(:doodad)</code>) and then use its properties as needed in assertions within the current test. This reduces the size of the input/output data, which makes it easier to read and reduces the amount of effort required to add more combinations later.</p>
<p><strong>Testing Views, Model Associations, and Model Validation</strong></p>
<p>As Bruce Eckel says, <a href="http://www.mindview.net/WebLog/log-0025">If it&#8217;s not tested, it&#8217;s broken.</a> Or as Peter Drucker said, &#8220;What gets measured gets managed.&#8221;</p>
<p>I test all of these. I&#8217;ve read the arguments of those who say that none of these are necessary, and I disagree. The arugment that testing associations and validations is tantamount to testing Rails itself is just incorrect. Rails&#8217; own unit tests cannot possibly test the validations and associations expressed in every Rails application&#8217;s model classes, so Rails application developers still have to do this.</p>
<p><strong>Associations</strong></p>
<p>I can&#8217;t tell you how many times I&#8217;ve gotten has_one and belongs_to backwards and only found out when ActiveRecord told me that the column didn&#8217;t exist, because I told it to look at the table on the wrong side of the association. I feel stupid when I see that I made that mistake, but writing that test takes seconds and once I see the failure it&#8217;s easy to fix. Better to catch it and fix it now rather than have a user find it, right?</p>
<p><strong>Validations</strong></p>
<p>The same goes for model validations. Yes, I know that <code>validates_format_of</code> has been tested, but my regexes for username format and email addresses need testing too.</p>
<p><strong>Views</strong></p>
<p>Views should be tested <em>only if you care what your users see</em>.</p>
<p>Somewhere there is probably an organization with no users, where inputs matter but outputs can be anything. Maybe the goal of the project is to burn cash rather than to ship something good. They don&#8217;t need to test their views.</p>
<p>I agree that views should be dumbed down as much as possible using helpers, but that&#8217;s not enough to assure that they work. If you&#8217;re not testing views with automated tests, then how do you test them? With a browser? Every time you change anything, you&#8217;re going to exhaustively check every combination of inputs and outputs to make sure that all the dynamic goodies are in the right place? I doubt it. Obviously you do have to check views in a browser to make sure that purely visual aspects are correct, but there are things you can check automatically. You can do quite a lot with assert_select, and for client-side tests, <a href="http://selenium.openqa.org/">Selenium</a> can do pretty much anything. (It&#8217;s probably not worth the effort to have Selenium use the DOM to see that the browser applied CSS in exactly the way that you wanted it to, but if you wanted to, you could.)</p>
<p>I don&#8217;t know how to do something similar to coverage testing for views, but a good start is to just check for the effects of everything that the controller stored in instance variables. Maybe those should be displayed as-is in the resulting document, or maybe they should be truncated, or processed by a helper into a different representation.</p>
<p>In any case, you don&#8217;t have to test with the same set of inputs as the functional test for the controller; just do white box testing for the minimal set of combinations that should exercise all of the permutations of the view code (which should be a very small number). Testing the helpers separately can cut down on the number of permutations of inputs and outputs also. So if you have a helper that creates a navigation breadcrumb visual element from an array of strings, you could just test that in isolation with 0, 1, 2, and 3 elements, and then check for one version of breadcrumbs when looking for it in a view.</p>
<p>I&#8217;m particularly inspired by the claim that Sebastian Delmont of <a href="http://www.streeteasy.com/">StreetEasy</a> made in the <a href="http://podcast.rubyonrails.org/programs/1/episodes/sebastian_delmont">May 31, 2006 episode of the Ruby on Rails Podcast</a> about having no human approval step between a successful test suite run and deployment to production. That&#8217;s pretty darn bold, but if you stop and think about it, it is feasible with today&#8217;s tools to automate any &#8220;white glove test&#8221; that a real person would do before approving the release for deployment to production. I&#8217;m not that brave yet, but I like the idea of a condition that checks if the changed code has anything to do with a view (ERB, JavaScript, CSS, etc.), and if not, would just rubberstamp it and deploy it. Clearly a change that could require a manual test in multiple browsers wouldn&#8217;t be a wise thing to autodeploy, but something like fixing a bug deep in the code shouldn&#8217;t require a human to approve it, especially if the autodeploy condition depends on that chunk of code having 100% test coverage following the bug fix.</p>
<p><strong>Your Tips?</strong></p>
<p>I&#8217;m always looking for ways to test code with less effort on my part. Please let me know if you have ideas or suggestions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/08/23/techniques-for-exhaustively-testing-a-rails-app/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Rakefile snippet to run Rails&#8217; rake:stats in a plain old gem</title>
		<link>http://www.pervasivecode.com/blog/2008/08/11/rakefile-snippet-to-run-rails-rakestats-in-a-plain-old-gem/</link>
		<comments>http://www.pervasivecode.com/blog/2008/08/11/rakefile-snippet-to-run-rails-rakestats-in-a-plain-old-gem/#comments</comments>
		<pubDate>Mon, 11 Aug 2008 21:48:47 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2008/08/11/rakefile-snippet-to-run-rails-rakestats-in-a-plain-old-gem/</guid>
		<description><![CDATA[I&#8217;ve been moving a bunch of utility code out of a medium sized project (>10KLOC)  to make it easier to test. I started by trying to make a set of plugins, but inter-plugin dependency management is basically nonexistent, and now that Rails supports explicit Gem dependencies, I decided to make them gems.
I&#8217;m happy I [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been moving a bunch of utility code out of a medium sized project (>10KLOC)  to make it easier to test. I started by trying to make a set of plugins, but inter-plugin dependency management is basically nonexistent, and now that Rails supports explicit Gem dependencies, I decided to make them gems.</p>
<p>I&#8217;m happy I chose to make them gems, but I miss some of the stuff you get in a Rails project. In particular I wanted &#8216;rake:stats&#8217;, so I can update my estimation spreadsheet which is now almost 9 months old. I need the stats for each gem in addition to the main Rails project, in order to compare this to prior figures from the Rails project before I split it up.</p>
<p>So, here is the Rakefile snippet that I added, which adds the rake:stats task into a regular gem. If you don&#8217;t have the Rails gem installed, it will fail gracefully, without breaking your whole gem. So you need not make your teeny little gem depend on all of Rails being installed on every machine where your gem needs to go. Just install Rails whereever you want to run stats, which is probably already the case on your development machine.<br />
<span id="more-77"></span></p>
<p>Here is a Pastie link, since my blog theme truncates the too-wide text: <a href="http://pastie.org/251453">this same code on Pastie</a></p>
<pre>
# stats
begin
  gem 'rails'
  require 'code_statistics'
  namespace :spec do
    desc "Use Rails's rake:stats task for a gem"
    task :statsetup do
      class CodeStatistics
        def calculate_statistics
          @pairs.inject({}) do |stats, pair|
            if 3 == pair.size
              stats[pair.first] = calculate_directory_statistics(pair[1], pair[2]); stats
            else
              stats[pair.first] = calculate_directory_statistics(pair.last); stats
            end
          end
        end
      end
      ::STATS_DIRECTORIES = [['Libraries',   'lib',  /.(sql|rhtml|erb|rb|yml)$/],
                   ['Tests',     'test', /.(sql|rhtml|erb|rb|yml)$/]]
      ::CodeStatistics::TEST_TYPES << "Tests"
    end
  end
  desc "Report code statistics (KLOCs, etc) from the application"
  task :stats => “spec:statsetup” do
    CodeStatistics.new(*STATS_DIRECTORIES).to_s
  end
rescue Gem::LoadError => le
  task :stats do
    raise RuntimeError, “‘rails’ gem not found - you must install it in order to use this task.n”
  end
end</pre>
<p>BTW I intend to replace this with a <a href="http://www.dwheeler.com/sloccount/">sloccount</a>-based task later. If and when I do that I&#8217;ll publish it here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/08/11/rakefile-snippet-to-run-rails-rakestats-in-a-plain-old-gem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updated .autotest</title>
		<link>http://www.pervasivecode.com/blog/2008/05/17/updated-autotest/</link>
		<comments>http://www.pervasivecode.com/blog/2008/05/17/updated-autotest/#comments</comments>
		<pubDate>Sun, 18 May 2008 05:36:19 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2008/05/17/updated-autotest/</guid>
		<description><![CDATA[I just brought a new project into the world of autotest. I&#8217;m not using the Leopard FSEvents &#8220;fix&#8221; because it&#8217;s not necessary (note the sleep and add_exception calls below). I am using the fun and helpful sound plugin, but not the playlist version of that plugin. Here&#8217;s my .autotest file.


Autotest.add_hook :initialize do &#124;autotest&#124;
   [...]]]></description>
			<content:encoded><![CDATA[<p>I just brought a new project into the world of <a href="http://nubyonrails.com/articles/autotest-rails">autotest</a>. I&#8217;m not using the <a href="http://rails.aizatto.com/category/autotest/">Leopard FSEvents &#8220;fix&#8221;</a> because it&#8217;s not necessary (note the sleep and add_exception calls below). I am using the fun and helpful <a href="http://www.fozworks.com/2007/7/28/autotest-sound-effects">sound plugin</a>, but not the <a href="http://www.metaskills.net/2008/4/6/autotest-playlist-for-red-green-feedback">playlist version of that plugin</a>. Here&#8217;s my .autotest file.<br />
<span id="more-73"></span></p>
<pre>
Autotest.add_hook :initialize do |autotest|
    autotest.sleep=3
    autotest.add_exception(/\\/\.git\\//)
end

require '/Users/jamieflournoy/autotest/sound/sound'
Autotest::Sound.sound_app = '/opt/local/bin/mpg321'
Autotest::Sound.sound_path = "/Users/jamieflournoy/autotest/sound/sound_fx/"
</pre>
<p>Note that the sound plugin needs a patch:</p>
<pre>
29c29
<   [:run, :red, :green, :quit, :run_command, :ran_command].each do |hook|
---
>   [:initialize, :red, :green, :quit, :run_command, :ran_command].each do |hook|
</pre>
<p>You&#8217;ll also need to make sure your sound set has an initialize.mp3 instead of a run.mp3.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/05/17/updated-autotest/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Making Rcov measure your whole Rails app, even if tests miss entire source files</title>
		<link>http://www.pervasivecode.com/blog/2008/05/16/making-rcov-measure-your-whole-rails-app-even-if-tests-miss-entire-source-files/</link>
		<comments>http://www.pervasivecode.com/blog/2008/05/16/making-rcov-measure-your-whole-rails-app-even-if-tests-miss-entire-source-files/#comments</comments>
		<pubDate>Fri, 16 May 2008 22:42:42 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[coverage]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2008/05/16/making-rcov-measure-your-whole-rails-app-even-if-tests-miss-entire-source-files/</guid>
		<description><![CDATA[I&#8217;ve seen a few Rake tasks for Rcov that work OK, but which fail in an interesting way (if you care about coverage): they give your coverage metrics an unexpected boost if you have 0% coverage in one or more source files.
Huh? Exactly. If you have 500 source files, and your test suite only requires [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve seen a few Rake tasks for Rcov that work OK, but which fail in an interesting way (if you care about coverage): they give your coverage metrics an unexpected boost if you have 0% coverage in one or more source files.</p>
<p>Huh? Exactly. If you have 500 source files, and your test suite only <code>require</code>s one of them, then you get a free ride on those 499 files that have 0% coverage. Theoretically you could get 100% coverage in your report even though 499 source files are not touched at all. D&#8217;oh!<br />
<span id="more-72"></span><br />
The reason for this is that rcov isn&#8217;t responsible for finding all of your source files. It just measures what portion of the files which you loaded were executed. The Rake tasks that people have written just kick off the test code, which also have no need to load all of your application&#8217;s source files. They just load whatever they need, and so that&#8217;s what rcov is aware of. But that&#8217;s not answering the question you thought you were asking, which is &#8220;how much of my application is being tested?&#8221;</p>
<p>You have to explicitly say that you want to see coverage numbers for all the files your tests need, plus all of the files that your tests did not touch. Put this in your test/test_helper.rb:</p>
<pre>
# require the entire app if we're running under coverage testing,
# so we measure 0% covered files in the report
coverage_testing_active = defined?(Rcov)
if coverage_testing_active
    all_app_files = Dir.glob('{app,lib}/**/*.rb').grep(
        /^(?!lib\\/(scheduled_tasks|template_optimizer)\\/)/)
    all_app_files.unshift('app/controllers/application.rb')
    all_app_files.each{|rb| require rb}
end</pre>
<p>You&#8217;ll probably want to customize that regexp to weed out any .rb files that you don&#8217;t want to load during the test suite (or which aren&#8217;t your own code).</p>
<p>Because of all this <code>require</code>-ing, you might want to apply the snippet in my <a href="http://www.pervasivecode.com/blog/2008/05/16/rails-snippet-require-app-files-only-once/">prior post</a>, which eliminates duplicate required source files if they&#8217;re under your RAILS_ROOT. Otherwise you may see evidence of repeated loading of the same source files.</p>
<p>With this snippet in place, you&#8217;ll still never see 0% coverage in a file. If there are zero lines of executable code in the file, it will not be listed. But you&#8217;ll see really low figures (4% etc.) for files that are loaded but not executed. Hopefully that will help you see where you&#8217;ve completely overlooked some code in your tests that users might still be able to get to.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/05/16/making-rcov-measure-your-whole-rails-app-even-if-tests-miss-entire-source-files/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Thoughts about using Git for closed source projects</title>
		<link>http://www.pervasivecode.com/blog/2008/04/14/thoughts-about-using-git-for-closed-source-projects/</link>
		<comments>http://www.pervasivecode.com/blog/2008/04/14/thoughts-about-using-git-for-closed-source-projects/#comments</comments>
		<pubDate>Mon, 14 Apr 2008 16:11:41 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[git]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2008/04/14/thoughts-about-using-git-for-closed-source-projects/</guid>
		<description><![CDATA[Git is getting a lot of press in the open source world lately, but hasn&#8217;t got much traction in the closed source corporate development world. There&#8217;s a reason for this, and it&#8217;s more than conservatism on the part of the corporate developers. Git (or any DVCS, really) embodies a development culture that isn&#8217;t very enterprise-y.

This [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://git.or.cz/">Git</a> is getting a lot of press in the open source world lately, but hasn&#8217;t got much traction in the closed source corporate development world. There&#8217;s a reason for this, and it&#8217;s more than conservatism on the part of the corporate developers. Git (or any DVCS, really) embodies a development culture that isn&#8217;t very enterprise-y.<br />
<span id="more-66"></span><br />
This is something that I&#8217;ve noticed when talking to some of my developer friends who are working on closed source projects, in software companies or in teams building in-house custom applications. Big companies like central control, hierarchy, policies, and audit trails, and centralized software version control systems fit this very well. You get one big server in the sky that has all the source code, central control over permissions, a log of changes, and usually a way to add pre and post commit hooks to integrate the VCS repo with related systems.</p>
<p>With a DVCS, everybody can be a lone ranger, unless you build a process on top that puts back these features (i.e. a remote repository that everybody pushes to). This is something that many of the introductory documents I&#8217;ve seen regarding Git try to downplay &#8212; you don&#8217;t need a central repository, yippee! Just pass changes around from developer to developer &#8212; but while that may thrill the solo coder hacking on his laptop on a long flight, it isn&#8217;t music to the ears of a CIO.</p>
<p>In Git&#8217;s case, there is no central list of version numbers, and the history can be altered using <code>git-rebase</code> and <code>git-commit --amend</code>. Do you really need to see the precise history of every change ever made to the code? Perhaps you think you do because it gets screwed up so easily in some version control tools, and you need to at least be able to backtrack and manually unsnarl a really big screw-up. In that case, you probably don&#8217;t need it, as long as the version control tool can be trusted.</p>
<p>Or maybe you&#8217;re guarding against human error, and what you really want is granular remote backups. Just as you can use <code>svnadmin dump</code> and <code>svnadmin load</code> to intentionally truncate the history that the repository knows about, you could use <code>git rebase</code> to squash a bunch of commits together into a single big change, and thereby lose the ability to go back to one of those intermediate steps. So you probably should think about archiving the full-granularity repository before you consolidate the old historical steps for developer convenience reasons. And even if you&#8217;re a lone ranger, you should think about using rsync or duplicity to regularly put your local .git repositories someplace safe, or push to a remote git repository that no one else has access to, or both.</p>
<p>One solution to make Git more enterprise-friendly <a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html">git-svn</a>, which gives you the tool integration and centralness of Subversion, with the local branch/merge and offline commit benefits of Git (which are <i>very very nice</i>). I haven&#8217;t used it but I am told that it works very well. It&#8217;s also a very low-risk way to try out Git, since you can just check your changes in and go back to using Subversion at any time.</p>
<p>Git is challenging to learn, partly because the command language is not very intuitive, and partly because the folks documenting it so far are obsessed with explaining how radically new and different it is rather than how you probably will want to use it. And for folks reading this documentation, the &#8220;look how different your process could be&#8221; examples are not necessarily very appealing, since the benefits gained by using a centralized VCS are not addressed.</p>
<p>Still, I think Git has enough hype around it that in a year or two there will be some very slick, usable tools that conceal the complex inner workings that you currently have to understand well in order to be productive. They may also include features that make backups or the setup and shared use of a remote repository easy. So if you&#8217;re not convinced that it&#8217;s time to migrate Git now, just wait. It will probably come to where you are eventually.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2008/04/14/thoughts-about-using-git-for-closed-source-projects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Looking forward to LinuxWorld Expo SF 2007</title>
		<link>http://www.pervasivecode.com/blog/2007/07/27/looking-forward-to-linuxworld-expo-sf-2007/</link>
		<comments>http://www.pervasivecode.com/blog/2007/07/27/looking-forward-to-linuxworld-expo-sf-2007/#comments</comments>
		<pubDate>Sat, 28 Jul 2007 02:58:52 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[gfs]]></category>
		<category><![CDATA[nfs]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[raid]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[vmware]]></category>
		<category><![CDATA[xen]]></category>
		<category><![CDATA[zfs]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/07/27/looking-forward-to-linuxworld-expo-sf-2007/</guid>
		<description><![CDATA[Last year I was doing mobile development and there was interesting Linux-as-smartphone-OS stuff going on. Now I&#8217;m doing Ruby on Rails development and there&#8217;s interesting server grid stuff going on. Here&#8217;s what I&#8217;m looking forward to finding out more about (all of these are things I&#8217;ve been watching or directly researching already):

Xen:
Xen seems to have [...]]]></description>
			<content:encoded><![CDATA[<p>Last year I was doing mobile development and there was interesting Linux-as-smartphone-OS stuff going on. Now I&#8217;m doing Ruby on Rails development and there&#8217;s interesting server grid stuff going on. Here&#8217;s what I&#8217;m looking forward to finding out more about (all of these are things I&#8217;ve been watching or directly researching already):<br />
<span id="more-36"></span><br />
<b>Xen</b>:<br />
<a href="http://www.xensource.com/products/xen/">Xen</a> seems to have eclipsed <a href="http://www.vmware.com/">VMware</a> as the standard low-cost virtualization solution, and virtualization looks like a giant sysadmin time saver for people like me who want to start dirt cheap (tens of dollars / month for a single Xen VPS) and potentially have dozens of servers in multiple data centers a few months later. I&#8217;d like to see what people are doing with it, especially along the lines of turning distro ISOs into preinstalled Xen images, and making tools to ease the creation and deployment of existing custom Xen images.</p>
<p><b>GFS, ZFS:</b><br />
I&#8217;m also interested in distributed filesystems like <a href="http://www.redhat.com/software/rha/gfs/">GFS</a>. I was under the impression until a few months ago that <a href="http://www.linuxinsight.com/ols2006_why_nfs_sucks.html">gross ugly NFS</a> was still the state of the art, but apparently somebody has finally addressed that. <em>Correction: GFS is a SAN filesystem, not a distributed filesystem, so it isn&#8217;t really comparable with NFS.</em><br />
<a href="http://www.opensolaris.org/os/community/zfs/">ZFS</a> is also interesting, because RAID has turned out to be complicated and expensive, mainly because it has to provide a transparent abstraction of a simple low-level block device. In classic time-sharing situations where many users run many applications on one volume that made more sense than it does now, where many users share one clustered application that has one dominant usage pattern across a large number of servers, each of which has several disks. The smaller set of requirements means that you can customize the clustered storage behavior and get major cost and performance savings, and ZFS seems to be a really good halfway point between application-level 100% custom clustered storage code, and kernel or hardware-level 100% generic RAID. The goal here would be to have dozens of cheap servers with several cheap drives each connected to cheap (motherboard-based) controllers, with HA and parallelization provided in software. </p>
<p><b>PostgreSQL:</b><br />
Also I&#8217;m becoming a total <a href="http://www.postgresql.org/">PostgreSQL</a> weenie and I want to see how they&#8217;re presenting themselves, and who&#8217;s making closed-source enterprise add-ons, esp. since Sun is increasingly investing in PostgreSQL (in a way that benefits the PostgreSQL community, not just Sun and Sun&#8217;s customers). Sun&#8217;s wagon is no longer hitched to Oracle on Solaris on SPARC, and the open stack of PostgreSQL on Linux (or Solaris) on x86 is proving to be extremely cost effective without sacrificing features, data integrity, or SMP scalability (as has been the case with MySQL). I think the &#8220;who&#8217;s the big fast fancy database of choice&#8221; tipping point from Oracle-&gt;PostgreSQL is already here and the world just hasn&#8217;t fully recognized that yet. The only thing left is built-in multimaster clustering (there&#8217;s <a href="http://www.pgcluster.org/">PGCluster</a> but it doesn&#8217;t look like a healthy project, and it&#8217;s not built in) but I think that&#8217;s just a matter of time now, since it&#8217;s such a desirable feature for the kind of customers Sun is courting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/07/27/looking-forward-to-linuxworld-expo-sf-2007/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>RCOV C0 line coverage more generous than EMMA&#8217;s C1 line coverage</title>
		<link>http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/</link>
		<comments>http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/#comments</comments>
		<pubDate>Wed, 11 Jul 2007 19:26:01 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[coverage]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/</guid>
		<description><![CDATA[Coverage tests in Ruby (with rcov) are less strict than in Java (with EMMA), so watch out &#8211; 100% coverage is easy to attain but not as meaningful.

For Java code coverage, I like EMMA. Clover looks really nice and all, but seriously, $250 a seat? Yeesh. Talk about poor product pricing &#8211; I will never [...]]]></description>
			<content:encoded><![CDATA[<p>Coverage tests in Ruby (with <a href="http://eigenclass.org/hiki.rb?rcov">rcov</a>) are less strict than in Java (with <a href="http://emma.sourceforge.net/">EMMA</a>), so watch out &#8211; 100% coverage is easy to attain but not as meaningful.<br />
<span id="more-34"></span><br />
For Java code coverage, I like EMMA. <a href="http://www.cenqua.com/clover/">Clover</a> looks really nice and all, but seriously, $250 a seat? Yeesh. Talk about poor product pricing &#8211; I will <i>never</i> buy that product, nor seriously consider buying it, because of the outrageous price. I mean, a single license of <a href="http://www.jetbrains.com/idea/">IntelliJ</a> is $1 cheaper. That&#8217;s like charging $300 for a better Ant. C&#8217;mon.</p>
<p>Anyway, EMMA is very conservative about coverage estimates. Consider this single line of Java code:</p>
<p><code>int x = 1; if (x &gt; 1){throw new RuntimeException();}</code></p>
<p>When you run it, the assignment will execute, as will the comparison, but the block containing <code>throw</code> will never be reached. So, the line is not fully covered. EMMA looks at bytecodes and maps those back to line numbers, and will mark this line as partially covered.</p>
<p>It&#8217;s maddening sometimes, but it&#8217;s correct; it&#8217;s your problem to figure out how to force all those darned IOExceptions that you know can&#8217;t ever happen, or to give up and let some apocalyptic error handling code not be covered. I used to shoot for 85-90% coverage, and just live with some uncovered wacky code when I couldn&#8217;t find a reasonable way to trigger hideous errors.</p>
<p>(There&#8217;s a little voice in my head that says, &#8220;Come on, you slacker, you should make it possible to dynamically break the database configuration and remount the root filesystem as read-only during the test suite so that the error handlers can all be 100% covered!&#8221; But that little voice never ships anything, he just sits around and writes more and more paranoid code &#8212; no <a href="http://archive.eiffel.com/doc/manuals/technology/contract/ariane/page.html">Ariane 5 disaster</a> on my watch! &#8212; and gets asymptotically closer to 100% coverage.)</p>
<p>Okay, now the Ruby version:</p>
<p><code>x = 1; raise RuntimeError if x &gt; 1</code></p>
<p>Same story, prettier code (cuz it&#8217;s Ruby; duh, of course it&#8217;s prettier): assignment gets executed, condition is executed, no exception is raised. Rcov says it&#8217;s 100% covered.</p>
<p>The difference is <a href="http://eigenclass.org/hiki.rb?rcov#l15">C0 coverage</a> (Rcov) vs. <a href="http://emma.sourceforge.net/faq.html#q.fractional">C1 coverage</a> (EMMA). EMMA only counts a line as 100% covered if all of the bytecodes compiled from it were executed. Rcov counts a line as 100% covered if execution visited that line at all.</p>
<p>(EMMA uses &#8220;basic blocks&#8221; instead of bytecodes, so in obscure failure cases the reported line coverage figure is even lower, but that doesn&#8217;t affect the conditions for what 100% line coverage requires.)</p>
<p>I&#8217;m not sure if it&#8217;s feasible to get C1 coverage on the regular Ruby VM, but it would be nice to have. In the meantime, just be aware that 100% C0 coverage is easy to attain with rcov, but doesn&#8217;t mean you&#8217;re done testing everything.</p>
<p>Of course, 100% C1 coverage doesn&#8217;t mean you&#8217;re done testing everything either, but it&#8217;s closer to meaning that than 100% C0 coverage is.</p>
<p>In fact, it&#8217;s good to over-test code that&#8217;s already covered once. On any given project in the real world, there is code that will succeed with some values and fail with others. (<code>print x/y</code>, for example.)  Just testing with one set of values isn&#8217;t enough. I like to create an array of inputs and expected outputs and use Array.each to iterate over them and pass them into a block that calls the code under test and then compares the actual outputs to the expected outputs with assert_equal. It means that I&#8217;m following DRY (rather than cutting and pasting several lines of test code and then editing a teeny bit of each pasted chunk&#8230; eww) but still testing many different ways.</p>
<p>But, even with a C0 coverage tool, at least you know what <em>hasn&#8217;t</em> been touched at all, and you can use your big smart programmer brain to think of a few ways to torture that code. Just remember that you probably should be aiming for an unmeasurable way-over-100% imaginary coverage target, beating the heck out of your fanciest code with many, many different inputs and then moving on to the next chunk of uncovered code only when the last chunk is thoroughly proven to not suck.</p>
<p>Good testing!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/07/11/rcov-c0-line-coverage-more-generous-than-emmas-c1-bytecode-coverage/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Subversion 1.5 will include merge tracking</title>
		<link>http://www.pervasivecode.com/blog/2007/07/08/subversion-15-will-include-merge-tracking/</link>
		<comments>http://www.pervasivecode.com/blog/2007/07/08/subversion-15-will-include-merge-tracking/#comments</comments>
		<pubDate>Sun, 08 Jul 2007 16:30:10 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Subversion]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/07/08/subversion-15-will-include-merge-tracking/</guid>
		<description><![CDATA[Despite Linus&#8217; strident criticism of Subversion (in the 70 minute video he accuses Subversion, and then anybody who wrote it, and then anybody who likes it, of being ugly and stupid) I still use Subversion and I like it. Clearly compared to Linus I am ugly and stupid. OK fine. But I&#8217;m not switching to [...]]]></description>
			<content:encoded><![CDATA[<p>Despite Linus&#8217; <a href="http://www.youtube.com/watch?v=4XpnKHJAok8">strident criticism</a> of Subversion (in the 70 minute video he accuses Subversion, and then anybody who wrote it, and then anybody who likes it, of being ugly and stupid) I still use Subversion and I like it. Clearly compared to Linus I am ugly and stupid. OK fine. But I&#8217;m not switching to <a href="http://git.or.cz/">git</a> now because my tiny teams have been fine with Subversion. Maybe later I&#8217;ll give git a whirl.<br />
<span id="more-33"></span><br />
Nevertheless, the ugliest-stupidest part of using Subversion in my experience is merging &#8211; specifically, repeated merging. It takes caution on the part of the person doing the merge to avoid re-merging the same changes, which sucks. Imagine everybody you&#8217;re developing with, including yourself when you&#8217;re on the phone and trying to wrap up some changes before running out the door for whatever reason, and you&#8217;ll realize that having a tool that can rapidly shoot you in the foot in a way that may take hours to unwind, but more importantly, days to recognize and identify, is scary. (Consider that old, replaced code, and the old tests that go with it, might be put back into your current source tree, and your automated tests would be happy since they all got merged back in as one big lump. You&#8217;d have to look for specific changes and features you had made in order to notice that they had regressed back to an earlier version without you meaning to do that. Eek!)</p>
<p>Well, <a href="http://blogs.open.collab.net/svn/2007/05/the_subversion__1.html">they&#8217;re fixing it</a>. I dunno if it&#8217;s gonna be perfect, but at least they&#8217;re addressing the problem and seem to understand what the needs of the masses are. So I&#8217;m optimistic.</p>
<p>And yeah, at some point I&#8217;ll probably check out Git. But not until Subversion irritates me more than it does today. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/07/08/subversion-15-will-include-merge-tracking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Impressions of Ruby on Rails from an ex J2EE developer (me)</title>
		<link>http://www.pervasivecode.com/blog/2007/07/05/impressions-of-ruby-on-rails-from-an-ex-j2ee-developer-me/</link>
		<comments>http://www.pervasivecode.com/blog/2007/07/05/impressions-of-ruby-on-rails-from-an-ex-j2ee-developer-me/#comments</comments>
		<pubDate>Fri, 06 Jul 2007 05:20:15 +0000</pubDate>
		<dc:creator>Jamie Flournoy</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.pervasivecode.com/blog/2007/07/05/impressions-of-ruby-on-rails-from-an-ex-j2ee-developer-me/</guid>
		<description><![CDATA[A friend who is working primarily in the J2EE technology world (as I was, until early 2006) asked me for a how&#8217;s-it-going with respect to Ruby and Rails.
The short version:
- Ruby is fun to program in, as you&#8217;ve probably heard
- Rails is over-hyped, but it&#8217;s still quite good (definitely not perfect)
- I like the productivity [...]]]></description>
			<content:encoded><![CDATA[<p>A friend who is working primarily in the J2EE technology world (as I was, until early 2006) asked me for a how&#8217;s-it-going with respect to Ruby and Rails.</p>
<p>The short version:<br />
- Ruby is fun to program in, as you&#8217;ve probably heard<br />
- Rails is over-hyped, but it&#8217;s still quite good (definitely not perfect)<br />
- I like the productivity of Ruby on Rails but I wouldn&#8217;t call it a silver bullet by any means<br />
- Ruby performance was bad and is getting less bad, and can even be good if you do what the experts say<br />
- The real gem (har har) in the Ruby and Rails space is the community itself<br />
<span id="more-32"></span><br />
Now for the longer version:</p>
<p>It&#8217;s hard for me to be objective since I only started programming in Ruby in February and started using Rails in April, but the language and framework don&#8217;t strike me as tedious or kludgy at all. I&#8217;m definitely enjoying Ruby and making use of its fancier language features, all of which seem to actually work as advertised without any hideous gotchas when you actually try to do something slick.</p>
<p>I particularly enjoy the way Ruby&#8217;s collections allow you to write in the style of a functional language; have a look at the <a href="http://www.ruby-doc.org/core/classes/Array.html">Array</a>, <a href="http://www.ruby-doc.org/core/classes/Enumerable.html">Enumerable</a>, and <a href="http://www.ruby-doc.org/core/classes/Hash.html">Hash</a> classes to see what I mean. It&#8217;s possible to write extremely compact code that morphs a collection into something very different, but without the inscrutability of Perl.</p>
<p>Compared to my experience with mainstream Java and J2EE, I certainly don&#8217;t miss Tomcat, Ant, Struts, or JSP Expression Language. (Instead I&#8217;m using Mongrel, Rake, Rails, and ERB.) That&#8217;s not Java&#8217;s fault, and could be alleviated by just picking better tools and frameworks at the start of a project. I don&#8217;t miss Hibernate but I don&#8217;t have any gripes about it either.</p>
<p>There are features in Java 1.5 that are helpful in alleviating some of the annoyances of programming in Java, but because these are new features, the vast majority of library code in the wild doesn&#8217;t use them (similar to the problems with OO being bolted onto Perl and PHP). Also there are political and business deployment roadblocks to using the latest technology: just because you can download an official release of something and it works perfectly for your code, that doesn&#8217;t mean that you necessarily have permission to deploy that technology stack onto production servers. Big organizations take years to officially support new releases, so you may be stuck developing against 3 year old products and APIs.</p>
<p>I&#8217;m not trying to troll for Java vs Ruby comment flames here. My point is just that Ruby has had features for a relatively long time that Java is just recently adopting (or simulating), and that&#8217;s important for more than just petty bragging rights; a feature that&#8217;s unavailable to you for your own org&#8217;s political or financial reasons might as well not be there at all. (Or maybe it&#8217;s worse, if it makes you bitter about your own work environment: &#8220;I have to write all this ugly stupid code because Bob is afraid to upgrade the server&#8230; grr.&#8221;)</p>
<p>I can remember quite a few times when I painted myself into a corner in Java and had to write lots of type casting / checking / converting code, or had to try and work around single inheritance using composition and lots of boilerplate proxy methods, or really wished java.lang.String weren&#8217;t final so I could subclass it, etc. Ruby feels a lot more like Perl or JavaScript than Java when it comes to being able to do whatever you want when you&#8217;re sure you know what you&#8217;re doing, and being able to write weird fancy code that magically makes everything that calls it become dead simple.</p>
<p>I used to be horrified at the idea of messing with somebody else&#8217;s classes (as is done by <a href="http://require.errtheblog.com/plugins/changeset/221">Hash.slice</a> from will_paginate, which I swiped all by itself since I don&#8217;t really need will_paginate), but I&#8217;m finding that the apocalypse I feared just isn&#8217;t there. If you do something wacky, like add a new method to String, the world doesn&#8217;t collapse. Or maybe it does, and you decide not to do it that particular way; just do something else. ActiveSupport adds all kinds of stuff to base classes like String, and it&#8217;s OK. Example: <a href="http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html">ActiveSupport::CoreExtensions::String::Inflections</a>.</p>
<p>I&#8217;m still adjusting to using a dynamic language: not uber-checking arguments and state all the way down a method call stack (oh no! is it nil?), not locking down everything so it can only work the way I planned, etc.  In most cases, the Ruby equivalent of a NullPointerException is fine. I think this is because the built-in error message includes the type and method you were trying to call, so you can usually just read that and see what you did wrong. The only time you&#8217;d want to prevent that is if you bury that error deep in your own code, so that the caller would have no idea of what they did that led to it. I&#8217;m finding that I&#8217;m OK with writing less paranoid code, because the failure will still happen, and be suitably clear in its cause, without my explicitly checking for it.</p>
<p>An issue with Ruby and Rails is that the official documentation is limited. It&#8217;s imperative to have 2 or 3 books on hand at all times, in addition to the RDoc Rails documentation. I own three of the Pragmatic Programmer books: <a href="http://www.pragmaticprogrammer.com/titles/ruby/">Programming Ruby</a> (the &#8220;pickaxe book&#8221;), <a href="http://www.pragmaticprogrammer.com/titles/rails2/index.html">Agile Web Development with Rails, <b>2nd Edition</b></a>, and <a href="http://www.pragmaticprogrammer.com/titles/fr_rr/index.html">Rails Recipes</a>. Just looking at generated API documentation won&#8217;t tell you how you&#8217;re supposed to use libraries.</p>
<p>The reverse way of looking at that need for documentation is symbol lookup. Rails does some pre-including of library and framework files before loading the application file you&#8217;re working on, so unlike Java, you don&#8217;t have a mandatory list of imports at the top that tell you where every class you&#8217;re working with came from. There are some symbols and functions you can call from instances of particular classes, and they came from somewhere but it&#8217;s not obvious where, at least when you&#8217;re starting. A good IDE with &#8220;find declaration&#8221; could fix this, but initially it&#8217;s daunting: &#8220;what are *all* the options for this method?&#8221; &#8220;Where is this method defined, even?&#8221; etc. This is where the books are less useful and API documentation can help.</p>
<p>I&#8217;ve also subscribed to a couple dozen RSS feeds that help me keep up with what the really slick Ruby and Rails people are using, writing, struggling with, etc. Chief among them is probably <a href="http://errtheblog.com/">Err the Blog</a>. The <a href="http://podcast.rubyonrails.org/">Ruby on Rails podcast</a> is helpful also.</p>
<p>As for productivity, here are 4 specific time-savers I&#8217;ve found:</p>
<p>1) TextMate, which is very slick. There are Windows equivalents, though from what I&#8217;ve heard, they&#8217;re not 100% as good. Point is, a text editor that understands Ruby is critical, and if it helps you jump around in a big tree of files, that&#8217;s very helpful.</p>
<p>I&#8217;m an Emacs devotee, and TextMate is far better for Ruby and Rails. It&#8217;s hard to explain, but let&#8217;s just say that TextMate is much deeper and more featureful than it appears at first glance.</p>
<p>I looked at NetBeans which is pretty close to being a very smart Ruby &#038; Rails IDE, but it was still suffering an identity crisis (am I a Java IDE? or a multi-language thing?) that cluttered the UI badly. This is a hot area of innovation right now so any week now TextMate might be eclipsed (or Eclipsed, har har) by something more full-featured. There are a few other options but I didn&#8217;t see anything that led me to believe a multi-hour or multi-day eval would be worth it.</p>
<p>2) Locomotive. It&#8217;s like MAMP or WAMP or any of those all-in-one application stack installers, except it gives you a working Rails environment. I set up PostgreSQL separately thru MacPorts (a cousin of the FreeBSD ports project), which was somewhat tedious but decently documented.</p>
<p>Getting all the Ruby and Rails stuff compiled from source is no picnic, and frankly unnecessary. On Ubuntu there&#8217;s a gotcha: the Ubuntu people and the RubyGems people can&#8217;t agree on a file layout, so Ubuntu&#8217;s rubygems package sucks. It&#8217;s better to install Ruby using apt-get and then install gems manually from the tarball.</p>
<p>3) Rails Plugins. There&#8217;s a lot of stuff being built on top of Rails and then improved day by day, and svn-over-WebDAV is the popular sync protocol. There&#8217;s a tool called Piston that helps you manage this. Anyway there&#8217;s a lot of stuff that is hard to do and commonly needed which is available in plugin form.</p>
<p>4) ZenTest, and more specifically, Autotest. It watches your source tree and runs only the tests in your test suite that need to be run based on what has changed; it&#8217;s the dynamic-language version of the incremental compilation that&#8217;s present in any good Java IDE.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pervasivecode.com/blog/2007/07/05/impressions-of-ruby-on-rails-from-an-ex-j2ee-developer-me/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

