Posted by Rick DeNatale
Wed, 30 Apr 2008 02:24:00 GMT
InfoQ recently published a
video interview with Dave Thomas (of OTI fame).
In his inimitable style, Dave covers lots of interesting topics in software development, both today and with a historical perspective.
I agree with almost everything he says, and find the rest food for thought.
His comments about Java as a platform are quite germane to the article I published yesterday. If you’ve been exposed to Big Dave before, you’ll enjoy this, and if you haven’t it’s a good introduction.
Tags BigDave, iconoclasts, java, ruby, smalltalk | 1 comment | no trackbacks
Posted by Rick DeNatale
Sun, 27 Apr 2008 19:17:00 GMT
Charlie Nutter just published an article which assesses
the various implementations of Ruby. In all it’s a quite even-handed description coming from one of the main proponents of JRuby.
Charlie talks about each implementation and describes the perils each faces.
These seem to be days of crisis for Ruby. With so many implementations compatibility is a challenge. Particularly since Ruby lacks a formal specification. The Rubinius developers have been working hard to address this by developing, RubySpecs, a set of rspec style specifications for Ruby. Matz has also convened a regular meeting of Ruby implementors via irc. The first meeting took place last week,and one of the decisions taken was to make RubySpec the officially blessed set of tests to be used by all implementors.
Compatibility is hard. I’m not talking a little hard, I’m talking monumentally hard. Ruby is a very flexible, complicated language to implement, and it ships with a number of very flexible, complicated core class implementations. Very little exists in the way of specifications and test kits. – Charles Nutter
Is Ruby Forking?
Currently there are two major “official” versions of Ruby. Ruby 1.8, which is in use for most production purposes, and Ruby 1.9 which introduces new features (e.g. integrated support for strings with different encodings), new language features (e.g. new syntax for hash literals which allows actual parameters to methods taking an options hash as the last argument to look like keyword parameters), and some incompatibilities.
As Charlie points out the peril here is that Rubyists have a hard time figuring out which Ruby to target. Ruby 1.9 isn’t yet ready for production, but even when it is, will the advantages outweigh the cost of the ‘porting’ needed to get past the incompatibilities.
Some implementations are attempting to bridge the gap. JRuby is taking on some 1.9 features while maintaining compatibility with 1.8. The recent preview release of Ruby 1.8.7, also introduces some 1.9 features to the 1.8.x code base, albeit with some initial incompatibilities, which hopefully will be worked out. RubySpec should help this.
MacRuby, on the other hand, is taking another approach to 1.9 features. MacRuby is a new Apple implementation of Ruby which uses the Objective-C run-time as a platform, much as JRUby and IronRuby use the Java JVM, and Microsoft DLR, as platforms.
One of the ways in which MacRuby exploits 1.9 is the way they are mapping the new hash literal syntax I just mentioned. Let’s look a bit at that new syntax.
At the risk of offending the “Rails isn’t Ruby crowd”, I’m going to take an example from ActiveRecord, because Rails tends to use option hash parameters quite a bit. In Ruby 1.8 I might code:
Book.find(:all, :order => "title ASC", :limit => 10)
To get the first 10 books sorted by title. The new Ruby 1.9 syntax allows this to be written alternatively as:
Book.find(:all, order: "title ASC", limit: 10)
Which is actually an identical call. These “keyword arguments” are quite reminiscent of the Smalltalk-inspired syntax used in Objective-C. As I understand it, MacRuby will look at such a call, and turn it into an Objective-C message internally something like:
[Book find: @selector(all) order: "title ASC" limit: 10]
But this isn’t exactly the same. In Ruby one method can handle multiple optional keyword arguments which can appear (or not) in any order. In Objective-C the message selectors find:order:limit, and find:limit:order would map to different methods. When I asked Laurent Sansonetti about this on ruby-core, he said that the implementation would actually determine whether the receiving object understands :find:order:limit: and if not fall back to a more ruby-like call. I’m not sure how such a chicken-typed implementation will really stand up in practice, but I guess that time will tell.
I’m also not sure what the long-term implications of this are as Matz moves from 1.9 to 2.0 and perhaps starts defining new method definition syntax which provides syntactic sugar (at least) for handling “keyword parameter” hashes on the other side of the invocation.
Platforms, Platforms, Platforms
As I said above, one way to characterize the various ruby implementations is by the platform each ‘advocates’. Traditional MRI Ruby, and Ruby 1.9 run well on UNIX like platforms like Linux, OS X, and Solaris. Rubinius is building a new Ruby-based platform using ideas from Squeak and earlier Smalltalk implementations, although as far as I can tell, it’s not following the Smalltalk philosophy of being an “operating system” on its own, IronRuby is really an attempt to optimize a Ruby implementation for Microsoft Platforms, while JRuby leverages the JVM.
I can’t help but think back to the early 1990s as a member of the Smalltalk community. Smallalk had gained a fair bit of traction in the enterprise, particularly in industries such as finance and insurance where rapid application development was important. Java started to take the wind out of Smalltalk’s sails. I always considered the switch from Smalltalk to Java to be driven by factors such as the cost of entry for an individual programmer, but my old friend Dave Thomas (OTI’s BigDave, not pragDave) points out that it was more a matter of companies like IBM (one of the main Smalltalk vendors by then) moving to Java as an anti-Microsoft platform. Java really took off in the enterprise after IBM, Sun, and others entered a kind of ABM treaty (Anyone But Microsoft)
Ruby is in a different place than Smalltalk was at that time. Smalltalk was available from, and advocated by, a small number of vendors who sold it at a handsome price. Two of the big Smalltalk implementations survive, IBM/VisualAge Smalltalk is still available from Instantiations at a four figure price. Cincom sells the latest version of VisualWorks Smalltalk, under a complex web of licensing options. Both of these “compete” with the open-source Squeak implementation.
The environment has shifted out from under the big corporate providers of software development tooling like IBM, Sun and Microsoft. It’s hard to see how to make big bucks selling development tools when so much is available under various open-source licenses for the cost of a download.
Ruby has come out of today’s open-software environment. It was conceived out of one man’s desire for a language which he personally found pleasing, and grew within the open source community. While I applaud and appreciate the support that Ruby has received from Sun, Microsoft, Apple, and other corporations, I can’t help but feeling that some of the motivation is based on keeping control of the platform.
These might be perilous times for Ruby, but I’ve got confidence that the overall community will keep things from getting too far out of whack.
Again, time will tell.
Posted in ruby | Tags opinion | 7 comments | no trackbacks
Posted by Rick DeNatale
Sat, 26 Apr 2008 15:11:00 GMT
A while back there was quite a thread on the Ruby-lang mailing list about the real semantics of the expression.
In many books and articles on Ruby the form:
Where <op> is an operator like + Is described as syntactic sugar:
While this is true in most cases, it isn’t’ true if the operator is ||.
This comes to light when the left hand side is a method call, to an accessor, or accessor-like method. For example
h = Hash.new("hello")
h[:fred] ||= ""
h #=> {}
Some find it surprising that the assignment doesn’t cause the hash to have :fred as a key. What this code snippet shows is that the assignment doesn’t actually assign anything if the left hand expression returns a logically true value. A Hash with a default value will return the default value when accessed by any key which is not present in the hash. Since h[:fred] returns the default value, the assignment doesn’t happen.
This affects any object which has ‘accessor’ methods. Here’s a class cooked up just to explore this aspect of Ruby.
class ChattyCathy
def initialize(x=nil)
@x = x
puts "created x is now #{x.inspect}"
end
def x
puts "x read x is #{@x.inspect}"
@x
end
def x=(val)
puts "x written, now #{val.inspect}"
@x = val
end
end
The purpose of this class is simply to let us see exactly when the x attribute is read and written. Now if we run this code
c = ChattyCathy.new(42)
puts "about to evaluate c.x ||= 43"
c.x ||= 43
c = ChattyCathy.new
puts "about to evaluate c.x ||= 43"
c.x ||= 43
We get the following output:
created x is now 42
about to evaluate c.x ||= 43
x read x is 42
created x is now nil
about to evaluate c.x ||= 43
x read x is nil
x written, now 43
Which clearly illustrates just when the assignment actually happens.
The real expansion of x ||= y
Matz explains that the real expansion of x ||= y is:
The expectation that x ||= y is the same as x = x || y, does seem reasonable to someone ‘coming from’ C or one of it’s derivative languages. As far as I can determine, C introduced the notion of assignment operators like += and -=. And K&R defined these assignment operators as a shorthand for x = x + y, etc.
On the other hand, although C has logical operators || and && which, like Ruby have ‘short-circuit’ evaluation, it doesn’t allow ||=, or &&= as assignment operators.
Since || is a ‘short-circuit’ boolean operator, the left hand operand expression is only evaluated if the right hand operand expression evaluates to a logically false value, i.e. either nil or false.
The way that Matz included ||= as an assignment operator makes perfect sense to me. The ||= assignment operator reserves the short-circuit nature of ||.
So what about x &&= y
Although I haven’t seen this discussed anywhere, &&= in Ruby has similar behavior:
c = ChattyCathy.new
puts "about to evaluate c.x &&= true"
c.x &&= true
puts "about to evaluate c.x = \"hi\""
c.x = "Hi"
puts "about to evaluate c.x &&= true"
c.x &&= true
created x is now nil
about to evaluate c.x &&= true
x read x is nil
about to evaluate c.x = “hi”
x written, now “Hi”
about to evaluate c.x &&= true
x read x is “Hi”
x written, now true
So the expansion of x &&= y is x && x = y
Posted in ruby | 5 comments | no trackbacks
Posted by Rick DeNatale
Wed, 23 Apr 2008 20:17:00 GMT
The third edition of Agile Web Development With Rails is now in Beta.
Sam Ruby has become the third author, along with Dave Thomas and DHH. According to PragDave, Sam has converted the Depot App tutorial to be compatible with Rails 2, and the rest of the book is also being revised.
Posted in rails | no comments | no trackbacks
Posted by Rick DeNatale
Fri, 18 Apr 2008 22:07:00 GMT
Some time ago, I wrote a rails patch which allows http file uploading in integration tests.
You just use the same TestUploadedFile class used in functional tests or controller specs if you’re an RSpec’er. So you can do something like.
post '/upload' :file => TestUploadedFile("/path/to/blah.txt")
The patch detects a TestUploaded file amongst the parameters, and converts the request into a proper multi-part request.
It will work for both posts and updates.
If you’re running edge rails you’ve already got this. But many have asked for a version for earlier rails versions. At work, I’ve been working on an RSpec story which requires file uploading, and we’re using the 2.0.2 gem version of Rails for deployment purposes, so I whipped up a little plugin which patches 2.0.2 Rails with the changes from Rails changeset 8978. The plugin checks the rails version and throws an exception if it’s anything other than “2.0.2” since I haven’t tried this with anything earlier, and it’s not necessary for anything newer.
You can get it from git hub at git://github.com/rubyredrick/integration_upload_plugin.git
This also marks the first time I’ve used git for anything but gitting Rubinius.
Posted in rails | Tags integration_upload_plugin, open_source_contributions | no comments | no trackbacks
Posted by Rick DeNatale
Wed, 26 Mar 2008 21:30:00 GMT
I was adding to an existing controller today at work and I was stumped because one of the examples in its controller spec was failing due to an exception thrown while rendering a view.
Normally RSpec controller tests, which are usually used to specify controller logic, bypass view rendering unless you specifically use the integrate_views method in the example group. The idea is that you should use view specs to specify the logic and output of views.
Since I was working in existing code, which pre-existed my being here, I’d followed some of the existing example groups in the file. These would typically look something like this:
describe HobbitController, "doing something" do
before(:each) do
@controller = HobbitController.new
end
end
I finally realized that that first line in the before block was clobbering RSpecs ability to control whether or not views should be rendered. RSpec actually creates the controller instance variable for you, and extends it with a module which overrides the render method to allow integrate_views to control the rendering while allowing the expect_render expectation to work whether or not rendering actually happens.
So I’ve got a new task to clean up all the other controller specs.
Posted in rails | Tags Rspec | no comments | no trackbacks
Posted by Rick DeNatale
Sat, 22 Mar 2008 20:45:00 GMT
Things have been hectic over the past month or so, and big changes have been in the wind.
As of the 3rd of March, I’ve been working full-time at Near Time as a Senior developer.
I really enjoyed the projects I did with Terralien and I can’t thank Nathaniel enough,
but the opportunity to have a steady diet of work, and to work on a large-scale project with a talented group which is enthusiastic about my
favorite tools and technologies like Ruby, Rails, and RSpec was just too good to pass up.
I must admit that I’m still adjusting to the idea of a 9-5 job (actually more like 9-7 or 8), and a 30+ mile commute instead of waking up the stairs, or out to the family room, but I’m having a blast.
I still plan to post my thoughts here, although perhaps a bit less frequently, albeit more frequently than over the past month.
Posted in site_news | no comments | no trackbacks
Posted by Rick DeNatale
Fri, 15 Feb 2008 13:29:00 GMT
One of the classics in the Smalltalk literature, which has also had a big influence on the Ruby community is Kent Beck’s “Smalltalk Best Practice Patterns”
, which captures the best practices for designing and coding Smalltalk programs. Back when it was published, I used to see Kent a few times a year, and happened to be in the Bay area when he made an author appearance at the Computer Literacy Bookstore in San Jose, where I got my copy, and the autograph shown here.
The Ruby language has many similarities with Smalltalk, so much of Kent’s advice applies to Ruby. I frequently hear prominent Rubyists mention the book.
On the other hand, Ruby is not exactly Smalltalk, so Kent’s book isn’t an exact fit to Ruby. I’ve been wanting to start writing about adapting some of these patterns to Ruby for a while, so this article will hopefully be the first in a series.
The Motivation For This Article
Recently on the ruby-talk forum a thread discussing accessor methods vs. direct instance variable access came up. This was a hot debate topic in the Smalltalk community back in the 90s, and Kent addressed it in two competing patterns in the book, one of which Ryan Davis (a.k.a ZenSpider) brought up in the conversation.
Read more...
Posted in ruby, smalltalk, best_practices | Tags bestpracticepatterns, kentbeck, patterns | no comments | no trackbacks
Posted by Rick DeNatale
Tue, 12 Feb 2008 14:42:00 GMT
Another
thought provoking piece from Steve Yegge.
Well, we also know that static types are just metadata. They’re a specialized kind of comment targeted at two kinds of readers: programmers and compilers. Static types tell a story about the computation, presumably to help both reader groups understand the intent of the program. But the static types can be thrown away at runtime, because in the end they’re just stylized comments. They’re like pedigree paperwork: it might make a certain insecure personality type happier about their dog, but the dog certainly doesn’t care. – Steve Yegge
And he’s getting the predictable responses from the static-typing advocates.
One quibble I’ve got with what I’ve just quoted, is that, in many languages, static types aren’t just comments. In the C++ implementations I’ve looked at, for example, the typing is used to generate runtime code which relies on the typing done at compile time. The other day I wrote about instance variable access in Java, Smalltalk and Ruby. In C++ instance variable (field) access is static and based on offsets. If a type error get’s past the compiler, say by a bad pointer manipulation, the run-time code can access a non-existant variable, possibly clobbering something vital.
In fact this “bug” is possible not in spite of static type checking, but because the compiler uses static type checking to affect the code, and “throws away” the information needed at run-time to avoid it.
Posted in ruby | Tags statictyping, types | no comments | no trackbacks
Posted by Rick DeNatale
Mon, 11 Feb 2008 13:18:00 GMT
Fabio Akita emailed me this morning to tell me that he had translated my recent article about variables in Ruby, Java, and Smalltalk into Portuguese.
I think this is the first time I’ve been translated!
Posted in site_news | no comments | no trackbacks