気難しいプログラマとの人間関係に必要ないくつかのポイント

優れたプログラムとは (1)

»

 基礎工学的な立場から見たプログラム開発における方法論や技術論が目指すべき目標は、ソフトウェアの生産性や信頼性の向上にあります。優れた開発技法に則って作られたプログラムは、開発や修正が容易で理解しやすく、常に正しく動作します。

 では、優れたプログラムを作るにはどうしたらいいでしょうか。この問いへの回答としては、オブジェクト指向などすでに存在するさまざまな開発技法が詳しいかと思いますが、私なりにざっくりと言ってしまえば、

 「いかに部品化し、いかにそれらを疎に結合するか」

という課題にほぼ集約されると考えています。「疎に結合する」というのは、変数や関数、オブジェクトやコンポーネントといったプログラムを構成する要素(以下、より概念的な意味合いとしてこれらをモジュールと呼びます)の独立性を高め、モジュール間の関係性をなるべく薄くするということです。

 疎結合化設計は生産性やプログラム品質の面において非常に有効です。疎結合化されたモジュール内で発生する障害は故障箇所の特定が容易で、壊れた部品だけを見て修正することが可能です。そしてその修正が他のモジュールへ影響を及ぼすことはありません。また個々の部品の独立性を高めることで、ソフトウェアの規模に左右されない開発効率や保守性を確保でき、再利用可能に汎用化することで全体のコード量を減らせます。

 これらの内容について、wekipediaには「モジュール性」という言葉を用いていくつかの説明が書かれてあります。構造化プログラミングとは、まさにこのモジュール性実現のための方法論であり、オブジェクト指向言語はモジュール化をクラスという概念を利用して言語仕様にまで落としこめたものであるといえるでしょう。いずれもプログラムの疎結合化を促すアプローチであり、そういう意味ではプログラミング言語の進化は、プログラムの疎結合性・再利用性の追及によって成し遂げられてきたといえるのではないでしょうか。

 私はこのテキストでプログラミング言語の成り立ちや歴史を議論・検証しようとしているわけではありません。あらゆるプログラムは生産性・信頼性の観点から根源的に疎結合性・再利用性を追及すべきであり、それこそが優れたプログラムを作成する上で非常に重要な点であると言いたいのです。

 スパゲッティを書く人がいつまでたってもそのままなのは、言語仕様だけしか理解していないからです。「オブジェクト指向とは、データやその集合を現実世界のモノになぞらえうんぬんかんぬん……」というような説明よりも、構造化プログラミング以降のさまざまな言語の根底に流れる疎結合化・再利用化の設計思想こそが、現代のソフトウェア開発の教育現場には必要なのだと私は思います。

 次回に続きます。

Comment(16)

コメント

疎結合という言葉をオブジェクト指向信者から何回も聞かされました。
しかし、結合度云々は、オブジェクト指向以前の問題で、趣味の悪いプログラムはモジュール間の結合が冗長になってたりします。

オブジェクト指向の疎結合という観点では、むしろポリモーフィズムを使ったオーバーライドがメインで、コンポーネントがカスタマイズできる利点があります。
つまりコンポーネントを作る人と、オーバーライドを使ってコンポーネントをカスタマイズする人は別にすることが容易にできる。

オブジェクト指向の抽象化技術でカップリング度について論ずるのはいささか的外れな感じがしますが、いかがでしょうか?

↑抽象度を上げることで結合度を下げることができるから、あながち的外れとも言えんのじゃないすか?

みながわけんじ

↑結合度の定義ななんですか?

私の考えているクラスAとクラスBの結合度とは
①クラスAからクラスBのパブリック変数にアクセスする
②クラスAからクラスBのパブリックメンバー関数にアクセスする
ことを指しています。またはクラスBからクラスBへのアクセスの加味する場合もあるでしょう。

抽象化することは、あるメンバー関数を抽象化し、派生クラスのメンバー関数で実装することですよね。

派生クラスだけでみた場合、私の考えている結合度は、確かに減ります。
しかし、派生クラス+基底クラスで見た場合、結合度は同じです。

ポリモーフィズムなど高度なオブジェクト指向が要求するわりに、単に特定のメンバー関数を派生クラスに外出しにしただけなので、ノーベル賞クラス的な、学術的に意味があるかといえば、「ない」。単なる職人の技でしかないと思えますが、いかがでしょうか?

玄米茶

みながわさん、επιστημηさんはじめまして。
コメントありがとうございます。

みながわさんの言いたいことのすべてを把握できているわけではないのですが、私なりにコメントしてみます。
ちなみに私はみながわさんが懸念しているようなオブジェクト指向信者ではありません。

みながわさんのおっしゃる通り、プログラムの疎結合化の話はオブジェクト指向以前の問題です。
だからこそコラム本文においても「プログラミング言語の進化は、プログラムの疎結合性・再利用性の追及である(あった)」というように言っています。

オブジェクト指向言語はそれ以前の言語よりもプログラムを疎結合化できるわけではありません(作り方によります)。
オブジェクト指向言語が優秀なところは、結合度をなるべく疎に保ちながら再利用を促す仕組みです。
これはおそらく、みながわさんの言うところの「ポリモーフィズムによる抽象化技術」という部分だと推測します。

例えば継承は、非常に結合度の高い再利用の仕組みであり、継承が進むとスーパークラスへの依存度が高くなり、修正コストが恐ろしくはねあがってきます。
私としては継承への過度な依存は危険であり、多用すべきではないと思います。
おそらく近年ではinterfaceによる抽象化の方が重要視されていると思います。

