Finishing Story One
Don’t forget the Simple Design and Testing Conference! It’s not too late!
Cards and Letters
One of the best things about writing these articles is the mail we get from people offering feedback and ideas.
Ruby Slow on Ron's Computer: Solutions???
Remember the basic story: Chet’s laptop, and mine, are comparable in nominal performance. For a number of benchmarks we have done, they are almost exactly equal in performance. Rails is incredibly slower on mine; the Ruby unit tests are some 15 times slower on mine. I’ve been whining here and on the Ruby list, hoping for some useful solutions.
The word “solution” doesn’t seem to mean the same thing to all of us:
- Mr C suggests that I should ditch Ruby and convert to Netbeans and Jruby. Seems like a lot of new software to me.
- Mr. M suggests that I should ditch my PC and get a Mac. My PC is a tablet PC, and I use the tablet facility.
- Mr. O suggests that if I were to run Linux on my PC, everything would be better. Well, except for the Tablet capability, which he wasn't aware of.
These are all interesting ideas. I have a couple of thoughts of my own that would probably make this problem go away:
- Ditch this computer and buy a new Thinkpad Tablet. Odds are it wouldn't have this slowdown.
- Format the hard drive and reinstall Windows XP Pro (Tablet Edition). Odds are this would fix whatever the slowdown is.
None of these are guaranteed, of course. We all know that stuff happens.
More importantly, however, none of these is actually a very satisfactory solution to the problem. The computer works fine for most things: it just doesn’t run Ruby and Rails at all well.
When your car runs poorly, the best solution probably isn’t to get a new one. When your spouse has a headache, the best solution probably isn’t a divorce. And if thine eye offend thee, my advice is to get glasses, not pluck it out.
Solutions need to be in proportion to the problem … and they need to actually be based on an understanding of the problem and why the solution works. When the IT guy comes in and formats your hard drive, your computer will probably work again. But he didn’t solve the problem. When your network crashes and you unplug everything and plug it back in again, it may work. But you didn’t solve the problem.
I’d like to solve the problem, that is, to understand what is causing it, and then fix that. If I can’t do that, then I would like to make changes that are more or less proportional to the problem. I’m not comfortable with replacing everything on the machine, or replacing the whole machine. It seems like a lot compared to the size of the problem. Here’s what I’m thinking:
- Measure and Triage: I've put some time hacks into the ruby test we're running, to see if it suggests anything. So far nothing really conclusive, though I have found one line in the tests that runs for 15 seconds (it is calling the Ruby compiler to process a line of code that processes a file that I believe to be short). Might compare that on Chet's machine to see what it tells us. I've brought down a Filemon program at someone's suggestion and have discovered that the ruby test does over 65000 I/O calls. Might run that on Chet's machine and see if he gets a different number of calls, or if their individual speeds seem quite different.
- Judicious Changes: I've installed Instant Rails three times now with slightly different options and no change. I might install follow the instructions in Instant Rails to upgrade my Ruby. I might remove Ruby from under Instant Rails and install it separately.
- Clean the Machine: It seems likely that there is something running on my machine that is causing trouble. I've downloaded some anti-spyware tools and a registry cleaner. They are finding lots of things to complain about. Cleaning the machine is probably a good idea anyway.
These things seem more in proportion to the problem than the various tactical and strategic nuclear options people are proposing. Of course what I’m really hoping for is for someone to say “Oh, I had that happen, and it turns out you need to set the -fast option in MUMBLEOPT.”
*** Breaking News: It's ALIVE!!! ***
At the suggestion of Mike Dwyer, I downloaded the UniBlue Software tools, a registry cleaner, and anti-spyware thingie, and such. I ran them last night. They found a number of unlinked files and such, plus over 800 problems in the registry. The software isn’t too transparent about what it is going to do, but it can back things up, so I just let it rip.
Today I wanted to compare Chet’s machine with mine, so I had him download the filemon software and run his tests. He showed about the same number of file accesses as I had, around 65,000. But his file accesses all seemed to be about ten times faster than mine, typically 0.0000x seconds where I had 0.000x. Wow. To compare real figures instead of my memory, I started filemon on my machine and ran again.
The ruby tests now run correctly on my machine, including my tracing output, in just under 23 seconds. They take 29 seconds on Chet’s machine. Perhaps more interesting is the fact that now they only require about 25,000 I/Os rather than 65,000. It appears that my individual I/O calls are a bit slower than Chet’s. Maybe his hard drive is faster than mine, but we think his RPM, at least, are less.
So the problem is gone. Was running UniBlue a “solution”? Not according to my standard of understanding what was actually wrong, since it just nuked everything it found and didn’t predict results. It’s interesting that the total number of I/Os is so much lower. Something about bad things in a path somewhere? Don’t know.
What I do know is that running some system cleaning software seems more in proportion to me than switching my entire life over to Linux or Mac. I realize I’m missing out, but hey.
Thanks to everyone for ideas, and I might still try a Mac one day. And thanks, especially, to Mike, for a small idea that worked. I wonder if that has anything to do with agility?
How Many Hours Are There In a Session?
Mr R writes that he hates the way we record our time. He says that we worked Monday thru Friday on the project and then reported that we had surely spent less than eight hours on it. “That’s rubbish,” he suggests. “If you and Chet pitch up at the coffee shop and work for some part of the morning, you have spent 1/2 day each on the project.”
Well, it’s an interesting viewpoint. Chet and I each charge a daily rate for consulting and training. Suppose we agreed to do a five-day training course for you, and each day we showed up for two hours in the morning. Would you pay the full daily tab? If so, please email me immediately. No, on second thought, don’t. I’m more concerned about customer satisfaction than I am about getting paid a day’s pay for a couple of hours work.
In any case, what we do is measure our estimates in sessions, which are a couple of hours work at a bookstore, coffee shop, or the like. We report what happens, and how long we actually work, because we think that that’s closer to useful information than something like the elapsed days from start to finish on the project. We try to be clear about what we do and how long it takes, and our readers should feel free to translate those raw figures into whatever standard kind of report they would like to view.
Right now, we think we have about a dozen hours of experience actually working with Rails right now, even though it has taken a couple of weeks to get it.
Mr R says that he does enjoy the articles, and we hope that he continues to, and that you all do. Take what you find of value in them, and ignore the rest. And thanks!
A Bit of Railing of Our Own
Our main software page, as shown again below, has a button for a new tool, left over from the automatic generation of the page. The second half of our story says that we are to put in a page for adding a tool. We explore how that button works, and find that it is doing the action “new”.
The existing controller code includes lots of Rails-generated code, including some for “new”:
class SoftwareController < ApplicationController
def index
list
render :action => 'list' #this is the name of the view file, list.rhtml
end
# GETs should be safe (see https://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }
def list
@tool_pages, @tools = paginate :tools, :per_page => 1000
end
def show
@tool = Tool.find(params[:id])
end
def new
@tool = Tool.new
end
def create
@tool = Tool.new(params[:tool])
if @tool.save
flash[:notice] = 'Tool was successfully created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end
def edit
@tool = Tool.find(params[:id])
end
def update
@tool = Tool.find(params[:id])
if @tool.update_attributes(params[:tool])
flash[:notice] = 'Tool was successfully updated.'
redirect_to :action => 'show', :id => @tool
else
render :action => 'edit'
end
end
def destroy
Tool.find(params[:id]).destroy
redirect_to :action => 'list'
end
end
The implicit behavior of Rails is to run the “new” method, then link to the page named “new.rhtml”, which currently looks like this:
<h1>New tool</h1> <P>This is new.rhtml</P> <P>Blah blah type in the info for your tool. Begin your email with mailto:// and your link with https://</P> <% form_tag :action => 'create' do %> <%= render :partial => 'form' %> <%= submit_tag "Create" %> <% end %> <%= link_to 'Back', :action => 'list' %>
The page itself looks like this:
The page has the right basic idea, but doesn’t refer to all the fields of the set. We think it was generated, usinc scaffold, prior to adding the most recent fields. The render method uses :partial => ‘form’ to reference in the fields, and the _form.rhtml file contains the form part. We edit that file to:
<%= error_messages_for 'tool' %> <!--[form:tool]--> <p><label for="tool_category">Category</label><br/> <%= text_field 'tool', 'category' %></p> <p><label for="tool_tool">Tool Name and Description</label><br/> <%= text_field 'tool', 'tool' %></p> <p><label for="tool_tool">Tool Site Link</label><br/> <%= text_field 'tool', 'tool_link' %></p> <p><label for="tool_author">Author Name</label><br/> <%= text_field 'tool', 'author' %></p> <p><label for="tool_author">Author Email</label><br/> <%= text_field 'tool', 'author_link' %></p> <!--[eoform:tool]-->
And now the “new” page looks about right:
Entering data into this page adds a record to the database. Our first story is done. It’s awfully rudimentary but that’s OK because that’s how we wrote it. Our approach to stories is always like this, even if the story itself is larger. First we push through to having the thinnest possible functionality across the board, then we refine it. When we have the option, we write the stories that way, coming up with refinement stories as we see what has been accomplished so far.
Review and Discussion
Chet and I have the habit of reviewing what we have done at every opportunity and discussing what went well and what did not. I’ll hold back some of the generalizations for a moment, in favor of a more specific discussion. Chet observed that our first work with this new model, after the tutorial walkthrough, generated the standard automatic list page and edit page, as well as a page for “new” and an action for “destroy”. These pages are in a section we called admin. Here’s the admin list page:
And this is the page that comes up when you press “Edit”:
Chet pointed out that if we could make the list page come up on just the user’s own items, then we could use these pages almost intact to satisfy our current story, and the upcoming ones about editing and deleting as well. We talked a bit about how we could link from the existing user pages to the admin pages, and we’re sure there is a way to do that, and we almost know what it is.
However, it seems to me that a better design is likely to result if we just throw away everything we have done, and regen from the beginning, with this option in mind. If this had been a week’s work, done over the course of a week, I’d be reluctant to do it over. But in fact it is the work of at most a dozen hours, and I’m guessing we can do it over in one or two sessions. I’m going to suggest that tomorrow.
Overall Reaction to Rails and the Agile Web Development with Rails Book.
I’m not happy. Chet is happier than I am, or more inured to discomfort, but he’s not happy either.
We have an application that is doing what we want, and we are sure that we can bang the pages into submission with no difficulty. However, we don’t feel that we understand what we have done. We have gone through the cookbook approach, and we can go back to any given page and its files, and, knowing what we do about Ruby and HTML, and with an occasional reference to the book, we can make what should happen actually happen.
But we don’t understand what the application really is or how it really works. We have to keep looking around and digging around, and we only know just a very few bits of syntax to make things happen. We are particularly fuzzy so far on how parameters are passed around, and how one page links to another.
Now we really have only been working with this thing for a few hours, and probably any other tool would be equally opaque at this time. But Rails feels to me as if it is intentionally opaque. Frameworks are often like that.
On the other haned, it seems that Rails can do the app for my web site, without our ever understanding anything. Proceeding in that way, we’ll understand the methods and approaches we get exposed to, and will not have much depth. On the bright side, we’ll get our app done quickly. On the dark side, we’ll have no real sense of how well Rails will help with things that are substantially more complex than this.
We have no conclusion for now. We’re only very lightly experienced with Rails, and we can write our app. That’s good. We’re uncomfortable. Maybe that’s good too. For now, the big fools will press on.
Starting Over
Talking with Chet Tuesday morning, I mentioned the notion that if we had proceeded in a slightly different way, the Rails-generated default pages might well have been directly usable in our app. We talked briefly about moving them into the main “software” space, but he immediately reached the same conclusion I did: we’re going to start over.
If we were looking at a week’s work, I might hesitate. But we could do what we’ve done in two full work days, if not in one, and we’re sure it will be better and that we’ll understand better. The rest of Tuesday’s session was spent writing this article, and listening to odd music, such as the Heartless Bastards, over in the Borders music department.
We’ll start over tomorrow, this time on my computer. Stay tuned.
And it’s not too late to decide to go to the Simple Design and Testing Conference. We’ll pair with you, or debate you, whichever you prefer.