Posts from def euler(x); cos(x) + i*sin(x); end...
Posted by brian 3 days ago
If you’re headed to OSCON 2008, I hope I’ll have a chance to meet you. I’ll be speaking on Thursday afternoon, something about Ruby performance. Come and heckle me if you wish. Here’s the talk details:
Also, please do come check out FOSCON. This is the 4th year for FOSCON. w00t.
UPDATE: Thanks to all who attended my talk. I’ve uploaded the slides. If you attended, please take a moment to send feedback.
Posted by brian 69 days ago
There’s a lot of things that Rubinius, MatzRuby (including YARV), JRuby, IronRuby, MacRuby, Ruby.NET, MagLev don’t agree on. But that’s ok, because above all, they seem to agree that Ruby is one awesome language. And lately, that apparent agreement has gotten a boost of sorts.
Earlier this week, Rubinius (an Engine Yard project) announced the RubySpec project at rubyspec.org. The effort to write an executable specification using RSpec-style specs started with the Rubinius project in late December 2006. Since then, many people all over the world have contributed to the effort, including core folks from JRuby. Engine Yard has been financially supporting significant development of the RubySpecs since hiring Evan in June 2007 and other full-time developers (myself included) in Jan 2008. All this effort has been to ensure that the Ruby programming language continues to evolve and receive the recognition it deserves.
Another recent development has been a regular meeting of folks working on various Ruby implementations. These Ruby design meetings are bringing together folks to discuss tough issues with Matz and everyone else.
Well, after last night’s meeting, Tanaka Akira (sorry, I don’t have a link to his website; if you do, please let me know) checked in some changes to the ruby-core Makefile to fetch and run the RubySpecs. This is a very proud moment for me.
If you love Ruby, it doesn’t matter what color shirt you wear, what language you play with, or what country you live in. You can play a valuable role in helping make Ruby a wonderful language for everyone. Please help us with the RubySpecs.
Update: I changed the link to the changeset for the Makefile. Thanks Michael.
Posted by brian 87 days ago
All the attention that the various Ruby implementations are getting these days is a wonderful thing. Competition and lots of people trying out different ideas is a win for everyone. That said, there are still the silly human issues of ego and vested interest, always exacerbated by tossing some green into the mix.
I would definitely assert that JRuby is one of the more impressive stabs at a Ruby implementation. And we have, in large measure, to thank Charles for that. But, at the same time, Charles can write FUD like the best of them. I haven’t made it through the whole article yet (it does ramble on a bit), but I should point out a couple things.
Method dispatch is hard to get fast in Ruby, no matter what. Substitute a VM for an interpreter, C# for C for Java, whatever. And if you read carefully about what Charles is pinning his hopes on for the future of JRuby, it is precisely optimizations in the new JVM for better method dispatch. Rubinius will address these issues for sure. But instead of working on this with something like 143,866 lines of Java code, we have something like this: In the new C++ VM (which is not yet complete but substantially implemented), we have 12,619 lines of C++, and in our kernel directory, we have 23,882 lines of, what now, oh, right Ruby code. What you might miss when you think about the 143,866 lines of Java code is the several hundred thousand lines of C++ that make up the JVM. Hmm.
So, ultimately, Charles hopes to make JRuby fast using the same basic techniques that Rubinius does and will use. Except, it seems he’d rather use a 747 passenger jet to mow his lawn, rather than a comfy John Deere riding mower that your average small engine enthusiast can tinker with when something goes awry.
Seriously, the “Ruby in Ruby” meme must not die. It is an inspiration to a lot of folks and, most importantly, it has great promise. Press Charles on the issue and he will admit he’d rather have more of JRuby written in Ruby. I sense something of “bitter-gate” in Charles’ post. We don’t cling to Ruby because we can’t write C#, C, Java, etc. We don’t just like Ruby when it’s fun and fashionable and hyped. We are demonstrating that Ruby can be sanely implemented and push the state of the art for the language forward.
The C VM (named shotgun) was not our last word. Nor is the next generation C++ VM. They are both pragmatic steps toward a higher goal. And, let’s be very clear. We have not recently implemented a bunch of core methods in C. I’ve done two major pieces of rework recently that introduced a number of primitives (chunks of C code that access the VM directly). One was LookupTable, which was written in C because it is used heavily in the VM. However, it is exposed to Ruby code as well because, oh yes, we write a ton of stuff in Ruby, like stuff related to method and constant lookup. LookupTable acts a lot like a Hash, but separating it from Hash actually made Hash more clear and enabled writing even more of Hash in Ruby.
Another piece of work was optimizing some of String’s methods. You can see the performance enhancements in this ticket. I did introduce a couple new primitives in this rework, mostly to make a more sane set of composable primitives that were useful in many String methods. Primitives are a necessary fact of life in this composite implementation. Something has to bridge Ruby and C/C++. Also, by using a well-defined set of primitives, it makes it very easy to take our Ruby core libs and run them on something else. Ask Charles and he will tell you this. And if we write a little C/C++ to get the performance of a large number of Ruby methods up to par, that’s a huge win.
So again, the “Ruby in Ruby” meme is really important. Don’t let it die. And don’t let Charles tell you otherwise. While he can make snarky comments about our C/C++ VM, he should really look at his own kettle of 143,866 lines of Java code plus hundred thousands more lines of C++ JVM. The goal is a first-rate, powerful, extensible, approachable implementation of Ruby. Everyone in the Ruby ecosystem is contributing to that in various ways. Rubinius just seems to be putting the best pieces together, if I do say so myself.
Posted by brian 189 days ago
This day has been a long time coming. About a year ago, I started trying to get Rubinius to run RSpec. Hats off to all the wonderful Rubinius contributors and special mention to the cool guys who hung out with me at pdx.rbc meetups in early 2007. (Unfortunately, the page in that link will disappear soon. Maybe I’ll make a pdf out of it and keep it here. You know, nostalgia.)
Everyone’s efforts have paid off and here is the proof:
$ shotgun/rubinius -I ../rspec-1.1.2/lib/ ../rspec-1.1.2/bin/spec spec/ruby/1.8/core/true/
.....
Finished in 0.988572 seconds
5 examples, 0 failures
The TrueClass specs were some of the very first ones I wrote, so I thought it fitting those be the first ones I ran successfully with RSpec.
Congratulations everyone!
Posted by brian 189 days ago
I’m going to be pedantic for a minute. If you are Betrand Russell, feel free to spend your time more productively. Everyone else, don’t be afraid of a few symbols.
If you read my last post, you might be inclined, as is every human mind, to reduce all those words to something simple you can put in your back pocket (maybe take it out later and show it to a friend). Perhaps something like this:
Immutable == Security == Good
If you do that, you might get lots of nods and a fair bit of affirmation from folks. Makes perfect sense, right. You can make all sorts of analogies that prove this to you. Consider my front door, if it’s not easily opened, I feel more secure. Perfect. Must be true.
It’s not. Things are not so easily distilled into such nifty little boxes.
Now, once they have this shiny, handy, palm-sized summary in their back pocket, folks tend to go the extra mile. They decide to make one of the most fundamental logic errors. Essentially, trying to think all the way around this hairy problem, they decide:
If Immutable == Security
Then Not Immutable == Not Security
Doh. That’s where this contra thing comes in. Read the gory details on Wikipedia, but here’s the summary:
In logic, something like A -> B is read “A implies B” or “if A then B”. It is very tempting to then think, “if not A then not B”. Unfortunately, that is not generally true. Given “A implies B”, the statement “if not A then not B” is called the inverse. Again, these are not generally logically equivalent. The statement “if not B then not A” is called the contrapositive, and it is generally true that a statement and it’s contrapositive are logically equivalent.
Applying this to the above, we can see that IF (a very big if) it is true that “if Immutable then Secure” is true, then the statement “if not Secure then not Immutable” is equivalently true. However, it has not been demonstrated that immutability is equivalent to security. And indeed there are numerous ways to achieve “security” (a word that begs precise definition) in a variety of different systems.
So, before you start touting something like Java because it is statically typed, immutable and “secure”, consider whether you are making the mistake of confusing the inverse for the contrapositive. If you’re feeling extra nimble and up for some mental gymnastics, consider this rather hyperbolic assertion:
Ruby is a very, very sharp knife. Java is a little more like a butter knife. We safely leave butter knives on the table when the kids are around. But, we probably grumble more than a little when trying to cut our steak with a butter knife.
If we want to make Ruby “safer”, it’s possible to do so in the same manner as dealing with sharp knives: we make something like a sheath. We don’t just take a hammer to the blade and dull it.
Posted by brian 189 days ago
The first post I read by Evan about Rubinius had a quote about evil built in. Of course, that caught my eye. What was Evan’s point? Legend has it (I wasn’t there) that during Q&A someone asked about fundamental aspects of the Rubinius system being available for modification from normal user code. The issue was raised that perhaps something should restrict that unlimited power. Evan’s response was that Rubinius sorta has evil built in. Usually, that’s a good thing.
In fact, it’s a very sharp double-edged blade. We all cherish the dynamic nature of Ruby when it allows us to do useful things. For example, the following works great in MRI:
class Fixnum
alias / quo
end
That little snippet and you’ve redefined fixed-point math to return a floating point number. That gem is one of the core pieces of the Mathn library in the Ruby standard library collection. Together with the Rational library, you can do some cool stuff:
$ irb
>> require 'rational'
=> false
>> require 'mathn'
=> true
>> 1 / 2
=> 1/2
>> 1 / 2 + 3 / 8
=> 7/8
Combine that with Matrix and Rational and you have at your disposal some pretty powerful tools for doing more realistic mathematics. Take a look at what some folks do with it.
Fortunately, and unfortunately, Rubinius is very different than every other implementation of Ruby that I’m aware of. Rubinius follows the Smalltalk model and uses the Ruby language itself to build the implementation. That means that Array, for instance, calculates values for its internal operations using none other than the same Fixnum values that you use in your Ruby code. So, what happens when we redefine Fixnum#/ to return a Float instead?
Yes, you guessed right. Things work differently. In fact, not at all.
Since we’re not about to rescind the promise of a better Ruby, we have to figure out some way to deal with this. There are several approaches possible. One would be to code all of the core library with a different set of numeric classes, say BasicFixnum and BasicBignum, that are superclasses of Fixnum and Bignum. That would be really cumbersome. Another approach would be to use different methods in the core library. Again, cumbersome. So, this sounds like there are some basic goals we have in mind. In fact, there are. We want to keep the core library code as simple as possible and provide the full power of Ruby at every level, to the greatest extent possible.
This isn’t necessarily the ultimate approach we’ll use, but I checked in some code today that leverages a very slick feature that Evan built into the compiler. I created the following compiler plugin:
class SafeMathOperators < Plugin
plugin :safemath
MathOps = {
:/ => :divide
}
def handle(g, call)
name = MathOps[call.method]
if name and call.argcount == 1
call.emit_args(g)
call.receiver_bytecode(g)
g.send name, 1, false
return true
end
return false
end
end
Essentially, what this does is map any calls to the #/ method to the #divide method. I’ve changed the core library classes Fixnum, Bignum, Float, and Numeric to handle this. So, the code in core looks the same, but is protected from the redefinition that the Mathn library performs. The compiler plugin is activated with the -frbx-safe-math switch only when compiling the Rubinius core libraries.
UPDATE: Note that you do not have to do anything differently. The compiler flag is passed in automatically when you type rake to build the Rubinius libraries. If you are writing user code, you also do not need to do anything differently. You just write your code as you normally would. If you require the Mathn library, 1 / 2 => 0.5. If you also require the Rational library 1 / 2 => 1/2. Invisible, maybe even a little evil.
Again, this is not necessarily the way we’ll always do it. The lessons are:
- Ruby is a great, powerful language
- Rubinius makes Ruby even more powerful
- We can work around snags pretty dang easily, even if temporarily
Of course, we’re always learning. Any papers, systems, code, etc that you can point me to?
Posted by brian 201 days ago
I’m going to give this live blogging thing a go. As of 14:52 PST, Evan announced that Rubinius runs irb. It hasn’t landed in the repository yet, but this is great news. Just a little while ago, we started with an irb wannabe. I guess a lot can happen in a year.
Congrats to Evan and all the fantastic Rubinius supporters and contributors.
UPDATE: So, I’m not a very good reporter. There’s some other very big news related to getting irb working. Evan checked in a working eval yesterday. Enjoy!
Posted by brian 231 days ago
I’m hanging out this week at the Engine Yard office in South Park hoping to catch a glimpse of Cartman and pals (I wish!). You’ve heard it all before but I would be remiss to not toss in my congratulations to my new (very soon) colleagues. Evan, Wilson, Ryan, and Eric are a stellar group of folks and a great bunch of personalities to boot. I am honored and extremely happy to be working closely with them, as well as the fantastic group of contributors world-wide.
Everyone at Engine Yard deserves big accolades for the vision, daring, and execution in making all this possible. Here’s my opinion (and gauntlet): This is why it is always the little companies that do something great. I see Ruby in general and Rubinius in particular as a powerful antidote to insane lumbering companies that have foisted agony, fear, and self-loathing on legions of otherwise decent folks with their sharp, pointy brackets and stupidly limited language features. Bring your hungry masses to our shores. We have the very ambitious intent to build the best programming language and system to date. Hubris? We’ll see.
Oh yeah, but about this looking at your own eyeball without a mirror thing. Some of you may recall that I’ve been working a bit on writing specs for Ruby as part of this project. Since we could not run RSpec initially because of its extensive use of very advanced Ruby features, we wrote a minimal replacement for it that I affectionately dubbed mini_rspec. At the time I wrote this, we were converting a ton of specs from the early host/target architecture I started with. We may have been able to run miniunit at that time, but my intention was to write specs for mini_rspec as I went along evolving the features of the framework itself. This is a very difficult bootstrap process akin to looking at your own eyeball… you get the picture. So, I must say I’m solely responsible for this little gem:
require File.dirname(__FILE__) + '/../spec_helper'
# hmm, this is embarrassing
describe "mini rspec" do
end
Of course, I took a nice bit of friendly needling (or should I say snickering) from Ryan for that one. But let’s not dwell on the sordid details of the past. Currently, in my branch I have a rewritten (and renamed) mSpec. This is a little better:
euler:rubinius brian$ spec mspec/spec
.................................................................................................................................................................
Finished in 0.062927 seconds
161 examples, 0 failures
That’s what I’m talking about. This time, I wisely just used existing RSpec to write the specs because my goal is not necessarily to be able to run the mSpec specs with mSpec, but to be able to evolve the system while still keeping layers of it so simple that nascent Ruby implementations will actually be able to use it.
A final word about the other approach. We wrote thousands of specs for Ruby using mini_rspec. We ran these specs against MRI 1.8.6 and they behaved as expected. So, those specs were essentially an indirect spec for mini_rspec. The challenge of that approach, of course, is that you do not have a simple and clear way to observe the impact of changes you make to the mini_rspec system. Anyway, I should finish up this massive bunch of changes very soon and push it out.
Posted by brian 309 days ago
In the last post, we saw a nice use case for the #send method. Now, we’ll see some coolness that Rubinius adds. First, some code:
class Apple
def seed
end
end
a = Apple.new
a.send :seed
a.__send__ :seed
Now, with the convenient and useful describe facility of the Rubinius compiler, we can see something interesting:
$ shotgun/rubinius describe send.rb
Path: send.rb
Size: 79 bytes
Sexp:
[:block,
[:newline, 1, "(eval)",
[:class, [:colon2, :Apple], nil,
[:scope,
[:newline, 2, "(eval)", set_local_fp 1 ; local a
---- snip ----
pop
#line 8
push_literal 1
get_local_fp 1 ; local a
send send 1
pop
#line 9
get_local_fp 1 ; local a
push nil
push_literal 2
dup
is_symbol
git send_lbl1
send to_sym 0
send_lbl1:
push 0
set_args
send_off_stack
pop
push true
ret
---- snip ----
I’ve truncated that output, but feel free to run this at home. (There’s no long lasting side effects other than an itching desire to contribute to the Rubinius project.) If you correlate the assembly with the line numbers in the source, you’ll notice that the two sends are not turning out to be the same. That’s right. We have a special, and fast, __send__ operation.
The #send method is a highly useful bit of Ruby. Unfortunately, there’s some concern that using it can hurt performance. Well, with Rubinius you can have your send and use it, too.
Posted by brian 309 days ago
Over at the Rubinius project, in between hatching plots to take over the world, we fit in some time for recreation. For example, we’ve got this masochistic interest in writing RSpec compatible specs for the Ruby core library. One of the challenges there is the large number of aliased methods that Ruby has. Using RSpec’s shared behaviors as an example, I’ve created a flavor of shared behaviors in our mini_rspec implementation. As the code below shows, this makes it straightforward to spec all these aliases.
hash_store = shared "Hash#store" do |cmd|
describe "Hash##{cmd}" do
it "associates the key with the value and return the value" do
h = { :a => 1 }
(h.send(cmd, :b, 2).should == 2
h.should == {:b=>2, :a=>1}
end
it "duplicates and freezes string keys" do
key = "foo"
h = {}
h.send(cmd, key, 0)
key << "bar"
h.should == { "foo" => 0 }
h.keys[0].frozen?.should == true
end
it "duplicates string keys using dup semantics" do
# dup doesn't copy singleton methods
key = "foo"
def key.reverse() "bar" end
h = {}
h.send(cmd, key, 0)
h.keys[0].reverse.should == "oof"
end
it "raises TypeError if called on a frozen instance" do
should_raise(TypeError) { hash.send(cmd, 1, 2) }
end
end
end
describe "Hash#[]=" do
it_behaves_like(hash_store, :[]=)
end
The very cool thing about this is how useful Ruby’s send method is. And in Rubinius, it gets even cooler, as you’ll see in part II
Posted by brian 311 days ago
Last week, Evan Phoenix, Wilson Bilkovich and I met up in Denver (ok, near Denver) for some serious Rubinius coding, aka a sprint. Charles Nutter (of JRuby fame) flew in just to hack with us for 15 hours straight and then flew back home. Very cool. When do you get collaboration like that from someone on a project that could be seen as a competitor? That’s some serious goodwill, folks, and much appreciated. Charles had his laptop out on the taxi ride from the airport digging into some issues we have with including modules. If you hang out in #rubinius, you know there’s a lot of collaboration occurring on different fronts.
This was only the second time I’ve had the pleasure to hang out with these folks in person. The sprint was intended to enable us to get some face-to-face time and work out some foundational issues, hopefully speeding other development and contribution as we head toward RubyConf07. Here’s a few things we accomplished (in no particular order):
- Evan hooked up Syck (the YAML parser) using our very cool subtend (Ruby C API compatibility) component.
- Wilson hammered out a bunch of StringIO specs in a couple hours.
- Evan promptly began writing a Ruby StringIO that passed the specs.
- Charles whipped out a bunch of
def and case specs, the latter being a serious beast to compile.
- Wilson added these wicked colorized backtraces that enable you to quickly pick out the ultimate failure line and some significant points in the backtrace.
- Wilson implemented the rest of the missing
case support in the compiler.
- Charles added some basic ObjectSpace support.
- I checked in a complete reorganization and a lot of fixes to our Ruby core library specs. We have around 2,800 specs, of which we’re passing over two thirds. We still have nearly 50% of the core library specs to complete.
- Evan fixed our Thread support and added some preemption.
- I added (with much help from Evan and some serious gdb sessions looking at x86 machine code) some coolness to our foreign function interface (FFI) to support reading and writing to C integers and doubles from Ruby. (The doubles support still needs a magic touch or two from Evan.) With that I was able to finish off our Math methods support and the rest of the Math specs.
- Wilson hammered out a ton of the machinery necessary to support compiling
eval. If you don’t realize how awesome (and painful) this is, don’t blame me.
- I started on an implementation of
File.fnmatch in preparation for Dir.glob (or dear glob is it is not-so-affectionately known to me) and cleaned up our fnmatch specs a bunch.
There’s more where that came from. For all the nitty gritty details, browse the git repository. There’s some cool stuff just over the horizon that we didn’t get to. Evan explained in more detail the architecture of our sampling profiler and our debugger support. Let’s just say you’ll be able to profile a Rails app in production with no significant performance penalty. And remote debugging is on it’s way. Seriously, let that sink in for a minute.
Interestingly, we did not consume 50 liters of coffee each and we had some incredible Japanese food one evening, thanks to a recommendation from one of Wilon’s contacts. Overall, I’m quite impressed with our progress and highly impressed with the technical prowess of these guys. The point it, Rubinius is quite accessible. It’s also some very cool and very real technology that’s going to make writing, running, living, breathing, and enjoying Ruby a lot better.
And last but not least, a big thanks to Sun for their sponsorship, and in particular Tim Bray for his advocacy. Rubinius is a small, ambitious project. But at heart, it’s very true to the value of making Ruby fun.
Posted by brian 311 days ago
At some point, you likely needed to grab some files and do something with them. You probably had a vague recollection about Dir[] from reading the Pickaxe book. To refresh your memory, you crack it open and fire up irb. Ah, easy…
irb(main):001:0> Dir['spec/**/*_spec.rb'].each do |file|
irb(main):002:1* puts file
irb(main):003:1> end
There’s no denying that Ruby makes this task dead simple. So simple, in fact, that you probably don’t think twice about how that nifty Dir[] method does its work. That is, unless you’re trying to implement it.
During the Rubinius sprint, I realized that having this in Rubinius would enable me to make our continuous integration spec runner much better. Now, I know that there’s a glob function in C that provides behavior similar to what you get in the shell using * and ? to match file names. There’s also a function fnmatch that wraps up some of that magic. No problem. We’ve got this nifty foreign-function interface (FFI) that Evan has graciously provided. Evan recommended I take that route first. Yep, took all of 10 minutes to hook everything up.
Of course, it wouldn’t be that interesting were this the end of the story. It’s not. Our fnmatch specs were mostly passing, but when I looked into the failing ones, I discovered something that I’d probably tried to shield my psyche from. Ruby implements its own fnmatch and glob functions. And when I say ‘implements’, it doesn’t really give you any idea of the pain and suffering involved. Do take a peek:
It doesn’t take but a minute to see that Ola Bini’s java code is extraordinarily more readable than the MRI source. But both are daunting to say the least. So, I’ve decided to take a different route.
def self.fnmatch(pattern, path, flags=0)
pattern = StringValue(pattern).dup
path = StringValue(path).dup
escape = (flags & FNM_NOESCAPE) == 0
pathname = (flags & FNM_PATHNAME) != 0
nocase = (flags & FNM_CASEFOLD) != 0
period = (flags & FNM_DOTMATCH) == 0
subs = { /\*{1,2}/ => '(.*)', /\?/ => '(.)', /\{/ => '\{', /\}/ => '\}' }
return false if path[0] == ?. and pattern[0] != ?. and period
pattern.gsub!('.', '\.')
pattern = pattern.split(/(?\[(?:\\[\[\]]|[^\[\]]|\g)*\])/).collect do |part|
if part[0] == ?[
part.gsub!(/\\([*?])/, '\1')
part.gsub(/\[!/, '[^')
else
subs.each { |p,s| part.gsub!(p, s) }
if escape
part.gsub(/\\(.)/, '\1')
else
part.gsub(/(\\)([^*?\[\]])/, '\1\1\2')
end
end
end.join
re = Regexp.new("^#{pattern}$", nocase ? Regexp::IGNORECASE : 0)
m = re.match path
if m
return false unless m[0].size == path.size
if pathname
return false if m.captures.any? { |c| c.include?('/') }
a = StringValue(pattern).dup.split '/'
b = path.split '/'
return false unless a.size == b.size
return false unless a.zip(b).all? { |ary| ary[0][0] == ary[1][0] }
end
return true
else
return false
end
end
This code is only passing 80% of our existing specs for File.fnmatch?, so the jury is still out. And I’m sure someone can make this much better. The lesson for me is that 1) Ruby’s implementation is typically not accessible (I already knew that), and 2) writing Ruby code is a good way to handle tough problems.
But then, you already knew that. ;)
UPDATE: I’ve changed the code here to reflect our current version. It’s now passing 100% of the existing specs.
Posted by brian 432 days ago
Looks like the RSpec folks dropped 1.0. Awesome! Congratulations!
Hmm, where’s the applause? This is the good shit. People should be knowing about this. So, as I sit here at RailsConf 2007 looking over the schedule, I’m not seeing any talks scheduled for BDD or RSpec. That’s regrettable. So, my goal will be to embarrass, cajole, entice, encourage (pick your emotional poison) you into trying RSpec. Not sure if it’s right for you? Try it. Not sure if it will work well? Try it. Don’t get it yet? Try it, already!
And while you’re trying it, think about this: How can descriptions of the behavior of a system form the common language that spans the spectrum of development from clients to developers. Do you think your clients care about how many def test_should_be_super_duper methods are in your tests? Why would they?
Would your customer care about something like this?
The Home page
- has an entry field for username labelled 'User name'
- has an entry field for password labelled 'Password'
- has a submit button labeled 'Log in'
- has a link to retrieve a lost password FAILED
1) The Home page has a link to retrieve a lost password FAILED
Do you think this could form the basis of a dialogue with your clients? Would it be easier to trouble shoot this over a client saying, “The lost password link doesn’t work.” Do you see how this could make everyone’s life easier?
Is this all there is to BDD and RSpec? No, not by a long shot. So… yeah, you guessed it. Try it.
Posted by brian 432 days ago
This post has no nutritional value. Feel free to put it over there by the jelly-filled pastry, bearclaw, and glazed pop tart, go back to your granola. You health nuts, you.
Now, to the jelly filling. Seems that _why dropped by #rubinius, not once, but twice yesterday. I missed it, but hopefully he’ll be back. For your viewing pleasure (no names have been changed to protect the innocents).
19:06 _why >> whoa
19:06 _why >> well fellows
19:06 _why >> i am blown away!
19:07 _why >> looks like things are really comin along
...
19:30 _why >> oh backflip
19:30 _why >> interpolation works, splat works, IO works
19:30 Vagabond >> spat is pretty new
19:30 Vagabond >> I think it's not completely tested
19:30 shadowfiend >> Yeah, like a couple of hours old :-)
19:31 Vagabond >> it's remarkable how much is actually implemented though
19:31 _why >> yeah it's got that new splat smell
Posted by brian 443 days ago
Well, not exactly. But here’s a nice anecdote that will give you pause then next time you sprint for the ^C escape hatch.
Yesterday, while compiling Subversion 1.4.3 from source on Ubuntu 6.06, I had invoked the command sudo checkinstall make install-swig-rb and, thinking it was going to overwrite my previous .deb package for subversion, hit ^C. Now that’s something I’ve done a million times, I’m sure. It’s the panic, “Oh shit, I don’t really want to do that” button. When you realize in a split second that there may be dire consequences from that ill-thought command, it’s a natural reflex.
But on that fine day, ^C left me with a root directory that had 700 permissions. The consequence was that nothing except a root shell could spawn. I couldn’t even su as root. Yeah, that’s right. Insane. And this was on a VPS. Lucky for me, Quantact has their Xen VPS setup configured so you can actually access a console remotely without needing to go through your VPS’s networking. Tim at Quantact took a look and suggested that the permissions could be causing the issue. He was right and boy, was I happy that’s all it was.
Most likely, something in checkinstall misbehaved, but needless to say, I didn’t try to reproduce the problem. Now, whenever I head for ^C there will undoubtedly be a microsecond pause to evaluate the relative merits. Hopefully, that won’t result in a Buridan’s Ass dilemma.
Posted by brian 444 days ago
The Dev’il is out; get it while it’s hot. What’s that? you’re wondering.
This is the story behind it. The Rubinius project (where The Best Ruby VM of All Time ™ is being built) had tried a couple project collaboration tools before Evan gave me the ok to try something different. My goal was a project collaboration tool that collected the relevant information in one place, making it easy to access and modify. Communication is key, so I decided to build on the excellent Beast forum.
The big question is: What is relevant information? I have some opinions about that. We have a liberal commit bit policy, which encourages a lot of participation. To balance that, we need to always stay on top of what is being committed. In my experience, that means RSS and graphical browsing of Subversion changes. We need tickets to track bugs. However, our tickets are super light. Basically, a ticket has a title, body, and status. A user can take a ticket to indicate that she is working on it. There are no comments, and no priorities. Tickets are versioned, so a user cannot destroy pertinent information. The ticket body should always be the definitive statement of the problem. No browsing through comments and attachments trying to figure out what is relevant. I’ll be writing more about the design decisions in the Dev’il docs.
I do owe a big debt to Trac , Collaboa, Devalot , Retrospectiva, mostly for showing me (especially Trac) what I did not want to do, which can be a great source of inspiration. The name itself came from a combination of pure frustration working on Devalot and Evan’s quote about rubinius having “a little evil built in”. It was mostly a response to the “alot” in Devalot. I wanted something much lighter and easier to understand and use. Anyway, if you’re offended by the name, it’s very easy to change: drop a file named project.rb in your lib directory that contains your project name.
The project is still under development. I’ve released the source because a few folks were clamoring for it. Drop by the Dev’il forums for features in the works and to offer up some feedback.
Posted by brian 470 days ago
That pretty much sums up my feelings about the majority of the interactive gadgets I encounter, soft or hardware. So, I’m delighted to have the good fortune of joining the talented folks at Needmore Designs. It’ll be a challenge to keep the code as beautiful as these designs, but using Ruby makes that a delicious challenge indeed.
One particularly generous perk for a company this size is that I’ll be able to spend around 20% of my time working on, I like to call them, “personal development” projects. Of course, I plan to contribute that to bettering the Ruby community. In particular, I’ll be spending a good portion on the Rubinius project. This alternative Ruby implementation aims to create an accessible, extensible, powerful, and fast virtual machine. We’re implementing as much as possible in Ruby and we have a lot of very cool things either implemented or in the works.
Not only will this project contribute to Ruby being more suitable for a wider variety of computing tasks, but using rubinius will actually be great for the environment, too! Far fetched? Nope. Our continual thirst for more computing power translates to increasing demand for energy. Any type of energy pretty much means some contribution of carbon to the already overloaded atmosphere. So, when rubinius runs your favorite Ruby applications and web 2.0 sites more efficiently, that reduces the required energy and that’s better for the environment. Ok, I’ve never made that pitch before but it’s a great reason join up and help out.
So, your moment of zen: not only has Needmore given me this great opportunity to work with talented design professionals, but they’re also contributing to a better environment. And if you treasure the abundance of green that we are privileged to have all around Portland, you know that’s a very cool thing. Around the circle goes.
Posted by brian 484 days ago
Eegads, how time flies. At the March 6th meeting of pdx.rb, I gave a short talk introducing BDD (Behavior-driven development) with a couple examples from RSpec. Since David Chelimsky has already done a terrific job writing an introduction tutorial, I decided to focus more on the big picture of BDD. My take is that BDD is some rather sweet glue that can foster collaboration across the spectrum of folks involved in software development, from clients to designers to developers to users. So far, we’ve got a lot of turf wars going on, and as in any war, there are casualties. In software there are crappy products, tortured users, unhappy developers, exasperated designers, cost overruns, and misunderstandings galore. BDD isn’t some magic salve that can be slathered on a messy process like butter on a toasty English muffin and make it all better, but I do believe it has promise.
So, here are the slides from my talk. (Right-click and Save As… Sorry, MIME types are not set right at the moment.) Unfortunately, in a tremendously idiotic move born of high stress, I deleted the original slides before I had uploaded them. Fortunately, I had some notes and a partial earlier draft, so I was (mostly I hope) able to reconstruct them. There is unfortunately no audio from the talk. As with most slides, these are marginally useful without it, but browse and feel free to ask questions.
There is one part that seems highly promising to me and easily attainable now. As you know, RSpec allows you to spec the views separately from the controller. This is a fantastic tool that interaction designers could use to communicate with developers. The syntax that an interaction designer would need to learn is fairly simple (most interaction designers are not developers), and you shouldn’t have much (if any) conditional code in your specs anyway (conditionals being one of the more difficult parts of programming to get right in my experience). The specs can accompany wireframes and provide another artifact of communication that bridges the different domains of interaction/interface design and development. Exciting stuff.
Posted by brian 526 days ago
For being a very young project (Evan’s been working on it about a year, but it’s only been in the public view for a few months), Rubinius has quickly hit primetime with the first (that I know of) FUD-ish review The basic premise is that pypy had money, minds, and at least one goal to produce a simpler VM than CPython, but as it nears 1.0 it’s much more complex than CPython. And since Rubinius is at least lacking in official monetary backing, it’s got a real tough row to hoe. Maybe; but I’m unconvinced.
The jury is still out on the mind-share Rubinius will ultimately attract. We’re certainly not sneezing at anyone’s contribution. And if you hang out in the channel, you might notice some rather interesting conversations between the JRuby folks and the Rubinius folks. You’ll definitely hear conversations about PIC, STM, concurrency models that make you go “Ohh” (thanks MenTaLguY), the possibilities of LLVM, even JIT’ing (though, to hear JP tell it, we’re hopelessly unqualified for that). I’d guess a who’s-who on Rubinius would turn up some rather accomplished folks. Personally, It is encouraging that I didn’t have to write the book on compilers to be able to hack on Rubinius. But really, do you have to know everything to jump into a project and start learning and applying it?
Let’s just say, I’m sure glad Linus was not deterred by the fact that IBM, SCO, AT&T, and Micro$oft had billions of dollars to spend on operating system development. Anyway, I’ll bet the “Yes, but does it scale?” posts will be showing up shortly. C’mon JP, live a little.
Posted by brian 528 days ago
They say good things come in threes, or perhaps I’ll bore you with another post about Rubinius, but what the heck. So, the other day I imported Ruby’s standard library from the SVN repository into the Rubinius repository. I’ve been itching to go through and see what successfully loads. Ah, now that we have sirb, the perfect opportunity presents itself.
$ ./shotgun/rubinius apps/irb/sirb.rb
sirb(eval):000> require 'tsort'
Couldn't find tsort.rbc in runtime/compiler.rba (No such file/-1)
Couldn't find tsort.rb in runtime/compiler.rba (No such file/-1)
Unable to find 'tsort' to load
main.raise at bootstrap/04kernel.rb:26
main.require at core/compile.rb:91
main.__eval_script__ at (eval):1
CompiledMethod#activate at bootstrap/compiled_method.rb:52
main.__script__ at apps/irb/sirb.rb:79
main.load at core/compile.rb:56
main.__script__ at core/__loader.rb:50
Hmm. Oh, yes! I think we need to check load path. (I’ve since added stdlib to the default load path.)
sirb(eval):001> p $:
[".", "runtime/compiler.rba", "lib"]
=> nil
sirb(eval):002> $:.push "stdlib"
=> [".", "runtime/compiler.rba", "lib", "stdlib"]
sirb(eval):003> require 'tsort'
Couldn't find tsort.rbc in runtime/compiler.rba (No such file/-1)
Couldn't find tsort.rb in runtime/compiler.rba (No such file/-1)
=> true
Oh baby. Just ignore those couple complaints. It’s that => true that we’re looking for. Nice! Now, we’ll just try the example in the tsort.rb file.
sirb(eval):004> class Hash
sirb(eval):005> include TSort
sirb(eval):006> alias :tsort_each_node :each_key
sirb(eval):007> def tsort_each_child(node, &block)
sirb(eval):008> fetch(node).each(&block)
sirb(eval):009> end
sirb(eval):010> end
=> nil
sirb(eval):011> {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
=> [3, 2, 1, 4]
sirb(eval):012> {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
=> [[4], [2, 3], [1]]
sirb(eval):013>
Excellent! Er, what’s that? Did I hear you say, “So, big deal, tsort.rb isn’t that tough”? Well, ok, it isn’t. (I didn’t even know about TSort before browsing through the source.) But, we can do other stuff, too.
sirb(eval):008> require 'csv'
=> true
sirb(eval):009>
Yep, that’s right, csv.rb compiles! But, I’ll spare you the pain that ensued trying to use it. Baby steps. Ok, enough fun. C’mon kids, there’s a bunch of the core library still to implement!