Hatena::Groupimplementationpatterns

sumim が Implementation Patterns と SBPP の比較を通じて Ruby と Java を学ぶ日記

 | 

2007-11-29

● Safe Copy (SBPP: Enumeration Method)

13:41 | はてなブックマーク - ● Safe Copy (SBPP: Enumeration Method) - sumim が Implementation Patterns と SBPP の比較を通じて Ruby と Java  を学ぶ日記 ● Safe Copy (SBPP: Enumeration Method) - sumim が Implementation Patterns と SBPP の比較を通じて Ruby と Java  を学ぶ日記 のブックマークコメント

・ Safe Copy [IPB97]

コレクションを代入したインスタンス変数へのアクセスにはコピーを介しましょう。

def get_books
  result = []
  result.concat(@books)
  return result   #不要ですが、なしだと result が返るというメッセージ性に乏しいように思うので…
end

def set_books(new_books)
  @books = []
  @books.concat(new_books)
end

疑問:

#get_books は、こうではダメなのか?

def get_books
  return @books.dup.to_a   #to_a は不要ですが、result = [] と同じメッセージ性をたもせるため
end

反省:

なにげに Java の例のまま使ってしまったけれど、#get_books と #set_books は、Ruby では #books= と #books のほうが(多くの場合)ふさわしいかもわからんね。(^_^;)



・ Enumeration Method [SBPP108]

あらためて読み返してみると Safe Copy とは方向性が違いますね。ま、いっか(^_^;)。

class Department
  def employees_each(&b)
    @employees.each(&b)
  end
end

def all_employees
  result = []
  departments.each do |d|
    d.employees_each{ |e| result << e }
  end
  return result
end

@employees の要素に an Employee だけでなく、a Depertment も含む可能性がある場合。

class Depertment
  def employees_each(&b)
    @employees.each{ |e| e.employees_each(&b) }
  end
end

class Employee
  def employees_each
    yield(self)
  end
end

疑問:

Ruby では、self や括弧が省略できるので、Indirect Access [IPB47][SBPP101] のメッセージ性(可読性)がある意味、阻害されてしまうかも。たとえば、上の #depertments のコールは、@depertments のアクセスと字面がほとんど変わらず紛らわしい。かといって、Java のように getHoge/setHoge なネーミングルールを用いると #attr_accessor のうま味がなくなる。self か括弧を省略しないことで回避できるように思うが、括弧を補うよりは self を補うほうがよいのか?

def all_employees
  result = []
  self.departments.each do |d|
    d.employees_each{ |e| result << e }
  end
  return result
end
def all_employees
  result = []
  departments().each do |d|
    d.employees_each{ |e| result << e }
  end
  return result
end

メモ:

Ruby では配列がサイズ可変なので、かつ、Smalltalk の WriteStream のようなしくみがないので、writer(配列をラップして伸長可能にしたもの)を介する必要がない。


疑問:

Smalltalk で、Ruby の Array のようにサイズ可変な OrderedCollection を使ってはいけないのか?

allEmployees
    | result |
    result := OrderedCollection new.
    self departments do: [:eachDepartment |
        eachDepartment employeesDo: [:eachEmployee | result add: eachEmployee]].
    ^result asArray

速度もそんなに変わらなんしなぁ…。

| oc |
oc := OrderedCollection new.
^[1e4 timesRepeat: [oc add: #something]] timeToRun   "=> 13 "
| writer |
writer := #() writeStream.
^[1e4 timesRepeat: [writer nextPut: #something]] timeToRun   "=> 10 "

参考。

| array |
array := #().
^[1e4 timesRepeat: [array := array copyWith: #something]] timeToRun   "=> 1019 "
 |