Wednesday, May 31, 2006

Use class methods for stubs

Since I believe in unit testing one concrete class at a time I frequently use stubs in my tests. These stubs always return the same value and are unimportant to the current test.

For example, assume you have an Employee class that contains check_email behavior.
class Employee
def initialize(cell_phone, laptop)
@cell_phone = cell_phone
@laptop = laptop
end

def check_email(user, password)
if @laptop.working?
@laptop.check_email(user, password)
else
@cell_phone.check_email(user, password)
end
end
end
In the above example Employee depends on cell_phone and laptop. When testing check_email you should have (at least) two tests, one for the case where @laptop.working? is true and one where it returns false. The second scenario (where @laptop.working? is false) is perfect for stub usage.
class EmployeeTest < Test::Unit::TestCase
class StubLaptop
def working?
false
end
end

...
def test_when_laptop_is_not_working_cell_phone_is_used
# code for setting up a mock for cell_phone
employee = Employee.new(mock_cell_phone, StubLaptop.new)
employee.check_email('jay', 'password')
# code to verify mock
end
end
The above test is correct; however, it can be slightly changed. Because of duck typing and the fact that stubs should always return a constant value it is possible to use class methods instead of instance methods. This relieves you from needing a new instance for each stub.
class EmployeeTest < Test::Unit::TestCase
class StubLaptop
def self.working?
false
end
end

...
def test_when_laptop_is_not_working_cell_phone_is_used
# code for setting up a mock for cell_phone
employee = Employee.new(mock_cell_phone, StubLaptop)
employee.check_email('jay', 'password')
# code to verify mock
end
end

Friday, May 26, 2006

Ruby Stunt Double

In the DSL focused system I'm currently working on we provide what I previously detailed as level 2 syntax checking. The DSL that we've developed is an internal DSL and requires the business user to call methods on objects (not that they have any idea what that means). The system depends on syntax similar to:
open.a.table.today.at 2
The users of the system requested some documentation to help them in building their business rules. Obviously we could have written or generated some documentation, but I thought displaying valid options within the system was a better choice.

The solution involves executing your DSL code in the syntax checking context and having key methods return Stunt Double instances. In the above code open is clearly a DSL keyword. In the syntax checking context open would be defined as:
def open
OpenStuntDouble.new(@messenger)
end
OpenStuntDouble is a class that inherits from StuntDouble and responds to all public instance methods of Open.
class OpenStuntDouble
def initialize(block)
super("open", &block)
end

stand_in_for(ThoughtWorks::Open) { AStuntDouble.new(@messenger) }
end
Any method that is executed on OpenStuntDouble will return a new instance of AStuntDouble. However, any method call that results in method_missing being executed will be reported as an invalid method call. Each invalid method call will also report the full list of available methods. Using this error you can provide your users with feedback on valid syntax.

Of course, the majority of the magic is in the StuntDouble class.
class StuntDouble

alias __methods__ methods
alias __class__ class

def initialize(name, &block)
raise "a messenger proc is required for stunt double" unless block_given?
@messenger = block
@name = name
end

def self.stand_in(*array)
block = block_given? ? Proc.new : Proc.new {}
array.each do |element|
define_method(element.to_sym, &block)
end
end

def self.stand_in_for(mod)
block = block_given? ? Proc.new : Proc.new {}
stand_in(*mod.public_instance_methods, &block)
end

def method_missing(sym, *args)
@notify_block.call "#{does_not_support(sym)} #{does_support}"
end

private

attr_reader :name

def does_support
return "Supported: #{valid_methods}." if valid_methods != ''
"Nothing is supported."
end

def does_not_support(sym)
"#{name} does not support #{sym.to_s}."
end

def valid_methods
result = self.__class__.public_instance_methods.sort.select do |operation|
!@@excluded.include? operation
end
result.join(', ')
end


@@excluded = public_instance_methods.select { |method| method =~ /^__.+/ }
@@excluded += %w(to_s inspect method_missing instance_eval)

instance_methods.each { |m| undef_method m unless @@excluded.include? m }

end
Of course, no code is complete without tests.
require File.expand_path(File.dirname(__FILE__) + "/../test_helper")

class StuntDoubleTest < Test::Unit::TestCase
class Inner < BlankSlate
def included_from_elsewhere
end
end

