ダックタイピングについて自然言語でイメージする

オブジェクト指向プログラミングにおいて、オブジェクト間の結合を疎にしてプログラム全体の安定性を高める手法のひとつである「ダックタイピング」。
タイピングというのはキーボードのタイピングではなく、タイプ(分類)の意味になるようです。

今回は、細かい説明は先人たちにゆずりつつ、勉強したことをもとに「ダックタイピングを自然言語でやるとこんな感じ」というたとえ話をします。


ダックタイピングとは

そもそもダックタイピングとは、
「対象が何者であるかに関わらず、同じことが出来るなら、それを指示する」みたいな考え方です。
ふわっとしているので、早速具体的なお話に入りましょう。

早速例題

上司からの指示

例えば以下のセリフをみてください。

上司「〇〇君、今度入社してくるXXさんが出社したら、この書類に記入してもらっておいてくれる?」

さて、この上司からの指示が「プログラム」だとしましょう。その指示を受けたあなたは「コンピュータ」だとします。

後日、実際にXXさんが出社してきたとき、あなたは指定の書類をXXさんに渡し、記入してもらうことができるでしょう。

思いがけない変更

しかし、実は入社してきたのがXXさんだけではなく、YYさんも一緒に入社してきたらどうでしょうか。
あなたが指示を受けたのは「XXさんに書類を書いてもらう」ことなので、YYさんは書類に記入しないことになります。

ここで、YYさんが書類に記入しなかったことを知った上司は、指示(プログラム)の修正が必要であることに気づきます。

上司はプログラムを修正し、新しい指示は以下のようになりました。

上司「〇〇君、今度入社してくる新人さんが出社したら、この書類に記入してもらっておいてくれる?」

指示から余計な指定を消す

さて、改善後の上司の指示はいい感じですね。
つまり、入社したのがXXさんひとりであっても、複数人であっても、「斉藤さん」だと思っていたら「斎藤さん」だった!みたいなことがあっても、コンピュータ(あなた)は正常に動作します。

このように、指示からいらない部分を削って、動作部分だけを残しました。

XXさんを抽象化し、新人さん とする

上記の指示をダックタイピングという意味で解釈すると、

  • 「書類に記入する」という動作を持つ「新人XXさん」を想定して指示を出したのが、最初の指示です。

  • 一方、「書類に記入する」という動作を持つ「新人さん」を想定して指示を出したのが2回目の指示です。

1回目の指示は「新人さんがXXさん一人である」状況に依存していたのに対して、2回目の指示は新人さんの名前、人数に依存しません。

このように「対象が誰であっても、その新人さんに書類を書かせる」というのが、ダックタイピングです。

ざっくりコードでも例示

新人さんが1人のとき専用のコード

class ShinjinXX
  def filling_some_paper(document)
    puts "XXさんが #{document} を記入しています"
  end
end

xx_san = ShinjinXX.new
xx_san.filling_some_paper("新人向けの書類")

上のコードは、新人XXさん(ShinjinXXクラス)が持つ"filling_some_paper"メソッドに対して「新人向けの書類」を渡すことで書いてもらうものです。
これでは新人YYさんが予期せず出社した場合、対応できません。
このままのアプローチでYYさんに対応しようとすると、以下のようになります。

増えた新人さんに無理やり対応したコード

class ShinjinXX
  def filling_some_paper(document)
    puts "XXさんが #{document} を記入しています"
  end
end

class ShinjinYY
  def filling_some_paper(document)
    puts "YYさんが #{document} を記入しています"
  end
end

def fill_out_documents_for_xx(xx_san, document)
  xx_san.filling_some_paper(document)
end

def fill_out_documents_for_yy(yy_san, document)
  yy_san.filling_some_paper(document)
end

xx_san = ShinjinXX.new
yy_san = ShinjinYY.new

fill_out_documents_for_xx(xx_san, "新人向けの書類")
fill_out_documents_for_yy(yy_san, "新人向けの書類")

この記述では、fill_out_documents_for_xxメソッドがXXさん専用に存在し、fill_out_documents_for_yyメソッドがYYさん専用に存在します。
このままでは、例えば書類を記入するときに「専用フォームに登録する」といった追加作業が発生したとき、人数分のプログラムを変更する必要が生じます。

一方、ダックタイピングを用いてfill_out_documentsメソッドを統合すると以下のようになります。

新人さんが今後増えても対応できるコード

class ShinjinXX
  def filling_some_paper(document)
    puts "XXさんが #{document} を記入しています"
  end
end

class ShinjinYY
  def filling_some_paper(document)
    puts "YYさんが #{document} を記入しています"
  end
end

def fill_out_documents(person, document)
  person.filling_some_paper(document)
end

xx_san = ShinjinXX.new
yy_san = ShinjinYY.new

fill_out_documents(xx_san, "新人向けの書類")
fill_out_documents(yy_san, "新人向けの書類")

新人さんがどんな名前であっても、「書類を書く能力はあるだろう」ということを期待して、新人さんが誰であっても対応できるようなコードはこんな感じになります。
(class ShinjinXXとclass ShinjinYYの両方に同じ名前のメソッドがあるから実現できています)

ということで、ダックタイピングとは……から始まる説明は難解(に見える)ものが多い気がしたので、ダックタイピングを自然言語にしてみた話を書いてみました。
「複数人が同じことをできる」ならば、「誰かを指定せず」指示を書くことで、指示そのものが再利用可能になる。という話でした。

短いですが以上です。
最後までお読みいただきありがとうございました。

この記事が気に入ったらサポートをしてみませんか?