オブジェクト指向再考(メッセージ1)

先週に続きましてオブジェクト指向再考ということで特にオブジェクト指向に毒された方を対象に現実的な観点でプログラムできるように、プログラマとして社会復帰できるように、ヒントを出したいと思います(もちろん回復するかどうかは本人次第です)。
今週からはメッセージについて話たいと思います。世の中には、

メソッド(メッセージ)>>どうしようもない壁>>関数

と思っている方がいらっしゃるようですが、今後数回に分けて、この『どうしようもない壁』というのはオブジェクト指向病特有の幻覚であるということを示したいと思います。まぁ、厄介なことに患者さんには明確に壁が見えているのでなんとも言えないのですが、もし少しでも『これは幻覚かも?』と思った方はこの連載が助けになるかもしれません。ちなみに『この壁を感じれないやつはプログラマとして終わっている』とお思いの方はお帰り頂いて構いませんし、反論のコメントを書き込んで頂いても構いません。

前回の最後に示しましたが、オブジェクト指向のキーファクターとしてメッセージがあります。この考え方(パラダイム)はそれはそれで素晴らしいものです。分かり切った例をあげますと、マウスの入力(クリック)がメッセージとしてOSに伝わり、イベントハンドラ(コールバック関数)に制御が引き渡されます。当たり前のようですがこの仕組みはメッセージパラダイムを具現化したものになります。もしメッセージを使わなかったら、例えば定期的にマウスの位置を読み込み、クリックされたどうかを確認することになります。考えただけでも厄介ですよね。GUIプログラムがイベント駆動型と言われる所以ですね。

さて、ここでのキーポイントは、『世の中の事象は全てイベント駆動(メッセージ)で記述するのが良いことか?』ということになります。例えば、以下のプログラムを考えましょう。

ユーザがスタートボタンをクリックしたら画面に"Hello"と表示する。

間違いなく、『ユーザがスタートボタンをクリックしたら』、というところはイベント駆動と相性がいいですね。では次の

『画面に"Hello"と表示する。』・・・・・(A)

というのはどうでしょうか?この部分はイベント駆動またはメッセージで記述できるでしょうか?

よくオブジェクト指向の教科書に出てくるのですが、

『画面オブジェクトに、引数に"Hello"を指定して表示依頼のメッセージを送る。』・・・・・(B)

というのを見受けます。最初に指摘しますと(B)は(A)を劣化させたものだと言えます。
ポイントは(A)は手続き指向で書かれて、(B)はオブジェクト指向(メッセージ指向)で書かれています。そして重要な点ですが、この場合、(A)はプログラムの仕様(本当にやりたいこと)を表していて(B)はプログラムそのそのものの説明を行っている点ということになります。つまり、(B)は以下のようなコードの説明を行っているということになります。

label.setText("Hello");

ここで画面オブジェクトというのがlabelになり、setTextが表示依頼メッセージで"Hello"が表示対象の引数ということになります。
つまり(B)は上記のコードの説明を行っていることになり、(A)は上記のコードの意図を表しています。
もし上記のコードにコメントを付与する場合、(A)、(B)どちらが良いでしょうか?

label.setText("Hello"); // 画面に"Hello"と表示する。・・・・・(A)

label.setText("Hello"); // 画面オブジェクトに、引数に"Hello"を指定して表示依頼のメッセージを送る。・・・・・(B)

(B)の方がよいという考え方の人に質問したいのですが、ラベルオブジェクトに値をセットする方法にはプロパティを使うというものもあります。つまり以下のコードもありえます。

label.Text = "Hello";

この場合、(A)、(B)どちらのコメントの方が適切でしょうか?

label.Text = "Hello"; // 画面に"Hello"と表示する。・・・・・(A)

label.Text = "Hello"; // 画面オブジェクトに、引数に"Hello"を指定して表示依頼のメッセージを送る。・・・・・(B)

それとも以下のようにコメントするのでしょうか?

