Techbay / study

1 stars 0 forks source link

NO.2 #2

Open iannono opened 8 years ago

iannono commented 8 years ago

@hlee @caok

iannono commented 8 years ago

394-396

394 Consistency

STOP_WORDS = %w[in the of]

# Block #1
input = %w"When in the course of human events"
output = []
while word = input.shift
  unless STOP_WORDS.include?(word.downcase)
    output << word
  end
end
output
# => ["When", "course", "human", "events"]

# Block #2
input = %w"When in the course of human events"
output = input.map(&:downcase) - STOP_WORDS
output
# => ["when", "course", "human", "events"]

保持编码风格的一致性, 能够使问题暴露的更明显 但是我并没有觉得下面的代码更容易暴露问题, 只是编码上风格更一致了

# Block #2
input = %w"When in the course of human events"
output = input.map(&:downcase) - STOP_WORDS
input
# => ["When", "in", "the", "course", "of", "human", "events"]
output
# => ["when", "course", "human", "events"]

# Block #3
input = %w"When in the course of human events"
output = input.shift(input.size).reject{|w| STOP_WORDS.include?(w.downcase)}
input
# => []
output
# => ["When", "course", "human", "events"]

395 Microconcerns

To ensure the max of age is 50

class Cheese
  attr_reader :value

  def initialize(value)
    @value = value
  end

  def age
    @value += increment if value < 50
  end

  private

  def increment
    1
  end
end

class GreenCheese < Cheese
  private
  def increment
    2
  end
end

The problem is:

gc = GreenCheese.new(49)
gc.age
gc.value                        # => 51

Solve the problem:

def age
  adjusted_increment = [increment, 50-value].min
  @value += adjusted_increment if value < 50
end

Separate concern:

def age
  @value += increment
  @value = [@value, 50].min
end

further:

def age
  increment_value
  constrain_value
end

def increment_value
  @value += increment
end

def constrain_value
  @value = [@value, 50].min
end

396 Invariant

class Cheese
  attr_reader :value

  def initialize(value)
    @value = value
  end

  def age
    increment_value
    @value                      # => 51
    constrain_value
  end

  private

  def increment_value
    @value += increment
  end

  def constrain_value
    @value = [@value, 50].min
  end

  def increment
    1
  end
end

This means that between when a public method is called, and when it returns, the object can spend some time in an inconsistent state, and no invariants will be violated.
class Cheese
  attr_reader :value

  def initialize(value)
    @value = value
  end

  def age
    new_value = increment_value(value)
    new_value = constrain_value(new_value)
    @value = new_value
  end

  private

  def increment_value(value)
    value + increment
  end

  def constrain_value(value)
    [value, 50].min
  end

  def increment
    1
  end
end

I especially like code where I can remove a concern or move a concern just by removing or moving a line, without any other touch-up needed