Saturday, November 25, 2006

I have just released a new update of Hebruby, the Ruby hebrew date conversion library. It is now available as a proper Ruby gem, and has much improved documentation. If your Rails application needs to convert from julian date to a hebrew date, or from a hebrew date to a julian date, or display a date in hebrew (either in hebrew or transliterated into english) this gem is for you.To install it, just:

gem install hebruby

Thank you to everyone who has helped with Hebruby, especially Joshua Harvey, and enjoy!

Sunday, November 19, 2006

This is another installment in a series about creating domain specific languages with Ruby. In part 1 and part 2 of this series, I created a simple Ruby DSL to describe the relationship between Pets and Persons. Now I will extend the DSL, and use some cool Ruby metaprogramming tricks to demonstrate the power and benefits of using Ruby to create an internal DSL.First, I want to simplify the syntax for declaring things in our DSL. Getting rid of the class definition stuff can make it a lot easier for domain experts to read. A simple, cool declarative style like Rake is what we want to end up with, something like this:

The little bit of DSL niceness is achieved using the class_eval method. The block of code within the "do" block is called in the context of the newly created object. Here is the Ruby code that achieves this for a new Pet:

Now that we have declared all of the Pets and Persons in to the context of a PetShop, we can test the relationships between Pets and Persons is a more general purpose way then in my previous post. The older, more fragile code was this:

dog = Toto.newbird = Tweety.newsnail = Slugworth.new

person = Dorothy.newputs "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"puts

person = Witch.newputs "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"puts

Is Toto a friend of Witch? falseIs Slugworth a friend of Witch? trueIs Tweety a friend of Witch? falseIs Toto a friend of Dorothy? trueIs Slugworth a friend of Dorothy? trueIs Tweety a friend of Dorothy? true

We have simplified the syntax of our domain specific language, and added some additional functionality. We have also been able to reduce the amount of Ruby code required at the same time.

Monday, November 13, 2006

I have usually been in favor of measurement of any possible aspect of the software development process. Proper techniques of gathering and analyzing metrics have been espoused since Capers Jones created the study of software measurement. I was first introduced to many of these concepts in the writings of Steve McConnell, particularly when his book Rapid Development first came out. If a thing cannot be measured, it cannot be easily studied or improved.But any tool, no matter how well intentioned its purpose, can be used for ill. Any system that relies entirely on user entered information can by lied to. Such systems can be gamed, for various purposes. In a very political environment, a rogue group can manipulate their own metrics to gain power over other groups, gain budget, or simply steer the company in the direction of their own egos. Sometimes metrics can be used to hide something important. "But look at our metrics," protests the manager in charge of a spectacular failure.

Even worse, once this starts to happen, the "everybody's doing it" syndrome strikes, and it can spread like a disease. Pity the poor foolish team that actually tries to tell the truth within such a system once this dynamic sets in. They will be punished, sometimes severely, for "not measuring up to the standards of the company".

The best sorts of metrics are collected automatically. All sorts of interesting information can be learned from analysis of the source code repository. Other information can be assessed from other dynamic sources such as number of unit tests passed, or Fitnesse tests, or measuring Running Tested Features. The important thing is that it is a lot more reliable to use metrics that are not so easily fooled by people with various agendas.

Wednesday, November 08, 2006

Previously, I was exploring the basics of DSL creation using Ruby. This post continues sharing my lessons learned while developing a prototype of a domain specific language in the mortgage industry. Since I cannot share the actual code itself belonging to my client, I will continue to extract the useful concepts into these simple examples.

Last time we created a simple Animal DSL class. The important part of that class is this bit that makes sure our DSL like syntax works for the declarative methods:

Now we will create a Person class that can interact with the Animals. Each Person will have a temperament (either mean or nice), and will be carrying some kind of food in their pocket to feed their pet. We will define people using our DSL as follows:

Since we are working with an array, the self.food method has a variable number of parameters, represented using the asterisk in front of the parameters list. The cool little idiom @food ||= [] returns with the current @food variable, or if it is nil, returns an empty array. There is also a has_food? method to tell us if a person is carrying a certain type of food.

