概要
抽象、具体、概念etc、物事や考え方を指し示す言葉はたくさんありますが、それぞれが何を指すのかどのように関連付いているのかを整理してみようと思います。違いを知ることで色々と適用できるのかもしれませんね。
PHPerKaigi2019のセッション「抽象化って何?」 に触発されてます、はい。
書いている人はこういう分野に明るいわけでは無いので「それ違うだろ」ってツッコミはあると思います。信用し切らずに自分で考えてみることが大事だと思います。
PHPerKaigi2019のセッション「抽象化って何?」
こちらのスライドを合わせて見て頂くのが良いかと思います。
ゴール
- 抽象、具体、概念の定義を理解する
- 普段意識せずに行っている抽象化を理解する
- プログラミングにおける抽象化を理解する
言葉の定義
まず、言葉の定義を確認し、自分なりの解釈を付け加えていきます。
抽象
事物または表象からある要素・側面・性質をぬきだして把握すること。 類義語として捨象という言葉がありますが、こちらは「事物または表象からある要素・側面・性質を抽象するとき、他の要素・側面・性質を度外視すること」、抽象化の方法(手法)になります。抽象という単語それ自体を単独で使うことはなく「抽象化」という単語で使われることが多いです。
例えば「白くてもこもこした生き物」から何を思い浮かぶかは人によって異なります。更に「白い生物」と言えば更に選択肢が増えます。この選択肢が増える・増えている状態が抽象化されている状態になります。逆に選択肢が少なくより物事や表象が限定されてる状態を次に説明する「具体」と称します。
具体
人間の感覚でとらえられるものであること。形や内容を備えていること。 類義語として具象がありますが、具体が形や内容を備えていることに対して、具象は形を備えていることが必要になります。
例えば「首と頭が長く、長い四肢をもつ。角はない。各脚とも第3指を残し他の指は退化している。よく発達した蹄(ひづめ)をもち...(中略)... 一般に、立ったまま寝ることでも知られるが、本当に安全な場所であれば、横になって休むこともあるという生物学的特徴を持ち(以下略」と長々書きましたが、抽象化されておらず、事物または表象の特徴を表しそのものの形や内容を特定できる状態にあるのが具体となります。「具体的」な説明とか良く言いますね。
概念
辞書で調べると「物事の概括的な意味内容」や「ある事物の概括的で大まかな意味内容」と出てきますが、自分の解釈で抽象と非常に近しいのですが、抽象化した結果の集合体を概念 と呼ぶと考えています。ただし、抽象化の程度(抽象化レベル)によって概念ではなく「抽象化された何か」にしかならないので注意が必要かと思います。犬の概念と犬種を限定した概念は異なる、と言うのと近いでしょうか。
抽象化について
PHPerKaigi2019のセッションであった「抽象化って何?」をベースに理解を深めていきます。プログラミングにおける抽象化は後ろの方で整理していきます。
抽象のハシゴ
※詳しくは思考と行動における言語を参照下さい。
具体を抽象化する変化として、
具体:特徴は多く、対象数は少ない
抽象:特徴は少なく、対象数は多い
となります。
また、抽象化にはレベルが存在しており抽象化のレベルを上げる(より抽象化する)には固有の特徴を切り捨てて行く必要があります。
「山田太郎」を抽象化をしてみる
山田太郎という日本人を抽象化するには山田太郎さんという特徴を持った人から特徴を切り捨てて行く必要があります(この時点で山田太郎を具体化していますが)。「山田太郎」という言葉から見える特徴は...
- 日本人
- 男性
- 山田さん
- 太郎さん
これらが思い浮かびます。これは山田太郎という単語に内包されている情報ではなく、山田太郎という単語を抽象化する時に捉えているひとつの側面(経験則)から得られる情報になります。日本およびアジア圏の人名に詳しくない人が「山田太郎」という何かを抽象化する時にそもそもこれが人名なのか、どこの言葉かわからなければ抽象化を行うことはできません。これは先に言葉の定義で整理した具体の「人間の感覚でとらえられるものであること。形や内容を備えていること。」に該当しておらず、山田太郎を具体的に捉えられていないことが起因すると考えられます。実際に山田太郎を抽象化すると以下のようになります(or なることがあります)。抽象化は段階的に行われます。この抽象化の段階は事柄により多い少ないはありますが、抽象化をしていくことを「抽象レベルを上げる」、逆により具体化していくことを「抽象レベルを下げる」と称します。
(具体)山田太郎 -> 日本人 -> 人間 -> 生物 -> 生命(抽象)
抽象化は1つではなく、様々な側面から事柄を抽象化しそれを集めて概念とします。勘の良い方はお気付きかと思いますが、抽象化の方向性は様々です。人によって物事または表象の捉え方(側面の見方)は異なり、抽象化の方向も異なります。抽象化の方向性が異なれば辿り着く結果も異なります。異なるだけでその抽象化が間違っているかどうかは別問題のベクトルになります。
抽象レベル
抽象レベルは先に少し出てきましたが、抽象化レベルが合っていない状態で会話をしてみましょう。
A「昨日のサッカー見た?」
B「競技場で人が物理的意思疎通による云々...(以下略」
この後めちゃくちゃ抽象レベル下げたってなりそうですね。抽象レベルが合っていないと会話が噛み合わないだけではなく、会話の中で抽象レベルを下げる必要が出てくるのですが、抽象化された事象はそれそのものだけで具体化することが非常に難しいです(先の山田太郎の例を考えるとわかりやすいかと思います)。話の論点や認識のズレが起きる原因にもなり得るので、コミュニケーションを行う時に抽象レベルは意識していきたいところですね。
プログラミングにおける抽象化
InterfaceやAbstractやな!わかるで!って思った方は自分と一緒です。手段が目的になっちゃったやつかもしれません。プログラミングにおける抽象化の本質は「扱っている問題や概念の抽象化」になります(個人的に概念の抽象化というのがよくわかっていません)。これらを解決するために「InterfaceやAbstractやな!わかるで!」となるわけですね。
プログラミングにおける問題の抽象化の指針(Speakerさん観点)
【注意】スライドと順番を前後させています。
狭い範囲
考慮する特徴の数が小さくなっていること
比較的良く言われる内容ですが、そのオブジェクトやメソッドが本来行うべき処理の本質は何かを考える。考えると言うより何をする必要があるのか、から何を行うべきなのかまで削り落としていくイメージに近いのかなと感じました。
スライドの例で言えば「マトリックスのチェック」という大きい役割から役割を遂行するのに不要なものを削り落として「順不同の9つの数字のチェック」という必要最低限の責務に落とし込んでいました。
適切な名前
名前と内容が一致していること。
順番としてはこちらが先に紹介されていましたが、順番的には 狭い範囲 を進めて行った結果として、不要なものが削ぎ落とされて本質が見える、本質は非常にシンプルであり、シンプル故に内容と名前が一致する。という印象を受けました。
抽象度の統一
ある側面が取り出されたものだけで辻褄が合うこと
セッションの中でおそらく最も大事な内容の1つだと感じました。先に記載した抽象レベルがここに繋がります。OOで言えばプログラミングはオブジェクトの会話と表現することができるかと思います。この会話レベルを揃えることで狭い範囲での会話が成り立ち、お互いに本質的な関係・役割を果たせるというところに繋がるのかなと思います。
ある側面と言っているのはあらゆる側面から見た場合の本質を詰め込むと抽象化されたものではなく概念となってしまい、抽象レベルが下がってしまうからではないかと考えています(合っているかhわかりませんが、そう理解しています)。
抽象化トレーニング
本質を発見するスキルを磨くには以下の内容が効果的らしいです。
- 数学
- 論理学
- アルゴリズム
個人的に普段当たり前にやっている抽象化や概念を改めて書き出して他の観点や側面は無いか、前提を少し変えて見る等でトレーニングするのも面白いのかなと思っています。
個人的要約
抽象化を行うことで本質的な役割や関係性が見える。本来の役割や関係性を洗い出し見える形に落とし込むのが抽象化。
抽象化することで明確になるというのが何とも不思議な感覚でした(今まで抽象化と言えばボカしたり曖昧にするってぐらいの考えだったので...)。
余談
PHPerKaigi2019っていうぐらいだからPHPわからないとダメでしょ?って思いますが、PHPだけでは無く多言語や他でも使える考え方や概念のセッションもあったのでセッションを見て興味がある内容があったら行ってみると良いと思います。
1つのセッションに対しての整理で結構な時間がかかったので、聞いたセッション全て整理するにはどれだけの時間が必要なのか...(´・ω・`)