RE:プログラミングの「抽象化」ってどういう意味で、なぜ必要なのか
さて、nobkzです。UX Fukuokaの活動ばかり書いてましたが。 久し振りにポエム書きます。
今回は、
nekogata.hatenablog.com と bugrammer.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という抽象に関しては「捨てていく」と考えると、一理ありますが、しかし、構造になっていない点、意味が無い点で、抽象とは言えない要素があるということです。
まだ、言いたりないような気がしますが、ここまでにしておきます。