Posts Tagged ‘Ruby’

New version of maroon

Posted: May 22, 2013 in DCI
Tags: , ,

Just a few seconds ago I pressed enter after writing

gem push maroon-0.7.1.gem

and I’m pretty satisfied with this version of maroon. The major chnaes are that you now define methods with regular method definition syntax I.e.

def methodname(arg1,...,argn)
end

The other change I made is in how the abstract syntax tree is treated. Maroon has 3 stages

  1. Reading the source
  2. Creating the AST for each method. The AST is represented as a context with the productions playing the roles and productions are in the form of S-expressions
  3. Traversal of the AST and performing the source transformation. In this stage there’s a transformation context where the individual ASTs for each method in turn play a role

One of the reasons why I changed the stages was the AST build as a seperate step, so that other work could be build on top of that. E.g. one of the requirements I wrote of in a previous post. Namely creating a visual representation of the network of interconnected objects that make up a system. That is visually show how the roles in a context connect to each other in various interactions and role methods.

I also feel that Maroon now itself is a pretty good example on how to use maroon and also on how to do DCI. As always the source can be found at at github

Advertisement

Bootstrapping maroon

Posted: April 9, 2013 in DCI, Thoughts on development
Tags: , ,

At #wrocloverb in the begining of March I started to bootstrap Maroon and have now released a fully bootstrapped version. It took longer than I had anticipated based on the time it took me to write maroon in the first place. The main reason for this was that part of the process lead me to find bugs needing fixing or features required to implement maroon that maroon didn’t support(1). Both tasks some what mind boggling. How do you fix a bug in the tool you use to fix said bug? a lot of the time I ended up having two mental models of the same concept and to be honest that’s one more than my mind can handle.
One model was of what the current version was capable of and another was what it was supposed to do. All this was part of the motivation for bootstrapping in the first place and often the reason why a lot of compilers are bootstrapped too. The current state of the code is a mess. I knew it would be. I’m often asked questions like “Is the code then in fact a lot cleaner when using DCI?” and my answer is that it for me depends on how I design the system. If I design as I presented at wroc_love.rb 2013 (top-down) then yes the code is a lot cleaner, however if I design as I often do when not using DCI (bottom-up) then I often find that the code becomes more messy when I try to rewrite it using DCI and maroon was designed bottom-up.
I’ve done some cleaning up but postponed a large part of the cleaning up till the bootstrapping was actually complete so that I had a foundation to test my refactorings against. So the now live version of maroon is a fully bootstrapped version making maroon the most complete example of how to use maroon. The goal of the version thereafter is to clean the code up and make maroon a good DCI example as well. An example I hope to have both James and Trygve review if their time schedules permit. What bugs did I find?

  • Indexers on self didn’t work in role methods, so if an array played a  role you couldn’t do self[1] to get the second element
  • You couldn’t name a class method the same as an instance method. This wasn’t really a big deal because you couldn’t define class methods in the first place but since that’s one of the features added it did become an issue

What features were added?

  • You can define initialize for context classes
  • You can define role methods and interactions with the same name as methods defined for objects of the Context class. E.g. you can define a role method called ‘define’
  • You can define class methods (The syntax for that is still messy but you can do it)
  • You can use splat arguments in role methods or interactions. In general arguments for role methods are discouraged which I heavily violate in the current version of maroon
  • You can use block arguments (&b). The syntax for this is even worse than the syntax for class methods
  • You can choose whether to build the classes in memory or to output a classname.rb file for each generated class. That’s the way the bootstrapping works. I use the current stable version to generate the files of the next version. I then use those generated files to generate an additional set of generated files and the last set of files, which are generated using the upcoming version are then packaged as a gem and pushed.

