简单"橙色生长"编码以理解类和方法

时间:2015-05-23 18:19:14

标签: ruby

class OrangeTree
  attr_accessor :treeage, :treeheight, :orangecount

  def initialize(treeage = 0, treeheight = 0)
    @treeage = treeage
    @treeheight = treeheight
    @orangecount = []
  end

  def growing_orange
    @treeage += 1
    if @treeage > 2
      i = @treeage
      i.times do
        @orangecount << Orange.new
      end
      return true
    elsif @treeage > 8
      @orangecount = []
      return false
    end
    puts "#{@orangecount} oranges collected"
  end

  def growing_height
    if @treeheight < 4
      @treeheight = @treeage * 0.5 + @treeheight
    else
      @treeheight
    end
    puts "#{@treeheight} inches grow"
  end
end

a = OrangeTree.new
a.growing_orange
a.growing_height

我试图通过课程和方法进行ruby编码练习。我试图制作一个可以模拟逐年增长的橙树的代码。在第3年到第8年,树应该能够生产与其年数相对应的橙子(第3年= 3个橙子,8年= 8个橙子)。直到第4年,树木才会停止生长。 但我所得到的只是收集的橙子,0.5英寸的长度和#34;。我的代码中哪一部分错了?

1 个答案:

答案 0 :(得分:0)

祝贺学习Ruby。我想你会发现它非常有价值。

我想扩展@ user2864740的评论,这表明你“分离了age!使树更老的副作用,从观察结果。”您的方法应该具有副作用,例如更改变量或生成输出,或者应该返回值,但不能同时返回两者。此外,每种方法都应该只做一件事。

OrangeTree的新版本

考虑到这一点,这是OrangeTree的新版本。它可能不完全与您的OrangeTree应该做的完全相同,但这并不重要。它显示了遵循这些原则如何产生一个更容易理解的课程。

class OrangeTree

  attr_reader :age

  def initialize(age: 0)
    @age = age
  end

  def new_year
    @age += 1
  end

  def orange_count
    return 0 if @age < 3
    [@age, 8].min
  end

  def height
    [@age, 4].min
  end

  def print_height(out = $stdout)   
    out.puts "#{height} inches grow"
  end

  def print_orange_count(out = $stdout)
    out.puts "#{orange_count} oranges collected"
  end

end

这个类是可以理解的并且易于测试,因为:

  • initialize允许设置年龄。这对测试很有用。 age是一个命名参数,因为OrangeTree.new(age: 2)OrangeTree.new(2)更容易理解。当名称或用法中没有显示裸常量的含义时,命名参数有助于使代码更清晰。

  • new_year只会增加年龄。它是唯一一种改变树状态的方法。这有助于使课程更易于理解和维护。

  • orange_count只根据年龄计算橘子数量。它不存储橙子的数量,因为它可以根据年龄来计算。

  • height只计算树的高度。它不存储高度,因为它可以根据年龄计算。

  • print_height只打印高度。为了方便单元测试,它需要out作为参数。

  • print_orange_count只打印橙色数量。为了方便单元测试,它需要out作为参数。

单元测试

这是rspec单元测试,显示了OrangeTree的测试结果:

require "stringio"

describe OrangeTree do

  it "should start out with 0 age" do
    expect(OrangeTree.new.age).to eq 0
  end

  it "should age" do
    tree = OrangeTree.new
    tree.new_year
    expect(tree.age).to eq 1
  end

  it "should grow to height 4" do
    expect(OrangeTree.new(age: 0).height).to eq 0
    expect(OrangeTree.new(age: 1).height).to eq 1
    expect(OrangeTree.new(age: 2).height).to eq 2
    expect(OrangeTree.new(age: 3).height).to eq 3
    expect(OrangeTree.new(age: 4).height).to eq 4
    expect(OrangeTree.new(age: 5).height).to eq 4
  end

  it "should grow oranges between years 3 and 8" do
    expect(OrangeTree.new(age: 0).orange_count).to eq 0
    expect(OrangeTree.new(age: 1).orange_count).to eq 0
    expect(OrangeTree.new(age: 2).orange_count).to eq 0
    expect(OrangeTree.new(age: 3).orange_count).to eq 3
    expect(OrangeTree.new(age: 4).orange_count).to eq 4
    expect(OrangeTree.new(age: 5).orange_count).to eq 5
    expect(OrangeTree.new(age: 6).orange_count).to eq 6
    expect(OrangeTree.new(age: 7).orange_count).to eq 7
    expect(OrangeTree.new(age: 8).orange_count).to eq 8
    expect(OrangeTree.new(age: 9).orange_count).to eq 8
  end

  it "should print the height" do
    out = StringIO.new
    tree = OrangeTree.new(age: 2)
    tree.print_height(out)
    expect(out.string).to eq "2 inches grow\n"
  end

  it "should print the number of oranges" do
    out = StringIO.new
    tree = OrangeTree.new(age: 4)
    tree.print_orange_count(out)
    expect(out.string).to eq "4 oranges collected\n"
  end

end