I have been developing in .NET since framework beta 1 (doesn't everyone say that) since 1892. I like many, (or so it seems) .NET developers are looking at other frameworks and platforms like Ruby on Rails due to a frustration with the continuous abominations coming out of Microsoft like RIA services, oData, Entity Framework, Worflow, Silverlight etc. Microsoft continually wants to lower the bar to lesser developers and all this does is....attract lesser developers who offer nothing back. I find myself just hating everything. I also find myself getting angry at the constant ill appropriated blog posts about Domain, Driven Design and other nonsense like CQRS that fill up my RSS reader from the better educated .NET developers. Am I alone in thinking that DDD is just impractical for 99% of all the applications that it is used in and the blue book was pretty dull? I still enjoy C# but the surrounding patterns, practices and new features just really annoy me now. I cannot work out if I am truly this enamoured with Ruby on Rails or is it that it is just different. I am probably just hankering after something new and shiny and Ruby on Rails ticks all the new and shiny boxes for me. I find the dynamic paradigms fascinating and I have been pouring over the source of things like the Rails ORM ActiveRecord for an idea of how to do things differently. The source of ActiveRecord is crazy, crazy, crazy but I do have a better understanding of just what shape shifting is available in a dynmaic language now. One thing, I really do not want to do is to start coding in a Ruby on Rails application, just like I was coding a .NET application. What would be the point? I want to fully explore what a dynamic language has to offer and why so many Java developers before us felt the need to move here.
I am working on a MicroIsv project in my spare time and I came across an interesting decision today which has lead me to this post. My infant product will scrape text from a yellow pages like directory website and then go through a data scrubbing process to make sense of the unstructured data. I could write the data scrubber myself but I would have to start delving into natural language processing or other time consuming concepts that would probably mean postponing the release date of the application to one that stretches beyond my lifetime. Thankfully there are a number of 3rd party webservices, REST webservices or whateverwebservices that can unburden me of this somewhat difficult task. I do not want to favour one just now and I also want to leave the option of changing provider if and when I feel the need. I also do not want to call the service from my unit tests for all the reasons that are usually trotted out for calling external resources with unit tests. The obvious thing to do is to isolate this functionality.
If I was doing this in .NET, I would create a service layer that is defined by an inteface for the requested service just like below:
1 public interface IDataScrubber
2 {
3 Lead ScrubData(Dictionary<string, object> parts);
4 }
I would then autowire this service into the IOC container of my choice that would inject the service via constructor injection into a controller or something where I would use it. This allows me to mock the service and also depend on an interface rather than the concrete implementation.
While looking at a lot of the Ruby source code that I have installed in the form of RubyGems on my hard drive, I just do not see this type of implementation. There are no interfaces in Ruby for starters and you rarely see an IOC container although they do exist. This has led me to seek a way that takes advantage of the flexibility of a dynamic languages. As I said previously, I see little point in writing this application in Ruby as if it were a static language like C#. I want to try to comprehend the power and malleability of a dynamic language.
The first approach does not lean on any dynamic magic, I am just going to suggest using default parameters that are part of Ruby. I can simply suggest a default implementation in the constructor of the Parser class below. Initialize is the constructor of a Ruby object if you did not know.
1 class Parser
2 attr_reader :scrubber
3
4 def initialize(scrubber = DataScrubber.new)
5 @scrubber = scrubber
6 end
7 end
8
9 class DataScrubber
10 #real implementation goes here
11 end
That is ridiculously easy and for simple cases, there is no reason not to use this approach, what could be simpler. In the constructor of Parser, I have a default parameter for the scrubber member variable. This will create the real DataScrubber if none other is offered when creating an instance of Parser. When testing, I can simply create the parser with a stubbed out version of the DataScrubber.
I still do not feel satisfied by this answer and next I want to look at mixins. From what I can tell in Ruby, it seems they use fewer classes than other OO languages like C#. In C# we tend to compose things through a lot of small classes that run under the guise of Separation of Concerns. The problem with this is that there is generally a lot of implementation details needed when creating these interwoven class structures. Hence we have the IOC container to take away this complex creation process that often exists.
With Mixins, we can implement behaviour in one module that gets mixed into one or more classes that should have that behaviour. A good way to ensure that the concerns are, in fact separated is to develop the mixins in a test driven manner.
We could define our DataScrubber in a module like this:
1 module DataScrubber
2 def self.included(base)
3 puts "module included by #{base}"
4 end
5
6 def scrub_data(parts = {})
7 parts.keys.each{|p| puts "doing something with #{parts[p]}"}
8 end
9 end
Note, I am using the hook method included above that fires whenever it is included by another object. The hook method here is purely for illustration but it is useful to know it is there.
This then allows me to test the mixin in isolation like this by mixing it in to a simple empty instance
1 class MixinTest < ActiveSupport::TestCase
2
3 test "should test DataScrubber" do
4 scrubber = Class.new
5
6 scrubber.instance_eval do
7 include DataScrubber
8 end
9
10 scrubber.scrub_data({:one => "one", :two => "two"})
11
12 #assert behaviour here
13 end
14
15 end
Here I am creating a blank instance of an object and passing a block or anonymous method to instance_eval which will evaluate a block in the context of the instance. You can add, override and modify object instances at runtime using instance_eval which is part of Ruby's dynamic playground. I like this approach because we are not having to create a plethora of classes to add behaviour and I can test the behaviour in isolation. If you have ever looked into creating Mixins in .NET then you will know how difficult a task this is.
When it comes to running a unit test against the Parser class that has this functionality mixed in via the include statement, I somehow want to stub out this behaviour when the DataScrubber is mixed into the Parser class like it is below:
1 class Parser
2 include DataScrubber
3
4 def parse()
5 parts = {:one => "one", :two => "two"}
6
7 scrub_data(parts)
8 end
9
10 def initialize
11 end
12 end
As ruby is a dynamic language, this is very easy, here is one way of doing this:
1 test "should stub out DataScrubber" do
2 parser = Parser.new
3
4 parser.instance_eval do
5 undef scrub_data #not strictly necessary
6
7 def scrub_data(parts)
8 puts "stubbed out method"
9 end
10 end
11
12 parser.parse
13 end
Of course any modern platform is defined by the number of mocking frameworks on offer and Ruby certainly has plenty, flexmock is my weapon of choice and below is an example of how I could use flexmock to create a partial mock to return some test data:
1 test "should stub out DataScrubber" do
2 parser = Parser.new
3
4 flexmock(parser).should_receive(:scrub_data).and_return { "some data"}
5
6 result = parser.parse
7
8 #assert result data
9 end
The last approach I am going to mention is inheriting from ActiveResource. I am not sure this is appropriate to me as the service must understand Rails-style URLs and I might not have that luxury with whatever 3rd party service provider, I choose.
If I was approaching this problem in C#, I would say, "I would isolate this functionality in a service that I inject into the controller" but in Ruby, I would say "I would write this as a Ruby module that I include in my class".
Testing, stubbing or mocking are, as is often stated, ridiculously easy.
It is funny to note that when I was musing about this earlier on twitter somebody who describes himself in his bio as a "passionate Rubyist" made the following questionable comment "Composing services with mixins? Ouch, enjoy the impending doom.". I suspect this guy is like me, a .NET developer who now suddenly thinks he is a "rubyist". Another thought is that perhaps real Ruby on Rails guys are thinking of moving onto Clojure or Scala, now that Ruby is no longer as hip as it was.