What features would I still like to add?

  • Default values for arguments to role and interaction methods
  • Make it possible to use all valid method names for role and interaction methods E.g. field_name=, which are currently not possible
  • Cleaner syntax for both block arguments and for defining class methods. I have an idea for this but it won’t be until after I’m done with the cleaning up. It’s going to be an interesting task since it’s probably not going to be backwards compatible. The changes will be small and make the syntax intuitive to ruby programmers (which the current is not for the features in question) but since I’m bootstrapping I’m breaking my own build before I’m done.
  • a strict flag that would enforce a strict adherence to DCI guidelines and a warn flag that would warn if any of those guidelines were violated
  • Add a third option, that instead of creating classes in memory or class files will visualize the network of interconnected roles for each interaction.

(1) Yes it’s a bit strange to talk about bootstrapping. You think/say stuff like ” features required to implement maroon that maroon didn’t support” that sounds kind of nonsensical a lot. The most mind boggling part of that is when debugging…

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

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 III

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

A few weeks back while debating Marvin on the object-composition group we talked about the meaning of ‘this’ in a role method. Today while working on Moby I realized how important it is that self/this point to the role itself inside a role method. It hasn’t bugged me while using Marvin but when using a dynamic language like Ruby where there’s no compiler that will ask “Did you really mean this? because I don’t know what you are trying to do” it’s paramount that the code shows the intention clearly and since DCI is all about clarity this should be reflected in other languages as well. It is already reflected in Marvin, and has been ever since that discussion.

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

Injectionless DCI in Ruby

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

The last few years I’ve been rather active in the DCI community but never really blogged much about it. This post is not going to be my first post on the main DCI concepts either. I’ve been fairly active on the mailing list object-composition, on stackoverflow.com and not least developing the Marvin compiler. One should think with all that activity I’d have enough information to a series of blog post and potentially an entire book and one would probably be right. However this time around I’ll will stick to describing the use of a Ruby tool I’ve recently created.

The first step to creating this tools was learning Ruby altogether. Until recently I’d only read Ruby but never actually coded anything in Ruby nor read a text on the subject and I couldn’t find a better “hello world” that trying to replicate functionality I’d already coded in a different language.

Inspired by a discussion on SO, where you could be led to believe that DCI in Ruby requires using #extend and that it will always be slow I decided to see how many of the tricks used in the Marvin compiler to change C# into Marvin I could replicate in Ruby. From a functional point of view I’m satisfied with the result

The canonical DCI example (MoneyTransfer) looks like this

class MoneyTransfer < Context
#Create a role called source with two role methods 'withdraw' and 'log'
role :source do
    role_method :withdraw do |amount|
           source.movement(amount)
           source.log "withdrawal #{amount}"
    end
    role_method :log do |message|
      p "role #{message}"
    end
  end


#Create a role called source with two role methods 'deposit'

role :destination do
 role_method :deposit do |amount|
 destination.movement(amount)
 destination.log "deposit #{amount}"
 end
end

interaction :transfer do |amount|
 source.withdraw -amount
 destination.deposit amount
end

def initialize(s,d)
 self.source = s
 self.destination = d
end
end

There's three methods in play here to actually generate the code
  • role -> defines a role, the accessor to the current RolePlayer is defined as private
  • role_method -> defines a role method, though it’s defined as a block, that block is never really executed. Instead it’s transformed into an instance method of the context class
  • interaction -> defines a public instance method. The only “magic” here has to do with bookkeeping in relation to the context stack

There’s absolutely no use of #extend. However there’s is some dynamic changes to classes but these are only performed the first time an object of a given type is playing any role and in the odd case where a role method and an instance method clashes then this is handled on a class level as well.


Being a Ruby novice there might be some subtleties I’ve missed or even big no-nos 🙂 however for the MoneyTransfer I’ve verified that


  • An instance method is chosen even if the object is playing two roles in the same context and the ‘other’ role defines a method with the same name (in the example above log is both a role method for source and on the account object I used for testing)
  • A role method is chosen over an instance method if the current role defines a method that clashes with an instance method
  • The role behavior doesn’t leak. I.e. the object looses the capabilities as soon as it stops playing the role (or when accessed outside the role context (pun not intended)
At present the code can be found as a gist