Thursday, December 20, 2007

Automated Testing Is Not The Silver Bullet


“Automated tests ensure the software is working as designed. Human tests ensure the design is working.”


(quoted from Why Does Vista Suck? Blame Automated Testing)


Do not get me wrong, I am a huge fan of automated testing. In fact I am a huge fan of automating whatever we can. But it is always good to be reminded that There Is No Silver Bullet.

Sunday, December 16, 2007

Employers Can Not Read Our Email (in Chile)

I was shocked to hear from a friend how every popular webmail was blocked inside his workplace. Not only that: Their corporative email was randomly read to ensure the good utilization of this resource.

Aside from never wanting to work for such kind of employer (I am also against massive blocking of instant messaging by the way, but at least that is open to debate), I questioned the legality of their surveillance. I thought it was not legal, but I'm not a lawyer, and some googling showed me that there are countries where it is accepted.

I did a bit more of investigation, and the results relieved me: In Chile it is not legal to read the employee's mail, even if it is a resource provided by the employer. They can set some terms of use of their mail, but can not enforce them by reading emails.

Sources (in spanish):

Resolution of Direccion del Trabajo
CLCert article

Saturday, December 15, 2007

Security by Stupidity I: Rails and attr_accesible

Sometimes you get surprised how frameworks and/or applications messes things up when trying to deal with security. Here is one example.

Context


Framework: Rails
Stupidity: attr_accesible/attr_protected
Output: Annoyed developers and/or missing data.

Explanation


The rails manual suggest declaring on your models what attributes are supposed to be protected (or accessible). Where protected/not accessible means not directly set from parameters coming from the outside.

This is stupid, because it works at the wrong layer: it is not the model the one that talks with the outside; that is the controller. So, is in the controller where we have to sanitize everything that comes from the outside and remove everything that should not pass to the inside of the application. Letting something dangerous pass this layer is simply a bad idea. Doing tricky stuff to catch this leak in a deeper layer is not going to fix it.

The first practical problem is that, as in every tricky situation, it is easy to miss something. In this case, a missing field in one of these lists gives either a security or a data-losing problem.

More important, even supposing that everything is consistent, this "solution" effectively limit the "mass assignment" methods (new , update_attributes and who knows what others). That may seem OK if you only use such methods for passing insecure data coming from HTTP, but chances are that you may find them useful for ther things. I had to do data loading coming from CSV files this week, and didn't expect that update_attributes may ignore some attributes. Principle of least surprise anyone?

The good thing here is how ridiculous easy is to program the attr_accessible functionality. Unless I'm missing something, the practical effect of attr_accessible is to filter out some keys from some hash:

def clean_input(input_hash, allowed_keys)
clean_hash = {}
input_hash.each do |k, v|
if allowed_keys.include? k
clean_hash[k] = v
end
end
clean_hash
end

So, instead of this (plus the corresponding attr_accesible definition on the model):
  User.new(@params['user'])

It would be:
  user_attrs = clean_input @params['user'], 
['name', 'password', 'email', 'signature']
User.new(user_attrs)

It may be my Python background, but I firmly believe that is this case, explicit is far better than implicit (and wrong).

Saturday, December 8, 2007

Things a Ruby Developer Should Know?

I'm currently working on a Ruby on Rails web application. I'm happy again because the language doesn't get on my way while programming. But I'm far from being a seasoned Ruby programmer, so I've been learning a lot.

Something that amazes me, is how people develop on Rails without knowing too much of Ruby, at least on my work environment. And how comfortable they seem! It may show how easy is to do web applications with Rails, but I don't think that it's a good thing overall (for them, that is. Rails is OK). They may argue that Rails is a good enough tool to solve their problem, so they don't need anything else, but how can they assert that without having an idea about the other possibilities? Almost everything is good enough when you don't have alternatives. Heck, 64 kilobytes of memory were good enough for people some years ago.

That doesn't work for me. I feel unpleasant when I'm using a programming tool almost blindly. I must know why (at least the basic) things work, and if times suffices, how they work.

So after a few weeks of using Ruby again, I must say that Ruby is a nice language. Its expressiveness is superb, and I can't emphasize enough how much that matters. Half of Rails greatness comes for the flexibility of the language upon it is built.

If you are already using Rails, this secret weapon called Ruby is right there, waiting to be used. You haven't to pay anything. So, please, use its expressiveness to make your program clearer. Short the distance between what you write and what you solve. It's not Lisp, but it's closer. They now call it "writing internal DSLs", but take the hype with a grain of salt: they are not new, and they aren't the silver bullet. They should be in your toolbox, though.

You can decide to not use some Ruby tricks, but only after knowing why is a bad idea to use them on the problem at hand. Not because you are too lazy to learn about the language.

Every programmer who is currently working on a Rails application and hasn't learned enough of Ruby is missing a lot. By now, this is my list of things a Ruby developer should know, in no particular order:
  • How to simulate keywords parameters
  • How to write mix-ins
  • What is method_missing
  • How source files are imported/evaluated
  • What are blocks and how to write methods that accept them
  • How to define anonymous functions
  • How to use the *eval methods


But who am I to establish what a Ruby developer should know? In fact, I still don't know too much about two of the items of my list. I'm sure there are other topics where I'm so ignorant that I haven't heard of them.

So, what's missing on this list?