Declarative Programming using a Domain Specific Language #2 0

Posted by mjbamford
on Sunday, February 08

Creating instance methods on the fly using declarative-style class methods has been a great learning exercise for me on the dynamism of Ruby. The example I provided in the previous post was a bit contrite. I’ll provide a real-world example of how I used technique.

Most of the users of our business application in the customer services department are not power users. They want to be able to perform the most common functions by clicking on ‘widgets’ on a dashboard. These widgets are large image buttons with memorable, distinguishable graphics and a clear explanation of the function they perform. Each widget represents an action in a controller in the application.

Within the controller, we want to declared the actions that have a corresponding widget on the dashboard:

class StatisticsController < ApplicationController
  widgetize :import, :export
  def import 
    ...
  end
  def export
    ...
  end
end

The widgetize declaration is a class method that creates an instance method ‘widgets’. From the DashboardController, each controller’s widgets can be collected and displayed:

class DashboardController < ApplicationController
  def index
    @widgets = StatisticsController.new.widgets
  end 
end

The widgetize code is:

class ApplicationController < ActionController::Base
  def self.widgetize(*actions)
    define_method(:widgets) do
      actions.collect do |action|
        { :action => action, :controller => self }
      end
    end
  end
end

But it would be written similarly:

def self.widgetize(*actions)
  proc = Proc.new do
    actions.collect do |action|
      { :action => action, :controller => self }
    end
  end
  define_method :widgets, proc
end

def self.widgetize(*actions)
  actions.collect! do |action|
    { :action => action, :controller => self }
  end
  class_eval %Q{
    def widgets
      #{actions.inspect}
    end
  }
end

We illustrated the facility to the representative power user in the customer services department. He was delighted that widgets could be declared so easily. He started envisioning other ways to widgetize the application to lower the cost of use of the application for the business.

Declarative Programming using a Domain Specific Language #1 0

Posted by mjbamford
on Saturday, February 07

I starting programming Ruby (via an initial introduction by Rails) some two years ago. I thoroughly enjoy the language. It’s fun, expansive, creative and economical. Nonetheless, the language throws down interesting challenges – it regularly reveals a new pattern, a new construct, or a new conceptual framework to get things done far more creatively. The language opens up a new way of thinking. I provide an example below.

Code as a Story

Ruby has many features that allow the programmer to define a story in their code. With a bit of coaching, it’s conceivable that a power user (with no coding experience) could read the code and understand what it does. Other languages are designed according to a strict code hierarchy of what goes where, with little license given to the programmer to define their own metaphors. Ruby encourages the development of metaphors that lucidly refer to real world concepts that power users could recognize. The language releases the programmer from the abstract world in code.

Ruby and Rails define class methods that are so well disguised that, although it’s easy to tell what’s going on, it’s not clear how it is being done:

class Message < ActiveRecord::Base
  has_one :sender
  has_many :receivers
  validates_presence_of :subject
  validates_length_of :subject, :maximum  => 200
  validates_length_of :body, :maximum  => 2000
end

A power user should be able to read this Rails code to validate that the business rules have been correctly captured (such as that a message must have a subject). I have always tried to maintain a level of readability of business objects and processes in code that a power user could conceivably digest and discuss.

These methods are class methods on the Message class (or more correctly, they’re singleton methods on the Message class object). This is all very nice, but we’re used to the idea (from statically-typed languages such as Java) that class methods can’t get access to instances of that class. This limits class methods to concepts that are common without variation to all instances of that class.

Not so Ruby. At the occasion of the definition of the Message class, we call the class method has_one, passing in a concept that is common to all messages, that is that every message instance has one sender. But here’s the Ruby benefit that’s so valuable but so disguised. Each message has of course their own unique sender. In statically typed languages, since the has_one method is a class method, and class methods are without variation for all instances of the class, the ridiculous conclusion that all messages have the same sender results.

Ruby’s class methods allow for a declarative syntax to mimic the business’ processes and conventions. This increases readability and code quality by allowing the code to be self-documenting. Concepts in the real-world are translated into code without a lot of intervening abstractness.

Method

Declarative syntax (using class methods) uses Ruby’s dynamical trickery. The class method defines a new instance method on the fly. This newly created instance method can refer to other instance methods and variables. For example: I want to be able to declare the carrier of a message when a define a new class of message (based upon some sort of business domain), like thus:

class SlowMessage < Message
  deliver_by :pigeon
end

class FastMessage < Message
  deliver_by :airplane
end

class ElectronicMessage < Message
  deliver_by :email
end

I then want to be able to call the business-rule inspired code:

message = SlowMessage.new
message.pigeon ...

I break open the Message class to add a new class method delivered_by. In the literature I’ve discovered a couple of ways that Ruby allows you to do this:

class Message
  def self.deliver_by(carrier)
    class_eval %Q{
      def #{carrier}
        "Deliver by #{carrier}"
      end
    }
  end
end

class Message
  def self.deliver_by(carrier)
    define_method(carrier) { "Deliver by #{carrier}" }
  end
end

class Message
  def self.deliver_by(carrier)
    define_method carrier, Proc.new { "Deliver by #{carrier}" }
  end
end

(Admittedly, the second and third methods are essentially the same – passing a block vs. passing a Proc, but the third example brings to mind interesting ideas with that Proc).

Using class_methods and dynamic instance methods, I’ve been able to create a declarative syntax for classes that model the business domain. It has come to be very handy to provide to power users and has significantly increased productivity.

References