軟件絕對領域

          TDDbyEx書中資金例子Ruby完整重現

          早上看了Ruby論壇中有人(blackanger)寫的TDD by Ex這本書里的資金例子,自己也想寫一寫。和他不同,我是全過程詳細寫出來。第一次用Ruby寫代碼,第一次用Ruby的Unit框架,而且下午睡醒后迷迷糊糊寫的,可能有很多錯誤,請多多指正。

          第一次迭代后的代碼(簡單的TDD代碼)

          #?file?tc_doller.rb

          $:.unshift?File.join(File.dirname(
          __FILE__),?"..",?"src")
          require?
          'test/unit'
          require?
          'dollar'

          class?TestMoney?<?Test::Unit::TestCase
          ????????
          def?testMultiplication
          ????????????????five?
          =?Dollar.new(5)
          ????????????????five.times(
          2)
          ????????????????assert_equal(
          10,?five.amount)
          ????????end
          end

          #?file?doller.rb

          class?Dollar
          ????????
          def?initialize(amount)
          ????????????????@amount?
          =?amount
          ????????end
          ????????
          ????????
          def?times(multiplier)
          ????????????????@amount?
          =?@amount?*?multiplier
          ????????end
          ????????
          ????????
          def?amount
          ????????????????
          return?@amount
          ????????end
          end

          第二次迭代后的代碼
          #?file?tc_doller.rb

          $:.unshift?File.join(File.dirname(
          __FILE__),?"..",?"src")
          require?
          'test/unit'
          require?
          'dollar'

          class?TestMoney?<?Test::Unit::TestCase
          ????????
          def?testMultiplication
          ????????????????five?
          =?Dollar.new(5)
          ????????????????product?
          =?five.times(2)
          ????????????????assert_equal(
          10,?product.amount)
          ????????????????product?
          =?five.times(3)
          ????????????????assert_equal(
          15,?product.amount)
          ????????end
          end

          #?file?doller.rb

          class?Dollar
          ????????attr_reader?:amount
          ????????protected?:amount
          ????????
          ????????
          def?initialize(amount)
          ????????????????@amount?
          =?amount
          ????????end
          ????????
          ????????
          def?times(multiplier)
          ????????????????
          return?Dollar.new?@amount?*?multiplier
          ????????end
          end

          第三,四次迭代后的代碼(添加了相等性測試,剛好Ruby中的equal?和==的語意和Java相反)
          #?file?tc_doller.rb

          $:.unshift?File.join(File.dirname(
          __FILE__),?"..",?"src")
          require?
          'test/unit'
          require?
          'dollar'

          class?TestMoney?<?Test::Unit::TestCase
          ????????
          def?testMultiplication
          ????????????????five?
          =?Dollar.new(5)
          ????????????????product?
          =?five.times(2)
          ????????????????assert_equal(
          10,?product.amount)
          ????????????????product?
          =?five.times(3)
          ????????????????assert_equal(
          15,?product.amount)
          ????????end
          ????????
          ????????
          def?testEquality
          ????????????????
          assert(Dollar.new(5)?==?Dollar.new(5))
          ????????????????
          assert(Dollar.new(5)?!=?Dollar.new(6))
          ????????end
          ????????
          end

          #?file?doller.rb

          class?Dollar
          ????????attr_reader?:amount
          ????????protected?:amount
          ????????
          ????????
          def?initialize(amount)
          ????????????????@amount?
          =?amount
          ????????end
          ????????
          ????????
          def?times(multiplier)
          ????????????????
          return?Dollar.new?@amount?*?multiplier
          ????????end
          ????????
          ????????
          def?==(obj)
          ????????????????
          return?obj.amount?==?@amount
          ????????end
          end

          第五,六,七次迭代后的代碼(短命的Franc對象登場)
          #?file?tc_doller.rb

          $:.unshift?File.join(File.dirname(
          __FILE__),?"..",?"src")
          require?
          'test/unit'
          require?
          'money'
          require?
          'dollar'
          require?
          'franc'

          class?TestMoney?<?Test::Unit::TestCase
          ????????
          def?testMultiplication
          ????????????????five?
          =?Dollar.new(5)
          ????????????????assert_equal(Dollar.new(
          10),?five.times(2))
          ????????????????assert_equal(Dollar.new(
          15),?five.times(3))
          ????????end
          ????????
          ????????
          def?testEquality
          ????????????????
          assert(Dollar.new(5)?==?Dollar.new(5))
          ????????????????
          assert(Dollar.new(5)?!=?Dollar.new(6))
          ????????????????
          assert(Franc.new(5)?==?Franc.new(5))
          ????????????????
          assert(Franc.new(5)?!=?Franc.new(6))
          ????????????????
          assert(Franc.new(5)?!=?Dollar.new(5))
          ????????end
          ????????
          ????????
          def?testFrancMultiplication
          ????????????????five?
          =?Franc.new(5)
          ????????????????assert_equal(Franc.new(
          10),?five.times(2))
          ????????????????assert_equal(Franc.new(
          15),?five.times(3))
          ????????end
          end

          #?file?doller.rb

          class?Dollar?<?Money
          ????????
          def?initialize(amount)
          ????????????????super(amount)
          ????????end
          ????????
          ????????
          def?times(multiplier)
          ????????????????
          return?Dollar.new(@amount?*?multiplier)
          ????????end
          end

          #?file?franc.rb

          class?Franc?<?Money
          ????????
          def?initialize(amount)
          ????????????????super(amount)
          ????????end
          ????????
          ????????
          def?times(multiplier)
          ????????????????
          return?Franc.new(@amount?*?multiplier)
          ????????end
          end

          #?file?money.rb

          class?Money
          ????????attr_reader?:amount
          ????????protected?:amount
          ????????
          ????????
          def?initialize(amount)
          ????????????????@amount?
          =?amount
          ????????end
          ????????
          ????????
          def?==(obj)
          ????????????????
          return?obj.amount.equal?(@amount)
          ????????end
          end

          第八,九,十,十一次迭代(消除子類,很巧妙的一步)
          #?file?tc_doller.rb

          $:.unshift?File.join(File.dirname(
          __FILE__),?"..",?"src")
          require?
          'test/unit'
          require?
          'money'

          class?TestMoney?<?Test::Unit::TestCase
          ????????
          def?testMultiplication
          ????????????????five?
          =?Money.dollar(5)
          ????????????????assert_equal(Money.dollar(
          10),?five.times(2))
          ????????????????assert_equal(Money.dollar(
          15),?five.times(3))
          ????????end
          ????????
          ????????
          def?testFrancMultiplication
          ????????????????five?
          =?Money.franc(5)
          ????????????????assert_equal(Money.franc(
          10),?five.times(2))
          ????????????????assert_equal(Money.franc(
          15),?five.times(3))
          ????????end
          ????????
          ????????
          def?testEquality
          ????????????????
          assert(Money.dollar(5)?==?Money.dollar(5))
          ????????????????
          assert(Money.dollar(5)?!=?Money.dollar(6))
          ????????????????
          assert(Money.franc(5)?!=?Money.dollar(5))
          ????????end
          ????????
          ????????
          def?testCurrency
          ????????????????assert_equal(
          "USD",?Money.dollar(1).currency)
          ????????????????assert_equal(
          "CHF",?Money.franc(1).currency)
          ????????end????????
          end

          #?file?money.rb

          class?Money
          ????????attr_reader?:amount,?:currency
          ????????protected?:amount
          ????????
          ????????
          def?initialize(amount,?currency)
          ????????????????@amount?
          =?amount
          ????????????????@currency?
          =?currency
          ????????end
          ????????
          ????????
          def?self.dollar(amount)
          ????????????????
          return?Money.new(amount,?"USD")
          ????????end
          ????????
          ????????
          def?self.franc(amount)
          ????????????????
          return?Money.new(amount,?"CHF")
          ????????end
          ????????
          ????????
          def?times(multiplier)
          ????????????????
          return?Money.new(@amount*multiplier,?@currency)
          ????????end
          ????????
          ????????
          def?plus(addend)
          ????????????????
          return?Money.new(@amount?+?addend.amount,?currency)
          ????????end
          ????????
          ????????
          def?==(obj)
          ????????????????
          return?obj.amount.equal?(@amount)?&&?(obj.currency?==?@currency)
          ????????end
          end

          最后的一部分
          最后是完成不同貨幣之間的計算,引入了兩個新的對象負責處理匯率的Bank和貨幣相加的Sum對象。

          由于Ruby的動態性無須讓Sum和Money實現同一接口,反正原書中的Expression對象也是為了Sum和Money對象可以通信。或許可以把Sum簡化掉,有空時再想想。

          #?file?tc_doller.rb

          $:.unshift?File.join(File.dirname(
          __FILE__),?"..",?"src")
          require?
          'test/unit'
          require?
          'money'
          require?
          'bank'
          require?
          'sum'

          class?TestMoney?<?Test::Unit::TestCase
          ????
          def?testDollarMultiplication
          ????????five?
          =?Money.dollar(5)
          ????????assert_equal(Money.dollar(
          10),?five.times(2))
          ????????assert_equal(Money.dollar(
          15),?five.times(3))
          ????end
          ????
          ????
          def?testFrancMultiplication
          ????????five?
          =?Money.franc(5)
          ????????assert_equal(Money.franc(
          10),?five.times(2))
          ????????assert_equal(Money.franc(
          15),?five.times(3))
          ????end
          ????
          ????
          def?testEquality
          ????????
          assert(Object.new?!=?Money.dollar(1))
          ????????
          assert(Money.dollar(5)?==?Money.dollar(5))
          ????????
          assert(Money.dollar(5)?!=?Money.dollar(6))
          ????????
          assert(Money.franc(5)?!=?Money.dollar(5))
          ????end
          ????
          ????
          def?testCurrency
          ????????assert_equal(
          "USD",?Money.dollar(1).currency)
          ????????assert_equal(
          "CHF",?Money.franc(1).currency)
          ????end
          ????
          ????
          def?testSimpleAddition
          ????????five?
          =?Money.dollar(5)
          ????????sum?
          =?five.plus(Money.dollar(5))
          ????????bank?
          =?Bank.new()
          ????????reduced?
          =?bank.reduce(sum,?"USD")
          ????????assert_equal(Money.dollar(
          10),?reduced)
          ????end
          ????
          ????
          def?testReduceSum
          ????????sum?
          =?Sum.new(Money.dollar(3),?Money.dollar(4))
          ????????bank?
          =?Bank.new()
          ????????result?
          =?bank.reduce(sum,?"USD")
          ????????assert_equal(Money.dollar(
          7),?result)
          ????end
          ????
          ????
          def?testReduceMoney
          ????????bank?
          =?Bank.new
          ????????result?
          =?bank.reduce(Money.dollar(1),?"USD")
          ????????assert_equal(Money.dollar(
          1),?result)
          ????end
          ????
          ????
          def?testReduceMoneyDiffentCurrency
          ????????bank?
          =?Bank.new
          ????????bank.addRate(
          "CHF",?"USD",?2)
          ????????result?
          =?bank.reduce(Money.franc(2),?"USD")
          ????????assert_equal(Money.dollar(
          1),?result)
          ????end
          ????
          ????
          def?testIndentityRate
          ????????bank?
          =?Bank.new
          ????????bank.addRate(
          "USD",?"CHF",?0.5)
          ????????assert_equal(
          1,?bank.rate("USD",?"USD"))
          ????????assert_equal(
          0.5,?bank.rate("USD",?"CHF"))
          ????????assert_equal(
          2,?bank.rate("CHF",?"USD"))
          ????end
          ????
          ????
          def?testMixedAddition
          ????????fiveBucks?
          =?Money.dollar(5)
          ????????tenFrancs?
          =?Money.franc(10)
          ????????bank?
          =?Bank.new
          ????????bank.addRate(
          "CHF",?"USD",?2)
          ????????result?
          =?bank.reduce(fiveBucks.plus(tenFrancs),?"USD")
          ????????assert_equal(Money.dollar(
          10),?result)
          ????end
          ????
          ????
          def?testSumTimes
          ????????fiveBucks?
          =?Money.dollar(5)
          ????????tenFrancs?
          =?Money.franc(10)
          ????????bank?
          =?Bank.new
          ????????bank.addRate(
          "CHF",?"USD",?2)
          ????????sum?
          =?Sum.new(fiveBucks,?tenFrancs).times(2)
          ????????result?
          =?bank.reduce(sum,?"USD")
          ????????assert_equal(Money.dollar(
          20),?result)
          ????end
          end
          #?file?money.rb

          class?Money
          ????attr_reader?:amount,?:currency
          ????
          ????
          def?initialize(amount,?currency)
          ????????@amount?
          =?amount
          ????????@currency?
          =?currency
          ????end
          ????
          ????
          def?self.dollar(amount)
          ????????
          return?Money.new(amount,?"USD")
          ????end
          ????
          ????
          def?self.franc(amount)
          ????????
          return?Money.new(amount,?"CHF")
          ????end
          ????
          ????
          def?times(multiplier)
          ????????
          return?Money.new(@amount*multiplier,?@currency)
          ????end
          ????
          ????
          def?plus(addend)
          ????????
          return?Sum.new(self,?addend)
          ????end
          ????
          ????
          def?==(obj)
          ????????
          return?obj.amount.equal?(@amount)?&&?(obj.currency?==?@currency)
          ????end
          ????
          ????
          def?reduce(bank,?to)
          ????????rate?
          =?bank.rate(@currency,?to)
          ????????
          return?Money.new(@amount?/?rate,?to)
          ????end
          end
          #?file?bank.rb

          class?Bank
          ????attr_accessor?:rates
          ????@@rates?
          =?{}
          ????
          ????
          def?reduce(source,?to)
          ????????
          return?source.reduce(self,?to)
          ????end
          ????
          ????
          def?addRate(from,?to,?rate)
          ????????@@rates[
          "#{from}-#{to}"]?=?rate
          ????????@@rates[
          "#{to}-#{from}"]?=?1?/?rate
          ????end
          ????
          ????
          def?rate(from,?to)
          ????????
          return?1?if(from?==?to)
          ????????
          return?@@rates["#{from}-#{to}"]
          ????end
          end
          #?file?sum.rb

          class?Sum
          ????attr_reader?:augend,?:addend
          ????
          ????
          def?initialize(augend,?addend)
          ????????@augend?
          =?augend
          ????????@addend?
          =?addend
          ????end
          ????
          ????
          def?reduce(bank,?to)
          ????????amount?
          =?augend.reduce(bank,?to).amount?+?addend.reduce(bank,?to).amount
          ????????
          return?Money.new(amount,?to)
          ????end
          ????
          ????
          def?times(multiplier)
          ????????
          return?Sum.new(augend.times(multiplier),?addend.times(multiplier))
          ????end
          end

          posted on 2007-10-03 21:02 _Kai_ 閱讀(850) 評論(0)  編輯  收藏 所屬分類: 敏捷開發Rails

          公告

          碼農一枚

          歡迎大家發E-mail到 與我討論關于軟件開發的各種看法。

          最新Blog地址:http://thekayway.com/

          導航

          <2007年10月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          統計

          常用鏈接

          留言簿(2)

          隨筆分類(21)

          隨筆檔案(18)

          常去的地方

          技術站點

          朋友的Blog

          搜索

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 双江| 泰兴市| 郑州市| 邹平县| 湘潭县| 长寿区| 昌邑市| 吉隆县| 民权县| 淳化县| 车险| 阿巴嘎旗| 洛隆县| 西城区| 三都| 深水埗区| 阳江市| 卢氏县| 汤原县| 牡丹江市| 朔州市| 澄江县| 墨竹工卡县| 澜沧| 德州市| 乌拉特后旗| 太仓市| 苏尼特右旗| 丰原市| 济源市| 青河县| 铁力市| 韶关市| SHOW| 平阳县| 阳江市| 乡城县| 清水县| 宁陕县| 延边| 读书|