Posts Tagged ‘Moby’

Using maroon to do Injectionless DCI part II

Posted: February 25, 2013 in DCI
Tags: , , ,

In the first part of this series we looked at how to install Moby maroon and how to write a simple context with roles. In this post we are going to look at two simple aspects of maroon. The first one is if you wish to have a base class for your context. In the below example the Account class is used as the base class for the context. This will seldom be needed when doing pure DCI but it is possible to do it when the need arises

class Account
   attr_accessor :account_id
end

context :Account_context Account do
   #implement the context
end

The second aspect is how to define a default interaction. In the example from the previous post in this series. There’s just one interaction and it might be worth your while to be able to use the context where you would otherwise have used a callable construct

context :Greeter :greet do
  role :who do
    say do
      self
    end
  end
  role :greeting do end
  greet do
    p "#{greeting} #{who.say}!"
  end
end

You can now use this context in two different ways where a callable construct is needed. Though you can’t transform this to a proc it still servers as a continuation where you can invoke call. The two options are

Greeter.call person1, person2
Greeter.new(person1,person2).call

In the first version whatever arguments you pass will be passed to new of your context class (in this case to Greeter.new) and the default interaction will be invoked on the newly instantiated context object. If you pass more arguments than new expects then the remaining arguments will be passed to the interaction. In the second version where the context object is explicitly constructed any argument passed to call will be forwarded to the default interaction. It’s worth mentioning that you can pass both a base class and a default interaction in which case you would pass the base class as the second argument and the default interaction as the third. In that case you can either pass the Class object as in the previous example or pass a symbol/string representing the name of the class and the name of the interaction.

context :Account :Owned :balance do

and

context :Account Owned :balance do

Have the same result. A context class called Account is defined. It derives from Owned and the default interaction is called balance. As a final remark all the examples in this post has used context rather than Context::define. to use context you’d need to require ‘maroon/kernel’ which adds a method to Kernel called context. context simply delegate to Context::define so the result is the same either way

Advertisements

The artist formerly known as Moby

Posted: February 20, 2013 in DCI, Subtle bugs
Tags: ,

Moby, which was short for Marvin On ruBY had an unfortunate nameclash with the gem moby and was named against recommendations with a capital M. Thanks to Jim Gay and Ted Milkner for pointing this out. I’ve as a result renamed Moby to maroon.

It can be installed using

gem install maroon

How Moby works

Posted: February 18, 2013 in DCI, Thoughts on development
Tags: , ,

As I wrote in my previous post I would write on how Moby maroon works internally. This is definitely not a post explaining DCI. As a matter of fact it might confuse you and potentially impair your understanding of DCI so tread carefully if you are new to DCI. The target audience is Rubyists that want to know how Moby maroon is capable of getting performance on par with regular method invocation and/or those that might want to contribute to Moby maroon and thereby indirectly to Marvin and DCI as well,

The context defined in the previous post is rewritten to an ordinary ruby class the source code of this class is returned as one of two objects from the define method. The first object being returned is the newly created class it self. The second object is the actual source of this class. In the case of the hello world example the source looks like this

class Greeter
   def greet
       p("#{greeting} #{self_who_say}!")
   end

   @who
   @greeting

   private
   def who;@who end
   def greeting;@greeting end
   def self_who_say 
     who
   end
end

As you can see there’s really nothing magically going on. So what did actually happen? Well firstly each role is rewritten to a definition of an instance variable and a getter. So for the who role there’s an instance variable ‘@who’ and a method ‘who’ and similar for the ‘greeting’ role. But there’s no role methods any more, where did the role method go? The last method in the source
def self_who_say
who
end

is where the role method went. The name might hint at this. Role methods are rewritten into instance methods of the context. And this is where you might be confused if you are new to DCI, so it’s worth stressing that this rewrite violates the mental model of DCI. Paradoxically DCI is very much about expressing the mental models and not violating them. A role method should be seen as a part of the role player and never be considered a part of the context.

it would have been safe to rewrite this to

def self_who_say
@who
end

So why isn’t it done? The reason to this is that there’s two rewriting phases in Moby maroon. The first rewrites the use of self to the corresponding role getter and the second rewriting phase depends on the role getter. When a role getter is encoutered the rewriter  will check to see it’s the instance expression of a role method invocation. If it is it will rewrite that invocation. E.g if we changed the who role to

role :who do
    say do
      self
    end
    talk do
      self.say
    end
  end

Then the first phase would rewrite talk to

talk do
who.say
end

And the second phase would the see this as a role method invocation and rewrite it to

def self_who_talk 
  self_who_say  
end

Recollecting from the previous post that if you call a method directly on the instance variable (in this case ‘@who’) it will always be an instance method and never a role method it should be obvious why the first phase rewrites to the role player getter and not the instance variable. Rewriting self to the instance variable would result in the second phase being unable to identify role method invocations.

Having seen how role method invocations are translated into invocations of instance method on the context obejct it should also be clear that there can be no performance difference between calling a role method or calling a regular instance method after all seen from the view of the interpreter role methods are instance methods.