class FooStuntDouble < StuntDouble
end

class BarStuntDouble < StuntDouble
end

def setup_foo
FooStuntDouble.stand_in(:bar) { }
FooStuntDouble.stand_in_for(Inner)
end

def test_name_is_returned_from_message
setup_foo
stunt = FooStuntDouble.new("foo") do |error|
assert_equal 'foo does not support zeb. Supported: bar, included_from_elsewhere.', error
return
end
stunt.zeb
fail 'assertion skipped'
end

def test_name_is_returned_from_message_but_nothing_supported
stunt = BarStuntDouble.new("bar") do |error|
assert_equal 'bar does not support zeb. Nothing is supported.', error
return
end
stunt.zeb
fail 'assertion skipped'
end

def test_methods_are_added_from_array
setup_foo
stunt = FooStuntDouble.new("foo") do |error|
fail "error"
end
stunt.bar
end

def test_methods_are_added_from_class
setup_foo
stunt = FooStuntDouble.new("foo") do |error|
fail "error"
end
stunt.included_from_elsewhere
end

end
The end result is user friendly errors that can be displayed directly to your users.
open does not support the. Supported: a.
An advantage to this form of syntax help is that as the system evolves so will the help without any additional effort.

Thursday, May 25, 2006

Practical Ruby

My current project team started a blog for quick gotchas we discover while working on our project.

Pair Programming Anti-Patterns

Pair programming is hard. Previous to working at ThoughtWorks I had a manager who requested that the team do pair programming. The idea failed miserably, but it wasn't pair programming that was flawed, it was our approach. Below is a short list of the mistakes I've witnessed, but it's by no means a complete list.
  • People who don't care. This is the biggest pair programming killer. If your employees are only there for the paycheck they will make pair programming fail. Getting two employees on the same schedule is hard. Once two employees get on the same schedule one will daydream while the other works. This is very boring, but to people who don't care, it's better than working.
  • Strong code ownership. It's often very hard to motivate people to care about code they aren't responsible for. For more info on code ownership see Martin's bliki entry.
  • Inconsistent workstation setup. People like to work in their own environment. Unfortunately, when pairing you are unlikely to find two people who agree on what an environment should be. The solution is to provide pairing stations with standard setups. Instead of trying to learn multiple environments, the team can work on one shared setup.
  • Small work area. People like to be comfortable. Putting two chairs in one cube where one person's view is obstructed is very unlikely to produce good results. On the ThoughtWorks projects I've been staffed on we always have a project room that has enough room to sit side by side, two monitors that mirror the desktop, two mice, and two keyboards. This allows either person to take control when necessary.

Wednesday, May 24, 2006

Ruby extend and include

Module.include(module, ..) is commonly used to mix modules into classes and other modules. When a module is included the constants, methods, and module variables of the module are added to the including module or class instances.
module Actions
def left(steps)
Movement.new(self, steps)
end
end
The Actions module can be included to allow a class to generate movements.
class Car
include Actions
end
After Actions is included left can be executed by any instance of Car.
car = Car.new
movement = car.left

Similarly, Object.extend(module, ..) adds the instance methods from each module given as a parameter. However, extend adds the methods to one instance, not to all instances.
car = Car.new
car.extend Actions
movement = car.left
The above code gives car the same behavior as include would, except only the instance that called extend would have this new behavior. Therefore, the above code is valid, but this code would result in an error:
car = Car.new
car.extend Actions
car2 = Car.new
movement = car2.left #calling 'left' here is invalid because car2 does not extend Actions
extend is commonly used to mix instance methods of a module into a class.
module AttributeInitializer
def attr_init(name, klass)
eval "define_method(name) { @#{name} ||= klass.new }"
end
end

class Statement
extend AttributeInitializer

attr_init :charges, Array
end
Many DSL style class methods are added by extending a module instead of including it.

For another example of correct extend usage see Forwardable from the standard library.

Tuesday, May 23, 2006

Law of Demeter and Forwardable