Now let us introduce the Pet. We will use the power of Ruby blocks to tell each pet the rules about when it likes a person, or not. Here is the DSL we want to use for the Pets:

class Toto < Pet friend_test do |person| true unless person.temperament == :mean # I like anyone who is not mean end

end

class Tweety < Pet friend_test do |person| true if person.has_food?(:sunflower_seeds) # I like anyone who has sunflower seeds endend

The friend_test method stores a block containing the test for that Pet, and the is_friend? method tests to see if a Pet will be friendly toward a particular Person.Last, we put it all together with some simple code to display the interactions between the People and the Pets:

dog = Toto.newbird = Tweety.newsnail = Slugworth.new

person = Dorothy.newputs "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"puts

person = Witch.newputs "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"

The result of running this code is:

Toto is a friend of Dorothy: trueTweety is a friend of Dorothy: trueSlugworth is a friend of Dorothy: true

Toto is a friend of Witch: falseTweety is a friend of Witch: falseSlugworth is a friend of Witch: true

Using this simple Ruby DSL approach, it is very easy to add a new Person or Pet, just by entering the rules that define its behavior. As the objects in a system become more complex, one of the best ways to manage that complexity is to create an abstraction that hides the ugly bits.

person = Dorothy.newputs "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"puts

person = Witch.newputs "#{dog.class.name} is a friend of #{person.class.name}: #{dog.is_friend?(person)}"puts "#{bird.class.name} is a friend of #{person.class.name}: #{bird.is_friend?(person)}"puts "#{snail.class.name} is a friend of #{person.class.name}: #{snail.is_friend?(person)}"

James Shore just posted a very cool chapterette from his upcoming book on agile development called "The Planning Game". The concept simply enough is that customers and developers work together to plan what features are going to be implemented, and in what order. Customers know what features have the most value to the business, so they get to choose the order in which features are developed. Developers know about the costs, so they get to say how long something is going to take.In the Planning Game, the play is not quite so simple as the description above might suggest. As each team discusses a feature from their perspective (cost vs. value), the requirements for that feature can come into clearer focus, or be negotiated to reduce their cost.More often, what I have experienced is the "Crying Game": whoever cries the loudest gets their way. The outcome of the Crying Game is not a good one. Either arbitrary and unrealistic deadlines are set by customers, or the wrong solution is provided by the developers. The crying doesn't end there; everyone is crying later as the recriminations fly back and forth. The moral of the story is that internal cooperation yields a lot more business value than internal competition.

Saturday, November 04, 2006

I have been working on a prototype of a Ruby domain specific language for one of my clients, a very large financial services company. I have learned a whole bunch of really interesting lessons, which I will share over a short series of posts as I make more progress.

The first thing I tried to do was create a basic bit of DSL tastiness like this:

Just looking at this bit of code, it seems like it should work. However, when trying this, it doesn't work as expected.

pet = Dog.newp pet.number_of_legs # prints nil

In Ruby EVERYTHING is an object. This includes the class objects themselves, not just the instances of class objects! This means that when the number_of_legs method is called, it is actually being called before the actual instance object itself has been created. We need to get to our instance variable, and one way is to copy the class-level instance variable to the instance itself when the actual instance is being initialized like this:

Thursday, November 02, 2006

I just installed the brand new Gmail for Mobile on my Motorola RAZR. In just a matter of a couple moments, I was looking at my Gmail inbox! Gmail for Mobile is a Java-applet that runs on your Java enabled phone. Keeping the network traffic down this way is a lot better option that a WAP-based email solution, which is what I had tried and abandoned previously.

Not having a QWERTY keyboard is a big limitation for smartphones especially where something heavily textual like email is concerned. Gmail for Mobile deals with this thru a clever mapping of hotkeys to the most commonly used functions (delete, in my case).

Between Google Reader, and now this Gmail for Mobile, another bit of my online existence has been sucked into the Googlesphere...and I like it!