Wednesday, March 19, 2008

Ruby Method References In A One-Pass Interpreter

Ruby allows for some very clever techniques involving run-time code evaluation. I find these particularly handy when writing table driven code (e.g. file parsers). But coder beware. There's been a lot of discussion about whether Ruby blocks are truly closures but the fact that it's a one-pass interpreter (at least the reference implementation I'm using, ruby 1.8.5) can cause some unexpected results as well.

Consider this simple case: initializing a class property using a method reference. The Object.method call will succeed or fail (return nil) depending on when it's called in the class definition. First, let's put the initialization at the top of the class (where most of us would normally put it):

class TestMeth

@@method_ref = self.method(:meth)

def self.meth
  puts "executing meth()"
end

def run_method
  @@method_ref.call
end

end

tm = TestMeth.new
tm.run_method

Sorry, no can do:

[chrisa@doppio ~]$ ruby t.rb
t.rb:3:in `method': undefined method `meth' for class `Class' (NameError)
from t.rb:3

Now move the assignment to the other side of the method definition:

class TestMeth

def self.meth
  puts "executing meth()"
end

@@method_ref = self.method(:meth)

def run_method
  @@method_ref.call
end

end

tm = TestMeth.new
tm.run_method

That works:

[chrisa@doppio ~]$ ruby t.rb
executing meth()

The behavior is the same if you make @@method_ref a constant (i.e. 'METHOD_REF'). The interpreter hasn't gotten to that line of the file when the assignment is executed. If you're using method references, you either have to position them correctly in the file or assign them at run-time in an initializer method. Works, but not as you might expect.

Sunday, March 9, 2008

"Dude, that's what they want."

Like many others, I'm filled with dismay and anger as I watch retroactive immunity for the phone companies make it's inevitable way through the legislature. I'm also reminded of my own early experience handling "confidential" information and the way in which it helped me develop professional ethics.

When I was in college I had the best campus job of anyone I knew. I worked for the adminstration as a programmer doing data processing. It paid two dollars more than minimum wage, I could work on my own schedule and best of all, it came with a key to the computing center, which in those prehistoric times had an entire air-conditioned room to house the Dec-10. It can get awfully hot and muggy in Connecticut in the summer and there were places to hide a sleeping bag, so this was no small perk.

The job also came with some responsibility. I had unrestricted access to academic, personal, and financial information for the entire student body and alumni. For a nineteen-year-old, on top of being recognized as an alpha geek, this was heady stuff.

So one day, just for fun, I printed out a sorted listing of the entire student body and their birthdays. It seemed a harmless opportunity to show off. I showed the listing to a friend and she immediately noticed that a roommate of hers had a birthday that week but hadn't mentioned it. She decided to get a suprise party together.

The party was a disaster. It turned out that her roommate was deeply embarrassed about her age, enough to lie about it and never mention her birthday. When the suprise was announced she was mortified and, crying, asked everyone to leave.

There are two lesons here. One, my intention may have been innocent enough but it had unintended consequences that hurt someone. Two, by breaking the rules about disclosure of this information I had violated the trust placed in me when I took the job. The consequences were a good illustration of why the rules were there in the first place.

I was reminded of this story the other day when I came across the affidavit of Badak Pasdar. This statement, which he made on Feb. 28 of this year tells a very disturbing story.

Acting as a computer security consultant in the data center for an unnamed wireless telecommunications company, he comes across a large (DS3, 45Mb/s), unaudited, unsecured network connection leading from inside the wireless telco's secure internal network to undisclosed recipient(s). This is referred to by telco employees as the "Quantico Circuit" (Quantico VA is the location of a 100 square mile marine corps base, including their research center). This pipe gives people on the other side access to everything: they can listen in to any client's phone in real time, track the physical location of their GSM phone, billing records (including who they call), everything. There's no auditing or tracking implemented so no one at the telco can tell precisely what the people at the other end are doing. When he asks where it goes and objects that this really can't be considered an acceptable practice WRT commonly accepted industry security standards, he's told to shut up or get fired.

There's been lots of discussion already (but not enough, IMHO) about the current administration's use of eavesdropping, wiretaps, etc. and the legal, constitutional issues involved. This story affects me in a personal way however because I am (on a smaller scale) often in positions of trust and responsibility with regards to the personal information of other people and I have to make decisions about the specifics of confidentiality all the time. As someone working in medical research I've been to more HIPAA compliance training classes and confidentiality seminars than I care to remember (I have another one coming next week, in fact). And I can tell you, there's a lot of thought and work involved in protecting people's information. Concerns about the identity and medical condition of study participants percolates all the way back up into database schemas and applicaion codes in a "non-trivial" (as we nerds like to say) way. Think separate, secured database instances. The question I have to ask all the time is "where's the line?" How far do I have to go? How much extra work should I do? I have a very simple, effective rule for this:

I follow the law.

A lot of smart, well informed people put a lot of work into drafting the applicable law. It may not be perfect but that's where my society has drawn the line for me. I'm not going to second guess them because I accept the fact that I'm not smarter than the combined efforts of all those administrators, scientists and legislators and because I accept the responsibility that comes with my well-paying, fascinating and enjoyable job.

So now I'm thinking about the people who work in that data center. I can only imagine what it must be like to have access, not to the academic records of two thousand or so students, but to the voice and data communication in real time of millions of American citizens. Intimate conversations, their location, their routines. Are they calling their stockbroker? A lover? A triple X chat line? Where are they? What are they doing? Who else do they talk to? Knowing as I do (something about) how one could use that data it's a scary, almost vertiginous thing to contemplate. What are they thinking when they walk past that network interface unit?

Maybe they're convinced they're doing the right thing. It may be illegal but it's for the greater good. They're informed participants in a critical struggle for the nation's secuirty. The nation has secrets too, and they're trying, to the best of their ability as professionals, to keep those secrets. I'd expect them to be ready to take responsibility and the consequences. Perhaps they (quite) reasonably expect a legal pardon if they were to be prosecuted for breaking the law.

Or maybe not. Consider this exchange from the affidavit:


When DS left, I asked C1 again, "Is this what I think it is?"

"What do you think?," he replied again, smiling.

I shifted the focus. "Forgetting about who it is, don't you think it's unusual for some third party to have completely open access to your systems like this? You guys are even firewallng your internal offices, and they are part of your own company!"

C1 said, "Dude, that's what they want."

I can almost see the smirk. They know. Their bosses know. They don't want to know the details, and they certainly don't want to be held accountable. It's one big wink and the folks at the other end of the cable will cover for them. That's the part I can't accept. I understand the terrible necessities of national security and I'm not so stupid or naive as to think we don't need spies or wiretaps. But this goes over the line that our society has, with considerable debate and effort, defined in law. You can't break the law and violate the public trust that severely because someone with a badge tells you to. The people who've done this are not showing any sense of responsiblity or the gravity of what they're engaged in. There's no sign of remorse. Hell, they told a visiting consultant where the cable goes. No, they're just going along to get along. And maybe showing off a little.

They should go to jail.

I'm not saying ruin their lives. Maybe just for six months. Maybe for one day, sentence suspended. But these individuals, from the tech who hooked up the box to the CEO that approved it, should be "film at eleven." I want to see them perp-walked in handcuffs out of the courthouse by marshalls. They should stand up in front of the whole society and acknowledge what they've done. "Yes, I broke the law, and failed to comply with the ethical standards of my profession. I'm sorry." They should be ashamed of themselves.

Not likely.

Tuesday, March 4, 2008

Nil desperandum!

Which means literally, "Despair of Nothing!" Makes you wonder if Horace ever worked in software.

When is a null object reference not a null object reference? Why, when you can dereference it, of course.

If a Ruby method returns nil and I try to dereference it thinking I have a valid object reference, it's going to throw, right? Raise an exception? Hurl?

Erm, no. Actually, nil is an object. Let's have some fun with irb:

[chrisa@doppio ~]$ irb

Can I convert it to an integer?

irb(main):001:0> nil.to_i
=> 0

Yep. At least it's 0. How 'bout a string?

irb(main):002:0> nil.to_s
=> ""

Of course, it's an object, silly! And an array, etc.

irb(main):003:0> nil.to_a
=> []

This next one is really cool. Let's say you got this object reference back from ActiveRecord using MyModel.find(:first). Since you've dutifully followed the convention, you expect to get it's accession number by dereferencing the automagic property "id":

irb(main):004:0> nil.id
(irb):2: warning: Object#id will be deprecated; use Object#object_id
=> 4

Love that deprecation warning. We all hunt down and fix those right away, right? I spent a pleasant afternoon staring at the source of that one. Remember to read those web server logs carefully, kids!

Fun with Ruby Conditional Evaluation

The first in a series of postings for the unwary Ruby Newbie (Rubie?).

Is a numeric value of 0 true or false? To a C or Perl programmer it's obviously false. In Java it's a trick question (try it). But even those who've never programmed in C or C++ seem to share a general expectation of "false, duh."

What about Ruby? It's easy enough to find out. We'll use irb (for "interactive ruby") to put the question to the interpreter directly:


[chrisa@doppio ~]$ irb
irb(main):001:0> if (0) then puts "true" end
true

Which is to say that any numeric value will test true. How about an empty string?

irb(main):001:0> if ("") then puts "true" end
(irb):1: warning: string literal in condition
true

Well, that's a little bit friendlier but still, I can see getting quietly horked by that one. Contrast this with Perl's behavior. The interactive debugger is a bit less friendly, so we just execute the test directly from the command line:


[chrisa@doppio ~]$ perl -e 'if (0) {print "true\n"} ;'
[chrisa@doppio ~]$

[chrisa@doppio ~]$ perl -e 'if ("") {print "true\n"} ;'
[chrisa@doppio ~]$

Doesn't quite match the "Principle of Least Astonishment" pattern...