In the next post we will look at how to bind block variables to roles followed by another post on how the rewriting handles this.

Yesterday I published my first gem ever. It’s called maroon and makes injections less DCI possible in Ruby. I hadn’t coded any Ruby prior to this but done similar work in C#. It took quite some time to reach a working compiler when I was creating injectionless DCI for Marvin in C#, a language I’ve been using for more than a decade. So being unfamiliar with Ruby I was surprised how fast I could actually reach a working solution and impressed at how little code was needed.

There was three separate factors that led me to work on this gem. The first two were different discussions. One on stackoverflow.com where a member of the SO community claimed that DCI was always going to be slow compared to regular method invocations and the other on the object-composition google group where something a long the line of “it can’t be done” was postulated. Doing something that can’t be done and doing it faster than possible seemed like fun challenges. The final push was an invitation to wroc_love.rb as a speaker. If I was going to present at a Ruby conference I thought I better learn Ruby.

The rest of this post is going to be a short introduction to maroon.

To get started install the gem

gem install maroon

This might install a few dependencies as well depending on whether they are already installed on your machine (just ordinary package management in work for you)

To follow traditions we could start with a hello world example and then disect that

require 'maroon'

Context::define :Greeter do
  role :who do
    say do
      self
    end
  end
  role :greeting do end
  greet do
    p "#{greeting} #{who.say}!"
  end
end

class Greeter
  def initialize(greeting,who)
    @who = who
    @greeting = greeting
  end
end

Greeter.new('Hello','world').greet #Will print "Hello world!"

The first line just requires the gem. Nothing fancy here.
The second line

Context::define :Greeter do

defines a new context called Greeter. As we will see later a context is simply a class. The difference is in how the methods are handled
Within a context you can define zero or more roles. Though if there’s no roles there’s no need for a context.

The next snippet defines a role called who

role :who do
  say do
     self
  end
end

There’s a single role method in this role which is called ‘say’. The method simply returns the role player. Notice that self in a role method is the role player and not an instance of the type we are defining. This might seem counter intuitive at first but when writing role methods this will feel very natural.

following the role ‘who’ is another role

role :greeting do end

this role does not have any role methods and could be a field (and in reality will be) however following the DCI line of thinking this is a role and we define it as such

The last part of the context is an interaction. Interactions are defined in the same manner as a role method. The only difference is that they are defined directly in the context and not inside a role.

greet do
   p "#{greeting} #{who.say}!"
end

The above snippet defines an interaction called ‘greet’. Interactions can be seen as public instance methods. That is what they will end up being but of course from a DCI perspective they are more than just that. From a DCI perspective interactions represent a graph of communicating objects. It is a core goal of DCI to be able to not only model the objects of a domain but also to model the interactions between these objects as one coherent structure.
In this interaction there’s two interacting objects, represented by the two roles of the context: ‘greeting’ and ‘who’

You can extend the context just like you can extend any other class in Ruby and it will often be advantageous to extend with an initializer that can bind role players to roles since there’s no way of doing this from outside the context.

class Greeter
  def initialize(greeting,who)
    @who = who
    @greeting = greeting
  end
end

We’re binding a role player to each of the roles we have. As you can see role players are kept in a field named after the role.You should only use this field in two cases. When binding as we are doing here and when calling an instance method on the role player where a role method with the same name is defined as well. You can’t call a role method using the field but will have to use the getter with the same name as the role.

The last line of code in the hello world example is where we instantiate the context object and execute the interaction
Greeter.new(‘Hello’,‘world’).greet #Will print “Hello world!”

So that’s our very first DCI program using maroon.

If you are interested in the inner workings of maroon, all you will have to do is execute the above program using irb or print the out put of define to the console. define returns two objects. The first being the newly defined class and the second being the actual source of the class. In the next post I will explain the source code

Injectionless DCI in Ruby part II

Posted: January 30, 2013 in DCI
Tags: , , ,

My latest post was on Injectionless DCI in Ruby was based on an approach using method_missing. I’ve since then diverted from that path. I started bench marking the code against simple ordinary method invocation and I wasn’t satisfied with the result. I could get the invocation of a role method down to a factor of 2.5 compared to a regular method call but could get any further improvement with my code using using method_missing so I needed a different approach which ended in a little piece of code I’ve called Moby it’s heavily inspired by how Marvin works and was surprisingly easy to write in Ruby.

All it really does is transformation of method invocation on roles. If there’s a suiting tole method it will call the role method if not it will send the message to self acting as a Ruby script would otherwise normally have done.

Since this happens at interpretation time there’s no performance hit when actually executing the method invocation. There will be an overload in the start up but once that’s paid there’s no penalty only the DCI goodies such as expressive code, separation between what the system is and what it does.

Being a first release and still having to convert more of the “canonical DCI examples” to use this piece of code I’m sure I’ll have to fix some bugs and make improvements to the code. The next example is the Dijkstra – Manhattan where I’m rewriting Jim Copliens #extend based version found on our fullOO site

When the Dijkstra example is done I will have to learn yet another new skill. How to construct a RubyGem until then the code can be found at http://github/runefs/Moby