While developing software I often see Law of Demeter violations. These days I seem to see more of this, probably because Ruby on Rails allows you to easily navigate between objects based on table relationships. For example, if you are working on a partial that displays a charge from a credit card statement it wouldn't be surprising to see:
charge.statement.customer.name
The above code could be used to display the customer's name in the partial. Unfortunately, it assumes statement will have a customer and customer will have a name. This is easily fixed by changing charge to only talk to it's friends.
charge.customer_name
The simple fix to support this is to define customer_name in charge, and customer_name in statement
class Charge
def customer_name
statement.customer_name
end
end

class Statement
def customer_name
customer.name
end
end
This change is simple enough; however, as the list of methods that require delegation grows your class can become littered with delegation code.

Luckily, Forwardable is included in the standard library. Forwardable allows you delegate method calls to an object, on a method by method basis. Using Forwardable the above code becomes:
class Charge
extend Forwardable
def_delegators :statement, :customer_name
end

class Statement
extend Forwardable
def_delegator :customer, :name, :customer_name
end
Forwardable becomes even more valuable when you need to delegate several methods
def_delegators :amount_info, :units, :fractions, :currency
For more info on Law of Demeter and it's advantages check out the definition on Wikipedia. For more info on Forwardable check out the documentation on Ruby-Doc.

Friday, May 19, 2006

Syntax Checking an internal DSL

"What about syntax checking?" is the most common question I receive concerning Domain Specific Languages. In my experience it depends on what level of freedom you want to give your users.

The simplest form of syntax checking I usually see is ruby syntax verification:
def valid_ruby?(text)
begin
ReceiveAny.new.instance_eval(text)
true
rescue SyntaxError => syn_err
yield "error on line #{extract_line_number(syn_err.message)}" if block_given?
false
end
end
In the above code ReceiveAny relies on method missing magic to allow any method call to work.

Verifying method calls and parameters is the next common level of syntax checking. Verification at this level can be achieved by evaluating the script in a syntax checking context.

In my previous example of evaluating a script in various contexts I used a script that represented some of the business rules of a poker room. Building from that example I have a similar script that clearly contains errors.
if the '$1-$2 No Limit' list is more than a then notify the floor to open
if the '$1-$2 No Limit' list is more than 1 then notify the floor to opeeen
if the '$1-$2 No Limit' list is more than z then ntify the floor to open
if the '$1-$2 No Limit' list is more than 1 then notify the floor to open
When syntax checking you could validate every method call; however, (especially if you are using bubble methods) you will more likely only need to validate key methods. For example you would want to validate that the more method was given a numeric value.
  def more(number)
@errors << "more than should be followed by a number" unless number.kind_of?(Numeric)
end
After validating methods and parameters, the last method to execute should return all reported errors.
  def notify(arg)
@errors.join(', ')
end
However, the last method executed could also be an invalid method (see line 2 of the sample invalid script). Because of this, method_missing should also return the errors.
  def method_missing(sym, *args)
if sym.to_s =~ /^dollar\d+dashdollar\d+space(Nospace)*Limit/
return true
end
@errors << "#{sym.to_s} is an invalid keyword"
@errors.join(', ')
end
In the example each line is executed individually. Because of this the returned errors will be specific to only one line.
    rules.each_with_index do |rule, index|
result = self.new.instance_eval(rule)
yield result, index if block_given? && result.any?
end
A benefit to executing each line individually is that errors can be reported with their associated line numbers.
Syntax Check:
errors on line 0, (a is an invalid keyword, more than should be followed by a number)
errors on line 1, (opeeen is an invalid keyword)
errors on line 2, (z is an invalid keyword, more than should be followed by a number, ntify is an invalid keyword)
Sample code for the SyntaxCheckingContext is available here.

The next common level of syntax checking I have encountered is using regular expressions to validate the structure of the script. This is the most extreme in my opinion because it either requires very complex regular expressions, or it limits the user from taking advantage of the underlying language (Ruby in my examples). I won't go into much detail on this subject because I haven't had the need for it personally. However, it is an option to be aware of.

Hiding the Parenthesize Warning in Ruby

