Technical Spiders


Something that stinks about Ruby’s core library

22 Apr 2010
Something that stinks about Ruby’s core library

smelly socks The other day my teammate said, “I finally found something that stinks about Ruby’s core library.”

What was wrinkling his nose? The Dir class gives you no way to ask for files only, or for directories only. He had a point. The Dir.entries is inflexible. And even the flexible

I really disagree with Nils Jonsson’s take on ruby’s standard library and so does matz. Nils claims that Something stinks about Ruby’s Core Library, and goes on to provide an implementation for Dir.files and Dir.directories. Yes, there might be functionality that is missing here, but it’s trival to implement. His solution shells which is both dangerous and non-portable. It’s also unnecessarily complex. The beauty of ruby is that it can be changed in very simple ways to solve your problem - even the core library. Here’s my alternative (and much shorter and portable) solution:

class Dir
  def self.directories(path)
    Dir.new(path).entries.select do |e|
      File.directory?(File.join(path, e))
    end
  end

  def self.files(path)
    Dir.new(path).entries.select do |e|
      File.file?(File.join(path,e))
    end
  end
end

Now, his two main arguments were:

  • if you don’t mind some computing time and space wasted and you want to write as little code as possible
  • if you know the contents of the directory in advance

The computing time and space will be much much worse with forking out to the shell listing all of the files, then gsubing out the items with a trailing slash. The ruby filtering will be much faster. But, if performance is a concern, I’m sure my code could be re-written as ruby C much like the rest of the Dir class, and it would be even faster. In the non-windows example, ‘ls -d’ is begin used to filter. In most POSIX implementations of ls, it uses opendir(), readir(), and stat(). So, ls is looking at each file and determining if it is a directory or not. This could potentially be sped up by using scandir(), but that’s a newer POSIX standard, so it might not be available on older unix systems.

nerd ruby

Ruby Can't Scale (Don't Listen to John Metta)!

24 Mar 2010

This is a follow-up to Ruby Can’t Scale! by John Metta

I want everyone to believe that Ruby can’t scale. I want you to think that Ruby is an awkward, weird little academic language that shouldn’t be used in “real" production deployments. I want you to think that it’s slow, memory hungry, full of security holes and breaks the rules of proper programming.

I don’t want everyone to use Ruby. I want to keep it for myself. I want my company to build software faster, easier, and still be able to go home before it’s dark out while outbuilding you and your product. I want to have my pick of small startups and recruiters breathing down my neck to hire me because I know this weird, obtuse, little language. If you learn it, then I’ll have to work even harder to beat out the next guy.

So beware of Ruby! It has lambdas, class evals, blocks, mixins, and all sorts of scary things. These are weird and strange! Stick to what’s tried and true. Java and C++ aren’t going anywhere. They are stable, and besides, that’s what real companies use. Save Ruby for me.

ruby programming tech startups

On Procs and Rubies

01 Aug 2009

Recently, I’ve been playing around with Shoes. I ran into an interesting bug (or side affect?) in Ruby 1.8.

Here’s the first code sample, create a Proc for each item in an array, then calling it.

procs = []
[1, 2, 3].each { | x | procs << Proc.new { puts x } }
procs.each { | p | p.call }

# prints 1, 2, 3

Here’s the same code, but adding a local variable of x before calling the block.

x = nil
procs = []
[1, 2, 3].each { | x | procs << Proc.new { puts x } }
procs.each { | p | p.call }

# prints 3, 3, 3

So what happened here? Well, as it turns out, in Ruby 1.8, block variables are not scoped locally to the block. Therefore, when x is evaluated in the Proc, it’s modified in each call. So, when it’s finally called, it’s been changed. This has been fixed in Ruby 1.9. Running the same code in Ruby 1.9 prints 1, 2, 3 for both examples. And now you know.

ruby proc coding horror

Facebook now allows username change... once.

24 Jul 2009

I really don’t understand why facebook is being so stubborn on restricting username changes. It just creates frustration for it’s users. The only reason why they would discourage changes is to prevent you from breaking your own vanity url, or someone else taking your vanity url after you change it. Come on, facebook! Give your users a bit more credit. Don’t treat them like idiots. Explain the downsides of changing their username, then let them do it!

(more info: readwriteweb)


Planning for failure

12 Jun 2009

Reading The planning fallacy over on Signal vs. Noise, I was struck at how off it seemed. The original article referenced was Planning for Fallacy and I think they all missed the point.

It’s all about planning for failure rather than planning for success. As a software engineer, you’re always considering the worst case runtime and space analysis. Linear search is always Θ(1) in the best case. If that always held true, why would we even bother improving on search?

When engineers need to give an estimate, they need to give the worst case. Always. Overly optimistic scheduling is a classic mistake that causes projects to slip (pointed out well in Rapid Development). These mistakes compound in large or complex projects because of dependent or related tasks.

One helpful technique I’ve found to keep these estimates better is by group estimation. This is commonly used in Scrum during Sprint Planning. Also, if you’re following iterative development, your iterations are short, so your dependancies should be small (or at least if things fail, they can only back up so much).

So, my point is, don’t throw away all planning and just wing it. You end up with Cowboy Coding and anyone who cares about the project being delivered won’t have any visibility into what’s going on. Get real by planning for the worst case.