みながわさんの言うところの結合度というのは、実際にアクセスする要素の数を元にしているようですが、(これは実際にこのような指標があるので正しいのですが)、私の考えでは要素のスコープが見えた時点で結合度が上がると考えています。
なぜならスコープの範囲内にあるモジュールはいつなんどきその要素にアクセスする修正が行われるかわからないからです。
障害は故障箇所を見るだけで直すことができ、拡張は拡張箇所を見るだけで作ることができるというのが真の意味での疎結合であり、優れたプログラムだと私は考えます。

オブジェクト指向言語はオブジェクトのやりとりが基礎となっているため、ポリモーフィズムがないと不要なスコープがどんどんと増えていってしまう、と考えることもできます。
乱暴な言い方ですが、オブジェクトのやりとり=簡潔な再利用の仕組みの土台、ポリモーフィズム=疎結合化(抽象化?)の仕組みの土台、と言えるかもしれません。

…というようなことも次回のコラムで書こうと思っていたのですが、もうこれで必要なくなったかもしれませんね。
長々と失礼しました。

> 結合度の定義ななんですか?

「とあるモジュール(機能単位)の変更/差し替えが他に及ぼす影響の度合い」
OOのおかげで変更/差し替えがとっても楽になったと感じています。

どっと

みながわさん>
付け焼き刃で語れるほど、オブジェクト指向は簡単なものではないですよ。
さすがにポリモーフィズムを間違えずに言えるようにはなったみたいですが。
わからないことは、素直に教えを乞いましょうよ。それは恥でも何でもないですよ。

モジュール同士が30本のケーブルで繋がってたら交換面倒だけど、
それが数個のコネクタにまとまってたら簡単ですわね。
OOでそんなコネクタを作れるよね。
# interfaceって、要はそゆことよね。

>επιστημηさん

何本のケーブルでつながっているという問題は本質的な問題でなないです。
それは非オブジェクト指向言語で何個の引数があるのか?と同じ次元の問題です。
抽象化したいというメリットがあればやったほうがよいでしょう。やらざるをえないでしょう。異論ありますでしょうか?

例えば、あなたが給与計算パッケージを作ったとします。A社の給与査定計算とB社の給与査定計算は違うとします。
その場合、給与査定計算は抽象化しパッケージコアを作り、派生クラスで実際の給与査定を実装する手法が、パッケージコアに悪影響を与えたり、会社ごとに給与査定計算のカスタマイズを行う場合、手違いでパッケージコアを破壊することがない。また、パートナー会社に安心して、派生クラスの実装を依頼することができます。

> 何本のケーブルでつながっているという問題は本質的な問題でなないです。

本質的の定義はなんですか? 本質的でなくてはならんですか?

> 抽象化したいというメリットがあればやったほうがよいでしょう。やらざるをえないでしょう。異論ありますでしょうか?

異論ありませんよ。「OOのおかげで(抽象化が)楽になり、たくさんのケーブルをまとめて差し替えられるね」いうてます。

DIコンテナなんざ「まとめて差し替え」の典型例でしょうか。
複数のケーブルをコネクタにまとめることで
「見かけの結合度が下がる(あたかも1本のケーブルであるかのように扱える)」
と考えます。

>επιστημηさん

>本質的の定義はなんですか?
疎結合にする、ビジネス的な目的、メリットです。

>本質的でなくてはならんですか?
それは、ビジネス的にメリットがあるからです。
我々エンジニアは実際に開発やメンテンンスでメリットがあれば、その技術(疎結合)を使います。


επιστημηの言っている「ケーブル」とは一体なんなのですか?
「複数のケーブルをコネクタにまとめることで」なんて非オブジェクト指向の構造体でもできることだと思います。

異論や質問ございますか?

>「複数のケーブルをコネクタにまとめることで」なんて
> 非オブジェクト指向の構造体でもできることだと思います。

できますね。
OOならもっとスマートに/ローコストに/フレキシブルにできます。
ビジネス的なメリットがすっごく大きい。

> 異論や質問ございますか?

ありません。

>> 非オブジェクト指向の構造体でもできることだと思います。
>できますね。
>OOならもっとスマートに/ローコストに/フレキシブルにできます。
>ビジネス的なメリットがすっごく大きい。

私はオブジェクト指向以前の話として構造体で、「複数のケーブルをコネクタでひとまとめ」の例を出しました。
今はVisual Studio C#でアプリケーション開発していますが、インスタンスやコンポーネントをメンバー関数の引数やリターン値に使っています。非オブジェクト指向言語って、数値や文字列しかデータとしか扱えなかったのに、オブジェクト指向は「インスタンス」というものが、数値や文字列意外にも(引数やリターン値に)使えるので、慣れてくると便利ですね。

> オブジェクト指向以前の話として構造体で、
> 「複数のケーブルをコネクタでひとまとめ」の例を出しました。

OOだとそれに加えて「(付随する)関数群もろともひとまとめ」にできますからね。
# 太束のぶっといケーブルをごっそり(能動部品まで)差し替える
# ことができるわけで♪

>OOだとそれに加えて「(付随する)関数群もろともひとまとめ」にできますからね

そうですよね。

以前、ドロップダウンリストのオブジェクトをメンバー関数の引数に入れて、ドロップダウンリストの選択候補項目をDBのテーブル入力値で初期化する、という内容のコラムを書きました。しかし、@IT編集部に炎上の可能性ありということで掲載却下されてしまいました。炎上マーケティングをしていたのは生島さんのほうで、私は炎上を目的としていないのに、ここの編集部は勘違いしているみたいですね。

↑わざわざよそ様のコラムのコメントに書くこっちゃないでしょ。

コメントを投稿する