If you execute the sample code for the Executing an internal DSL in multiple contexts entry you will see results similar to this:
Context One:
(eval):1: warning: parenthesize argument(s) for future version
(eval):1: warning: parenthesize argument(s) for future version
(eval):1: warning: parenthesize argument(s) for future version
(eval):1: warning: parenthesize argument(s) for future version
(eval):1: warning: parenthesize argument(s) for future version
(eval):1: warning: parenthesize argument(s) for future version
(eval):1: warning: parenthesize argument(s) for future version
(eval):1: warning: parenthesize argument(s) for future version
$5-$10 Limit
action open
position floor
...
The code was just sample code so I wasn't very concerned with hiding the warnings; however, since several people asked how to do it I thought I'd do a quick follow up entry.

The code required to silence warnings can be found in the Rails framework (activesupport/lib/active_support/core_ext/kernel/reporting).
module Kernel
def silence_warnings
old_verbose, $VERBOSE = $VERBOSE, nil
yield
ensure
$VERBOSE = old_verbose
end
end
After adding the above code to your codebase (or, if you are writing a Rails app it's already included) you can execute your code as a block to silence_warnings and no warnings will be shown.
silence_warnings do
puts "\nContext One:"
ContextOne.execute(script) do |notification|
Broadcast.notify(*notification)
end

puts "\nContext Two:"
ContextTwo.execute(script) do |stakes|
puts ContextTwo.sym_to_stakes(stakes)
end

puts "\nContext Three"
ContextThree.execute(script) do |positions|
puts positions
end
end

The results are much quieter after silencing the warnings
Context One:
$5-$10 Limit
action open
position floor
$1-$2 No Limit
action open
position floor
$5-$10 Limit
action announce
position brush
$1-$2 No Limit
action announce
position brush

Context Two:
$5-$10 Limit
$1-$2 No Limit
$5-$10 Limit
$1-$2 No Limit

Context Three
floor
floor
brush
brush
Updated Sample Code

Monday, May 15, 2006

Apple in Detail

I recently bought a MacBook Pro and I'm quite happy with the purchase. Apple's attention to detail is amazing.

If you are holding out or still deciding, take the jump, you won't regret it.

Developing Ruby in TextMate

I recently made the switch from IntelliJ to TextMate. So far I'm happy despite losing some features such as local history and Subversion integration. I haven't really found anything in TextMate that I couldn't do in IntelliJ, but I find I'm happier in TextMate so far. I think fighting with IntelliJ to work with Ruby wore on me. I also found IntelliJ was slightly annoyingly slow.

If you haven't already, I suggest giving TextMate a chance.

Tuesday, May 09, 2006

DRY code, DAMP DSLs

Everyone knows code should be DRY, but does the same rule apply to Domain Specific Languages? Based on my experience designing a DSL based system for a major bank, I believe the answer is no.

One reason for using a Domain Specific Language is to separate the business rules from the complexities of designing the system. When done correctly, the business rules can be maintained by business users who are the most familiar with the problem space. To a business user a DSL should be no different than a group of phrases that describe the rules for running the business correctly.

A well designed Domain Specific Language will appear as Descriptive And Meaningful Phrases.

In my previous post I described a DSL designed for running a poker room. I defined the syntax of the DSL as:
if the '$5-$10 Limit' list is more than 12 then notify the floor to open
In the example I defined a bubble method that created methods for each member of the list passed to bubble. Each method that was defined by bubble took one value and returned the same exact value. This allowed the DSL to be verbose enough that not every word was required to have meaning. In fact 'the', 'list', 'is', 'than', and 'to' are all bubble methods. Without bubble methods the DSL can be DRYed out to read:
notify floor open if '$5-$10 Limit' more 12
However, the meaning of the business rule has been lost at the expense of removing the duplication.

As businesses change, their software requires changes also. By providing a meaningful syntax such as "if the '$5-$10 Limit' list is more than 12 then notify the floor to open" the software can be altered by poker room managers, casino executives, or anyone well educated on poker room management. However, with every word that is removed the message becomes less descriptive and thus less maintainable.

A sure sign that there is room for improvement is when a DSL requires training to understand. An ideal DSL contains phrases that are descriptive and meaningful enough that they require no explanation at all.

Saturday, May 06, 2006

Executing an internal DSL in multiple contexts

Creating an internal DSL (or embedded DSL) is challenging, but it does provide many advantages. One advantage to expressing your business rules in an internal DSL is the ability to execute them in various contexts. By executing the DSL in various contexts you can generate multiple behaviors from the same business rule. When the rule changes over time, all parts of the system that reference the rule will also be changed.

For example assume you work for a casino and you have been tasked with designing a system that will notify the poker room employees when a new table needs to be opened or when you are looking to open a new table. The rules for opening a table vary based on the stakes of the table and the length of the waiting list. For example, you need more people waiting for a no limit game because people go broke more quickly and you don't want the table to be short-handed shortly after you open it. The rules would be expressed in your DSL like this:
if the '$5-$10 Limit' list is more than 12 then notify the floor to open
if the '$1-$2 No Limit' list is more than 15 then notify the floor to open
if the '$5-$10 Limit' list is more than 8 then notify the brush to announce
if the '$1-$2 No Limit' list is more than 10 then notify the brush to announce
The first context in which I will execute the DSL is the context that notifies the employees.
class ContextOne < DslContext

bubble :than, :is, :list, :the, :to

def more(value)
'> ' + value.to_s
end

def method_missing(sym, *args)
@stakes = sym
eval "List.size_for(sym) #{args.first}"
end

def floor(value)
__position(value, :floor)
end

def brush(value)
__position(value, :brush)
end

def open
__action(:open)
end

def announce
__action(:announce)
end

def __action(to)
{ :action => to }
end

def __position(value, title)
value[:position] = title
value
end

def notify(value)
[@stakes, value]
end

end
ContextOne uses the DSL to check the List for the size per stakes and sends notifications when necessary. This is of course sample code and my List object is just a stub to verify that everything works correctly. I'll add a link to the sample code at the end of the post.

Based on this same script you could execute a second context that returns a list of the different games that are currently being spread.
class ContextTwo < DslContext

bubble :than, :is, :list, :the, :to, :more, :notify, :floor, :open, :brush

def announce
@stakes
end

alias open announce

def method_missing(sym, *args)
@stakes = sym
end

end
As you can see, adding additional contexts is very easy. Another could be added to display all positions that are set up to receive notices.
class ContextThree < DslContext

bubble :than, :is, :list, :the, :to, :more, :notify, :announce, :open, :open

def announce; end
def open; end

def brush(value)
:brush
end

def floor(value)
:floor
end

def method_missing(sym, *args)
true
end

end
Executing a DSL script in multiple contexts begins to blur the line between code and data. The script 'code' can also be executed to do things such as generate reports (i.e. A report of which employees are contacted by the system). The script could also be executed in a context that will show how long before a table will be opened (i.e. the rule states that 15 are needed, the system knows 10 are on the list so it displays the message '5 more people needed before the game can start').

A note on implementation: In my experience it is much easier to create a class per context and execute in the scope of that object. An alternative is to execute the script in the scope of one object that creates a generic object graph. The problem with this approach is finding an object graph that is generic enough to be useful in several situations. Clearly, I prefer the first approach.

Sample Code: http://www.jayfields.com/src/dslcontext.txt

Friday, May 05, 2006

IntelliJ Ruby Syntax Highlighting Plugin

I'm very happy to see that the previous hack I detailed for IntelliJ is no longer necessary.

Following my post (a few days later) I got this comment:
Quick follow-up: I spent quite a few evenings working on a generic highlighter (with basic Ruby highlighting as the example config). You may want to have a look here.

Cheers, Daniel

My initial impression was not very good. Then I realized that few options in Colors & Fonts (CTRL + ALT + S, F) were set by default. I made a few quick changes to the color scheme that I prefer and was quite pleased.

Also, I made a few changes in the config to add some extra support:

In simplesyntax_ruby.config I added:
regex SYMBOLS => :[a-z][A-Za-z0-9_]+
descriptions[ SYMBOLS ] = Symbols

This change supports highlighting symbols.

I also modified the tags\keywords.rb file change my keyword array to be:
KEYWORDS = ["alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined", "do", "else", "elsif", "END", "end", "ensure", "false", "for", "if",
"in", "module", "next", "nil", "not", "or", "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless", "until", "when",
"while", "yield"]


Overall, super job Daniel.

Monday, May 01, 2006

Setting up a printer

As a consultant I'm constantly working from different locations and printing to foreign printers. For some reason, printers seem to be a black art to most of us who are otherwise quite comfortable working with technology. I too used to fear printers until Pat Sarnacke showed me the one true way to enlightenment: Printing to a Standard TCP/IP Port.

steps to printer nirvana:
  1. Print the configuration of the printer to get the printer's IP address
  2. Plug in to the same network the printer is on. (ping if necessary to find out)
  3. Open the windows add printer wizard
  4. Select "Local printer attached to this computer" AND uncheck "Automatically detect and install my Plug and Play printer"
  5. Select "Create a new port:"
  6. Set "Type of port:" to "Standard TCP/IP Port"
  7. The Add Standard TCP/IP Printer Port Wizard should appear, click Next
  8. Enter the IP address into the "Printer Name or IP Address" textbox
  9. Use the default "Port Name", click Next (The 2nd wizard should close)
  10. Select your printer from the list
  11. Give your new printer a name
  12. Do not share, print a test page, and click Finish because you are done.
You now possess the knowledge to print from any random printer your heart desires.

Why do *YOU* like Ruby?

An old friend of mine recently sent me this:
In short, why do *YOU* like Ruby?
It's a fair question. I'm currently developing exclusively in Ruby and writing almost only about Ruby. The short answer is Ruby requires less to get the job done. I'll elaborate, but remember, this is why *I* like Ruby, not an attempt to compare Ruby to any other language.

#1. It's easy to add behavior to objects. You can extract patterns and put them in modules or add them to existing classes. Once you have added the behavior you can quickly add responsibilities to your objects with much less code. Since I've been developing in Ruby I've found myself using Attribute Initializer and Initialization Chain quite often. By having the patterns for both of these behaviors extracted out to class methods I can reduce the code necessary which also reduces the potential for errors.

#2. Ruby's duck typing allows me to easily create dependencies. I strongly believe in the Unit Testing Guidelines I previously posted. The guideline I suggest in that entry is: Only one concrete class (with behavior) should be used per test. Because of duck typing I can follow this rule by creating stub dependencies without worrying about interfaces. Consider the following class:
class Consultant
def initialize(boss, phone, laptop)
@boss, @phone, @laptop = boss, phone, laptop
@phone.on if @phone.off?
@laptop.on if @laptop.off?
end

def text_boss(message)
@phone.text(message,@boss.number)
end

def send_email(email)
@laptop.send_email(email)
end
end
Consultant has a dependency on Boss, Phone, and Laptop. Additionally, when a Consultant instance is created it calls the on method of both the phone and laptop. Because the Consultant instance calls methods on phone and laptop in the constructor, nil cannot be passed as either argument.

Now, I want to test the Consultant class in isolation so I need to create stubs for Phone, Laptop, and Boss. In a statically typed language I would need a Phone, Boss and Laptop interface and each stub would need to implement the full behavior of the interface. However, in Ruby I can create simple stubs that only define behavior I'm interested in:
class StubLaptop; def on; end; def send_email(e); end; end
class StubPhone; def on; end; def text(msg, num); end; end
class StubBoss; def number; end; end;
Now I can use these stubs and define mocks that allow me test only the isolated Consultant class and it's interactions. Also, these stubs are really only in the test for support, thus making them essentially noise. The less noise I am required to include in a test the more readable (and maintainable) the test becomes.

#3. The dynamic features of the language allow me to more easily write Domain Specific Languages (DSL). At my current project we've provided the client with a domain specific language that allows definition of variables and reuse of those variables later in the script.

In the script a variable is defined similar to define :jay => thoughtworks.developer. Obviously, we are really using Ruby to call the method define with a hash where :jay is the key and thoughtworks.developer is the value. When the define method is executed it defines a method dynamically by the key and sets the return value to the value of the hash. Later in the script the variables are used similar to work jay, mike, charles. Again, no magic here, the work method is being called with the return values from the jay, mike, and charles methods. However, the end result is a very readable DSL which empowers my business users to code part of the system.

The same functionality could be achieved by changing the work line to read work :jay, :mike, :charles and storing the values in a hash. But, this is a step down from the above syntax in most business users eyes.

Similarly, I recently had a requirement build an ad-hoc sentence using dot notation. For example, this.was.the.syntax.but.the.sentence.needs.to.be.free.form. By using method_missing I was able to support this style with very little code required other than protecting keywords.