![]() |
[ANN] Handshake, an informal contract system for Ruby
Handshake is an informal contract system for Ruby. It allows
developers to apply clear, concise, and enforceable interfaces to classes, in three forms: - method signatures - class invariants - pre- and post-conditions Note that Handshake will only enforce checked contracts if the $DEBUG flag is set to true (ruby -d). Method signature contracts are applied in the following way: class Foo include Handshake contract [ all, acceptable, arguments ] => return_value def method(arg, ...) ... end Signature contracts accept clauses, which are defined as any object that implements the === method. When specified with a symbol, they will be applied the named method; when specified without one, they will be applied to the next defined method. Handshake comes with a number of useful clauses predefined: contract :foo, any?(String, 0..5) => Symbol contract :sum, many?(Integer) => Integer contract :deposit, positive_n? => Integer It can also apply contracts to varargs and anonymous blocks: contract [ String, [ Integer ] ] => anything def foo(str, *ints) ... contract :each, Block(String => anything) => many?(String) In addition, users can define their own custom project-specific clauses very easily. See the RDoc for Handshake::ClauseMethods for more information. Class invariants accept a message and a block, which is expected to return a boolean value. Their value is checked before and after each method invocation and are scoped to allow checking of instance variables and private methods. class NonEmptyArray < Array include Handshake invariant("should never be empty") { not empty? } end Pre- and post-conditions allow for grouping common sets of assertions, typically those that require checking arguments against one another. All Test::Unit assertions are available, although they raise a Handshake::ContractViolation exception here upon failure. before do |first_half, second_half| assert_equal 10, first_half.length + second_half.length end def accepts_ten_items(first_half, second_half) ... Handshake is implemented by aliasing the new method of any class that includes it. The modified new method returns a proxy object in place of the original object that looks, acts, and feels like the real thing. It acts as a barrier, and all method invocations that cross the barrier are checked against the defined contracts. It differs in this manner from other Ruby DBC-style systems, which generally alias each contract-checked method as necessary. Because of both this and its grave irrelevance to a Rails context, I wouldn't recommend trying to use Handshake with any Rails projects. Handshake is written in pure Ruby, is available as open source under the same license as Ruby, and is installable as a gem (latest version=0.3.0). It lives at http://rubyforge.org/projects/handshake, and the RDoc is available at http://handshake.rubyforge.org. I'd love to hear any comments, criticisms, and suggestions. I'm also presenting Handshake tonight at the Boston Rubygroup and figured, well, I should probably announce the silly thing on ruby-talk first. Brian Guthrie btguthrie@gmail.com http://blog.brianguthrie.com |
| All times are GMT. The time now is 07:23 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.