Ruby de FizzBuzz

Ab55f7551d7e4e4b2ea07e60dec4279e?s=47 ohto
March 07, 2018

Ruby de FizzBuzz

Introduction to test driven development.
This presentation is based on
https://qiita.com/ohto/items/281d127a7938121556c0

Ab55f7551d7e4e4b2ea07e60dec4279e?s=128

ohto

March 07, 2018
Tweet

Transcript

  1. Ruby de FizzBuzz 2018/3/8 おおとや

  2. おおとや 趣味 – 数学とか – アニメとか – LTとか 最近転職しました!! 2

    / 28
  3. はじめに Qiita 記事を元に作成しました – FizzBuzz Advent Calendar 2017 12/24 –

    Qiita Ruby de FizzBuzz で検索!! 3 / 28
  4. 質問 テスト書いてますか? 4 / 28

  5. 質問 テスト書いてますか? スプレッドシート管理ですか? 5 / 28

  6. 質問 テスト書いてますか? スプレッドシート管理ですか? あかん! 6 / 28

  7. なんであかんのん? • テスト要員が必要 • 時間がかかる • テスト漏れが生じる 7 / 28

  8. なんであかんのん? • テスト要員が必要 • 時間がかかる • テスト漏れが生じる ヒトとカネの無駄 8 /

    28
  9. 目的 テスト書きませう 9 / 28

  10. 目的 テスト書きませう Pros – 動く要求仕様で合意形成 – 自動テスト/CI – すばやいテスト –

    徐々に改善 Cons – 書くのが面倒... 10 / 28
  11. 目的 テスト書きませう Pros – 動く要求仕様で合意形成 – 自動テスト/CI – すばやいテスト –

    徐々に改善 Cons – 書くのが面倒... (゚Д゚)ハァ? 11 / 28
  12. 開発フロー テストファースト!! 仕様作成 合意 テスト作成 開発 テスト 評価 リファクタリング 12

    / 28
  13. 例題 13 / 28

  14. 開発対象 -FizzBuzz 1から順番に数値を出力します。 ただし、下記の条件をみたすとき、 数値の代わりに指定した文字列を出力します。 • 3で割り切れるとき "Fizz" • 5で割り切れるとき

    "Buzz" • 3と5で割り切れるとき "FizzBuzz" 14 / 28
  15. 開発対象 -FizzBuzz 例 1. 1 2. 2 3. Fizz 4.

    4 5. Buzz 6. Fizz 7. 7 8. 8 9. Fizz 10. FizzBuzz 15 / 28
  16. 使用言語 -Ruby Rubyとは… – オープンソースの動的なプログラミング言語で、 シンプルさと高い生産性を備えています。 – エレガントな文法を持ち、自然に読み書きが できます。 https://www.ruby-lang.org/ja/

    16 / 28
  17. 開発 • 仕様 • テスト • 実装 • 評価 17

    / 28
  18. 開発 -仕様 1 から n までの数値について FizzBuzz して、 ファイルに書き込むメソッドを作成 18

    / 28
  19. 開発 -テスト テスト作成 – 1 から 100 までの期待する答えを作成 spec/fizz_buzz.answer とする

    – テストコード(rspec) を作成 – rspec spec でテスト実行 19 / 28
  20. 開発 -テスト require_relative '../fizz_buzz.rb' describe :FizzBuzz do before :all do

    dir = File.expand_path(File.dirname(__FILE__)) @_read = ->(fn){ File.open(fn).map{ |r| r.chomp }} @answer = @_read[File.join(dir, 'fizz_buzz.answer')] end it 'should be eauql to anser' do fn = 'fizz_buzz.result' fizzbuzz(100, fn) expect(@_read[fn]).to match_array @answer end end 20 / 28
  21. 開発 -実装 1.テストが通るように開発 2.テストが通るのを維持してリファクタリング 21 / 28

  22. 開発 -実装(初回: 文字列結合) def fizzbuzz(n, fn) File.open(fn,'w') do |f| 1.upto(n)

    do |i| out = '' i % 3 == 0 and out << 'Fizz' i % 5 == 0 and out << 'Buzz' f.puts out.empty?? i : out end end end 文字列を結合 22 / 28
  23. 開発 -実装(場合分け) def fizzbuzz(n, fn) File.open(fn,'w') do |f| 1.upto(n) do

    |i| f.puts case when i % 15 == 0 then 'FizzBuzz' when i % 3 == 0 then 'Fizz' when i % 5 == 0 then 'Buzz' else i end end end end 文字列演算が重いので、 場合分けに変更 23 / 28
  24. 開発 -実装(ハッシュを使う) class FizzBuzz CONDITION = { 0 => 'FizzBuzz'

    } { 3 => 'Fizz', 5 => 'Buzz', }.each do |no, key| no.step(14,no){ |i| CONDITION[i] = key } end def fizzbuzz(n, fn) FizzBuzz.fizzbuzz(n, fn) end class << self public def fizzbuzz(n, fn) File.open(fn,'w') do |f| 1.upto(n) do |i| f.puts CONDITION[i % 15] || i end end end end end 24 / 28
  25. 開発 -評価(実行速度の計測) require 'benchmark' n = 10000000 fn = 'fizzbuzz.out'

    Benchmark.bm do |r| r.report('no 1'){ fizzbuzz1(n, fn) }; File.delete(fn) r.report('no 2'){ fizzbuzz2(n, fn) }; File.delete(fn) r.report('no 3'){ FizzBuzz.fizzbuzz(n, fn) }; File.delete(fn) end 25 / 28
  26. 開発 -評価(実行速度の計測: 結果) user system total real no 1 5.810000

    0.160000 5.970000 ( 6.045857) no 2 5.120000 0.150000 5.270000 ( 5.311798) no 3 4.850000 0.130000 4.980000 ( 4.990330) ハッシュ版が一番速かった!! 26 / 28
  27. まとめ • 動く仕様書/テストで合意形成 • 小さくスタート • リファクタリングでコードを育成 • 作りすぎない 27

    / 28
  28. テストは大切 28 / 28