RE:プログラミングの「抽象化」ってどういう意味で、なぜ必要なのか

さて、nobkzです。UX Fukuokaの活動ばかり書いてましたが。 久し振りにポエム書きます。

今回は、

nekogata.hatenablog.combugrammer.hateblo.jp

に関してのアンサーブログです。

nopが「世界一の抽象化だ」の納得と違和感

さて、「何も書かないことが世界一の抽象化だ」という論理について納得する一方違和感を感じ、考えてみたことを述べていきたいと思います。

まずは納得する面から。

抽象と捨象

個人的には、「抽象」という言葉は、ソフトウェアの世界に限らず、一般的用語だと思います。ここで、適当に辞書を取ってきて意味を見てみると

《名・ス他》多くの物や事柄や具体的な概念から、それらの範囲の全部に共通な属性を抜き出し、これを一般的な概念としてとらえること。 

とあります。抽象というのは、「全部に共通は属性を抜き出す」ということが含まれています。その、「抜き出す」という行為の裏には、「共通してないものを捨て去る」ということがあり、それで「捨象」という言葉が、「抽象」と同義語としてあります。

《名・ス他》(概念を抽象する作用の反面として)現象の特性・共通性以外を問題とせず、考えのうちから捨て去ること。

捨て去ると何もなくなる。

さて、一理あるなと思う点は、この抽象という行為の中に「捨て去る」というこういがあるからです。なるほど、そりゃあ、全部捨ててしまえば、何もなくなるのはその通りだなと、いうことです。

また、集合論的に言えば、「空集合はすべての部分集合である」ということを言っていると、似ている感じにもなり、その点で、通じるものがあるということです。他にも、ゼロの概念とか、「空」の概念とか、東洋思想的な感覚になります(笑)。

違和感

上記の点で、一理あるなと思う反面、おかしいなと思うことがあります。その点を書いていきます。

抽象したものがない

まず、抽象した結果が、「なにもない」ということです。これは、果たして「抽象した」と言えるでしょうか? ある意味、「抜き出すものが無い」=「抜き出してない」とも考えられ、それは「抽象したものではない」とも言えそうです。

ここらへん、Russell's paradoxを思い出します。ただ、 ここらへん深く書いていくと、型理論まで発展して泥沼になりそうなので、これ以上書きません。

抽象と構造

抽象としている場合基本的には、構造があります。 上記のnopの話は、「構造化されてない」という点で、抽象とは異なる言えそうです。

ここまでずっと、ソフトウェアに限定しない、話をしてきましたが、「抽象」と「構造」もソフトウェアだけのものではありません。

エスノグラフィーや心理学などの、質的、定性的データを使う分野では、「ラダーアップ、ラダーダウン」という質的データの構造化分析手法がありまして、ラダーアップは、「事象」から「抽象概念」までの構造化、ラダーダウンは「抽象概念」から「事象」までの構造化であります。また、KJ法(こっちの方が良く聞かれるかもしれないですね)なども構造化手法の一つでしょう。

なにが言いたいかというと、そうした、「構造」なくして、「抽象」はありえないのではないか?ということで、そこが違和感の一端になっているということです。

ソフトウェアの「抽象」

さて、全般的な文脈から語ってましたが、ソフトウェアのコンテキストを考えて、抽象を考えてみましょう。

「良い」と「正しい」

まず、一点あるとすれば、「抽象」としては「正しい」けれども、「良い」ものでは無いという場合があるということです。 ソフトウェアで、抽象するときは、システムを作る上での、「抽象」する上での意義があるということです。

新しい意味付け、メタファー

個人的な意見としては、抽象化の先に、「良い意味付け」が基本的には、ソフトウェア的に「良い抽象化」では無いか?と思うことです。

システムを構築する上での、抽象化のした最後に待ってるのは、「名前付け」であり「意味付け」です。どう意味付けするかによって、ソフトウェアの「抽象化」の「良い、悪い」が出てきそうです。そして、「名前付け」というのは、つまり「良いメタファー」を作ることであり、その点に関して、みなさん苦心されているのかなと。

良いメタファーを作ることは、「使う側」にとって、「どのように使うのか?」というのかが、明確になり、その結果、適切な組織化が可能ということだと個人的には考えてます。

ある意味、これは表示的なもであり、良いインターフェースを設計することが「良い抽象」としての活動に含まれていそうです。そこに、「操作的」なものを入れてしまうと、無意味な抽象となってしまいそうです。

具体と新しい意味

さて、上記2つの記事において、いくつか、コードが出てきました。

def transfer_gold
  # user_1 から50G引いて
  user_1 = User.find(1)
  user_1.gold -= 50
  user_1.save!

  # user_2に50G足す
  user_2 = User.find(2)
  user_2.gold += 50
  user_2.save!
end

さて、これが、元となるコードで、いくつか変更を加え、

def transfer_gold(amount, from_user_id, to_user_id)
  user_a = User.find(from_user_id)
  user_a.gold -= amount
  user_a.save!
  
  user_b = User.find(to_user_id)
  user_b.gold += amount
  user_b.save!
end

def pay_service_fee(customer_id, store_id)
  transfer_gold(50, customer_id, store_id)
end

こうなってました。

さて、これを、僕の観点から、言えば、「抽象化」の他に「意味付け」を行なっているということであります。 1や2という数字の意味、、50という数字の意味は何か?そういうことを考えていたと思っています。

「悪い」抽象化というのは、その意味付けが良くないということです。もし変数名が、amountじゃなくて、単なるxだとしたら、それは良くない抽象でしょう。

nopのコードに関していえば、構造化、意味付けを行っていない点で、抽象というと「違和感」や飛躍した原因だと考えています。

まとめ

まとめますと、nopという抽象に関しては「捨てていく」と考えると、一理ありますが、しかし、構造になっていない点、意味が無い点で、抽象とは言えない要素があるということです。

まだ、言いたりないような気がしますが、ここまでにしておきます。