#!/usr/bin/ruby -w # first draft for Design By Contract class, glarked from ruby-talk. module DBC class DBCError < StandardError ; end class DBCPreError < DBCError ; end class DBCPostError < DBCError ; end class DBCInvariantError < DBCError ; end def pre raise DBCPreError unless yield end def post(klass, method, invariant) raise DBCPostError unless yield if defined? invariant and klass.public_instance_methods(false).include?(method) then raise DBCInvariantError unless invariant() end end end include DBC class Foo #@a def invariant @a != 3 end def initialize @a = 0 end def bar(b) pre { b != 1 } @a += b print "@a = ", @a, "\n" post(Foo, "bar", self) { @a != 2 } end end for i in (0..4) do print "\nTesting foo.bar(#{i})\n" foo = Foo.new begin foo.bar(i) rescue DBCPreError print "DBCPreError happened as expected\n" rescue DBCPostError print "DBCPostError happened as expected\n" rescue DBCInvariantError print "DBCInvariantError happened as expected\n" rescue Exception print "Some unexpected error happened\n" end end