Sunday, June 8, 2008

Railsconf 2008

I had a great time at Railsconf. I got to meet up with a lot of coworkers I haven't seen in a while. The buzz around the conference was energizing. It definitely feels like the community is maturing. There were a lot of people there using rails for their day to day business. I also was happy to see how a lot of the sessions were very ruby focused. The Rails and Ruby communities felt like they were coming together.

On Thursday I went to see Neal Ford and Pat Farley's metaprogramming tutorial. Now I may be a bit biased but I thought their talk was great. I also heard good things from random people I talked to. After that I went to the Refactotum talk put on by Relevance. Thanks to them, I submitted my first patch to CruiseControl.rb!

I enjoyed Nathaniel Talbott's 23 Hacks talk. Its easy to forget to keep programming fun! Justin Gehtland's Small Things, Loosely Written and Written fast was also a great talk. Great ideas and an entertaining presentation. Philippe Hanrigou's talk on troubleshooting Mongrel processing was great, too. It was pretty hardcore and narrowly focused, but the people that were there seemed to get a lot out of it.

All the upcoming ruby implementations are pretty exciting as well. They all look to be progressing well and each has their own niche. The Rubinius demo of browseable backtraces was awesome. After hearing Kent Beck's comment on using Ruby tools to develop Ruby, I think Rubinius in particular has great promise as a Ruby development platform. I could see some powerful IDE's taking advantage of all the internals exposed by Rubinius. A lot of people have commented on it already, but Maglev looks interesting. As a consultant, a platform like that could allow us to use Ruby in places beyond traditional web apps.

Its great to be around a large group in the Rails community. It looks like the excitement isn't dying down anytime soon!

Sunday, April 6, 2008

iPhone SDK first impressions


I've been working with the iPhone SDK lately. I'm working on an application to input receipt information for expense reports. It's a fairly simple app, but its useful to me and a good starting point.

Here's the things I like so far:

  • Apps are written in Objective-C and use the same Foundation framework as OS X apps. Things like NSArray, NSDictionary, NSDate are all the same. If you have any experience writing Cocoa apps, you can get started on iPhone apps fairly easily.

  • iPhone development is well integrated into XCode. You just pick an iPhone app template and go. The "Build and Go" button will build and deploy your app to the built in simulator.

  • The Cocoa Touch UI widgets are nice. Apple did the smart thing and built a new UI framework from the ground up. The iPhone interface is quite a bit different, so trying to shoehorn desktop UI widgets would have been a mistake. UITableView is easy to use and extend. I'm using it on just about every screen.

  • There is a lot of good documentation so far. I know its still in beta, but there is a lot of sample code, videos and API docs.



The SDK is still in beta and there are a few rough edges. Some problems I've run into:

  • Interface Builder is not usable. The second release of the SDK included Interface Builder for the iPhone. There are no project templates available to set up an iPhone project with Interface Builder. I searched around and found out how to add the IB xib file to the build and show it on the screen. It is not as seamless as it is in the desktop version. I'm sure this will get fixed by the time the SDK leaves beta. Fortunately, the SDK is still quite usable without Interface Builder.

  • OpenGL, CoreLocation and other frameworks are not useable in the simulator. I can understand the technical problems in getting these to work, but Apple is not accepting developers into the iPhone Dev Program very quickly. So, its impossible to work on any apps using the frameworks that won't run in the simulator.

  • I can't figure out how to get OCUnit to work in the SDK. After being immersed in TDD while working at ThoughtWorks, it would be nice to be able to unit test my iPhone code. I'm still not familiar with how OCUnit works, so I haven't figured out if there is a way to have tests run in the simulator.



It's been fun getting away for web apps for a bit and working on mobile devices again. I think the iPhone has great potential, and the SDK is quite powerful. It will be interesting to see all the applications that will come out for it. I think the iPhone also has potential in the enterprise space. It looks like Apple has thought about that, too. I'm eager to see how their enterprise developer program turns out.

Saturday, February 23, 2008

Fun with Enumerable::Enumerator

Ruby has a nice class in the core library for turning objects with iterator methods into Enumerable objects: Enumerable::Enumerator. I discovered this class a while ago, but hadn't thought of a need for it at the time.

Recently, I was integrating with some web services and needed to parse some XML. REXML's XPath is a great tool for this. XPath has a method #each that will allow you to iterate over all the elements that match the XPath. So, to collect all the text nodes for an XPath, you could do something like this:

items = []
REXML::XPath.each(@document.root, "//list/items").each do |element|
items << element.text
end


XPath implements the each method, but isn't an Enumerable so it doesn't support methods like collect. Using Enumerable::Enumerator and Rails' to_proc makes this code simpler:

Enumerable::Enumerator.new(REXML::XPath, :each, @document.root,  "//list/items").collect(&:text)



Friday, January 18, 2008

Spiking with reckless abandon



A couple months ago, we were trying to improve our build process to better reflect our production environment. Our application runs on Oracle and the database schema is owned by one Oracle user, and our application logs in as another. The application user is granted rights to the tables it needs to use. There are also synonyms defined for all the tables our app uses.

Our builds only used a single database user for all our tests. If we forgot to update our database scripts to add new grants or synonyms, we wouldn't know it until we deployed to our QA environment. So, our goal was to have our build run with the same user split that the production environment did.

One problem with that scenario is our functional tests inserted data into tables that the app user didn't have insert rights to. We decided to spike switching to the schema owner for insertion of test data and go back to the regular app user for the rest of the test. We came up with this crazy bit of code to hijack our ActiveRecord models and reuse them to insert test data:

module TestData
def self.const_missing(name)
klass = Kernel.const_get(name)
new_klass = Class.new(klass)
const_set(name, new_klass)

new_klass.class_eval do
establish_connection "test_db_owner"

def ==(comparison_object)
comparison_object.equal?(self) ||
(comparison_object.instance_of?(self.class.superclass) &&
comparison_object.id == id &&
!comparison_object.new_record?)
end

def instance_of?(klass)
self.class == klass || self.class.superclass == klass
end
end

new_klass
end
end



This bit of code defines a new module called TestData. It overrides const_missing? and looks for an existing constant in the root namespace. It creates a new class in the TestData module that is a subclass of the original class. It then tells ActiveRecord to connect as the schema owner. There is some stuff in there to patch == and instance_of? to allow the new object to be compared to the original one.

Now, code like this is quite dangerous and is nothing I'd ever use in real production code. The real point of the spike however, was not figuring out how to connect as a different user, but to see how feasible it would be to modify our tests to use two database users. This little hack only took about 20 minutes to write and allowed us to attack our main problem. Since this was a spike, we knew we were going to throw it all away after we learned what we needed to know.

It turned out that we ran we couldn't use two seperate users easily, because all our test methods ran in transactions. We relied on the transaction rollback to clean up all our inserted test data. We could work around this, but it would take a lot more rework than we had originally planned. Our little TestData module was promptly deleted from our code base.

I am a big fan of any language that gives power to the developer. I don't like to be shackled because some language designer thinks that developers should be protected from themselves. Features like Ruby's const_missing? can be horribly misused and can cause code that is extremely difficult to debug, but it can also be really useful. Our little experiment only took a couple of hours, because we were able to use a powerful, but possibly dangerous feature of Ruby. That module was the quickest way for us to get to the meat of the problem without wasting a lot of time on technical details that we could figure out once we committed to doing the work.

I believe in smart tools for smart developers. Making a language overly safe doesn't really enforce code quality. Bad programmers will write bad code no matter the language. All it does is keep the good ones from accomplishing what they need to do.