label.Text = "Hello"; // ラベルプロパティに"Hello"をセットする。・・・・・(C)

もっとも、(C)のような発想もオブジェクト指向から離れたと言えるでしょう。
さて、ある程度経験のあるエンジニアなら大なり小なりこのようなジレンマを抱えたことがあるかと思います。つまりメソッドの中身を書こうとしたときに『どうもオブジェクト指向していないな・・・』と感じることがあったかもしれません。しかしよく考えてみれば分かりますが、メッセージ指向というのはある種の手続きの上っ面(呼び出し方法)についてパラダイムであり中身をどうするかは別問題ということに気付くかと思います。
ここで重要なことは、

メッセージというのはプログラミングパラダイムの一つであり、メッセージで表現した方がよいもの(例えばイベント)もあれば、そうでないもの(手続き指向のもの)があるということで、プログラマは適宜適切なパラダイムを選択してプログラムを行えばよいです。多くのプログラマは、プログラミングパラダイムについて

オブジェクト指向(メッセージ指向)> 手続き指向

と考えているかもしれませんが、実はそれぞれ適材適所があり適宜使用すればよいということになります。つまりマルチパラダイムですね。さてオブジェクト指向言語しか知らない方は実は手続き指向という発想がないかもしれません。何かをステップバイステップで処理をするという発想が手続き指向になります。特段難しいとは思えないですが、もしピンとこない方がいらっしゃいましたらコメントを下さい。
イベント処理を手続き指向で考えるのは不適切ですし、能動的に画面に何か表示したいと思った時にいちいちメッセージ云々を考えるのも不適切ということになります。そう考えると以下の2つの記述方法のどちらかが適切か理解できるかと思います。

z = 3 * x * y + 4 * x + 6 * y + 2;

z = 3.multiply(x).multiply(y).add(4.multiply(x)).add(6.multiply(x)).add(2);

もう迷う必要はなく上の方が適切だと理解できるかと思います。数式も一つのパラダイム(というか表現方法の一種)だと理解すれば無用なパラドックスに悩まされる必要もなくなります。

次回は、メソッドと関数についてもう少し突っ込んで話したいと思います。
2016-03-20 | コメント:6件
あいだより
2016-03-23 15:04:28
素晴らしい内容だと思います。
わかってる人(オブジェクト指向に疑問をもちつつある人)には、
 ・上手い例
 ・上手な説明
だと思います。
しかし、洗脳を解くにはには弱いし、難しいかも?

よろしかったら一つ質問させて欲しいのですが。

文字数で処理する関数、length関数、substring関数が存在する世界で、
byte数で処理する同様の関数を作成することになるとしたら、
どのような名前を付けますか?

私ならlengthB関数、substringB関数。
しかし洗脳されている人たちはほぼ例外なく、
byteLength関数、byteSubstring関数
ときます。
(byteを略すor略さないは些末な話で趣旨じゃないです。
 修飾を前にするor後にするが趣旨です。)

私の解釈では、
 ・現実的な使い勝手を優先した命名
 ・オブジェクト指向的な(メッセージライクな、かっこいい)命名
の違いだと思うのですが。

ohfuji様はいかがでしょうか?
(もちろん「lengthBこんなダサい命名しない」が回答でも悪く思いませんのできたんないご意見を!)
ohfujiより
2016-03-24 14:27:54
ご感想ありがとうございます。
少し様子を見てみたいところではありますが、確かに洗脳を解くには弱いかもですね。

名前ですね、私の場合間違いなく
LenB,MidB
ですかね。もちろん元はVBです。
一瞬ですが、byteLengthは英語の文法に忠実かな?と思ったのですが、よくよく考えたら、必ずしもそうとは限らないかもしれません。マルチバイトに慣れている民族はbyteLenghtの意味が正しく理解できるかもしれませんが、そうでない民族はbyteLengthと聞いたら、1と返信しそうですね。つまりbyteのLengthと受け取る場合もあるかと。
そういう意味でも、LengthBの方が『Bってなんやねん』と思わせるものがあって好きですね。あと、修飾をするのならポストフィックスが好きなので、byteというLengthの意味を補完するものにプリフィックスが付くというのも私の感覚では無しなのですが、ただ、時代の趨勢か、.NetライブラリもByteLengthという命名を使っているようです。もっともByteCount/byteCountというメソッドもあるようでこちらはなぜかしっくりきます。
byteSubStringに関しては確かにそういうメソッドもあるようで嘆かわしい限りです。
あいだより
2016-03-25 10:36:40
回答ありがとうございます。
私もvb厨だったせいか。
Len関数、Mid関数が存在する世界なら、
LenB関数,MidB関数しかないですね!
ByteLen関数,ByteMid関数にはしないですよね。

私がこの命名を実践的(現実的な使い勝手)と考える理由は圧倒的に以下ですが。
 ・関数の存在を知らない人が見つけやすい。(例えばインテリセンス(コード保管)で同種の関数が並ぶ。)

byteLength関数、byteSubstring関数を命名できる人(オブジェクト厨)は何を考えているのか気にしています。
 ①考えてない。
 ②考えた末にこれがベストと思った。
 ③考えた末にサフィックスが良いと思ったが、他の実装とそろえることを優先した。

私自身はわりと③です。
②はお目にかかったことがないし、いるなら話を聞いてみたい。
(「byte版の関数が並んでわかりやすいだろう!」って言うのかな?)
どうせみんな①なんだろう!?
ならオブジェクト指向勉強するのなんて早すぎる!
ohfujiさん文章読んでたほうが上達するよ!!
ohfujiより
2016-03-27 03:11:20
ご返信ありがとうございます。

月末になり忙しく、週末作業があり、次回の更新の時間がとれなさそうです。ので遅れそうです。
私の方でも調べてみましたが、byteLenghtという命名についてネット上には根拠はみあたらないですね。
ただ英語の文法的にはlengthByteはなく、byteLengthはありえます。正確に表現するとlengthInByteはありでこの表現が最も適切なようです。さて、手元の本を当たってみましたが、The Art of Readable Codeには、変数名の命名規則でサフィックスで単位を表す例としてmb(メガバイト)が使われていました。またメソッド名の場合、getBytesのように表現していました。またOracleではLengthBが使われている一方でSQLServerはDataLengthのようです。
ということで広く考えればどちらもあり得るようで、確かにインテリセンスを考えれば、『②考えた末にこれがベストと思った。』というのはないみたいですね。一時期、変数名で単語の省略はよくないという流行があったかと思いますが、今でもそうでしょうが、その関係でlengthBよりbyteLengthとなったのでしょう。
まぁ、byteLengthの支持派の意見が聞きたいですね。
あいだより
2016-03-28 10:04:07
私のほうこそ返信ありがとうございます。
略語の弊害は理解したつもりで、
WINDOWS APIの命名にWINDOWとWNDが混在していることに腹を立てたり、
あらゆる識別子一生懸命フルスペルで打った時期もありました。
また、あらゆる日本語(ローマ字)を止め英名を使おうとしたり。
でも今は・・・。

私のとりとめのない書き込みで
お邪魔してしまっていたらすみません。

ゆっくりでも、
ブログを更新されてくだされば嬉しいです。
さっそくブログ更新されているので、
楽しみに読ませていただきますね。!
ohfujiより
2016-03-30 11:23:37
新しい記事をアップしたところで力つきました・・・亀レスですみません。

そういえば、名前の付け方一つとっても流行り廃りや流派(大文字小文字交じりや_で区切ったり)がありますね。
また日本人は英語が弱いので英語名は特に難しいですが、かといってローマ字はそれはそれで読みづらいし。
思いっ切って漢字・ひらがなで命名してもいいかもと思ったりしますが、それはそれでプロとしてはどうかと思ったり・・・。

コメントをどうぞ


『不適切なコメントへの対応』を一読下さい。
現在コメントは承認制となっております。

Previous Page | Next Page