- PR -

ソフト開発を成功させる1つの方法の感想

投稿者投稿内容
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2001-10-24 14:38
引用:

しょむさんの書き込み (2001-10-24 03:33) より:
「行数がすくない」は単なる量的なお話ですが、「クラス数・メソッド数がすくない」は単にコード量がすくないというのではなく、機能と API の重複を減らせ(or なくせ)という質的なものも含む感じがします。


 ここでは、行数がすくない、ではなく、「要素」が少ないとさせて下さい。
 ソースを見やすくするためにコメントを入れたり、改行を入れたりして、行数が増えるのは、短いプログラムとは必ずしも矛盾しないと思うのですよ。実行ファイルのサイズが変わるわけではないので。
 それで本題ですが、単なる行数を減らすことは機械的な作業として行うこともできますが、「要素」を減らすためには、問題の本質を分析し、整理し、把握し、具体的なソースコードに展開する必要があります。問題を分析しないで適当に行き当たりばったりで書いても、(よほど幸運の女神に気に入られない限り)最小になりません。ですから、「短いプログラムであれ」というメッセージの裏側には、「問題の本質を把握して、それを無駄なく表現せよ」というメッセージが隠れていると思うわけです。つまり、「質の改善無くしてプログラムは短くならない」と私は思うわけです。

引用:

# あー、極論思いついた… クラスひとつ、main() ひとつのアプリ、とか(笑)
# そんなこたー XP が言ってることではない:)


 きっと言う奴が出てきますね。でも、そういう奴の相手を真面目にやってもしょうがないでしょう。そんな奴でも、現場で揉まれていれば、そのうちに分かるようになると思います。経験則っていうのは、そういうものだと思いますので。

引用:

もあれ、実は「ふつうのプログラマは冗長な(重複のある)プログラムを書きやすい」とか「アプリケーションが大規模になってくると冗長性が高くなる」とかいう前提のもとに、「いまふつうに書いているものをベースとして、短くしましょう/クラス数やメソッド数が減らせないか考えましょう」あたりが落としどころかなぁと思ったり。


 他人を説得しやすいだけでなく、すぐ実践できて有意義ですね。
_________________
川俣晶

[ メッセージ編集済み 編集者: autumn 編集日時 2001-10-24 14:40 ]
ひで
会議室デビュー日: 2001/10/02
投稿数: 15
お住まい・勤務地: 三重県
投稿日時: 2001-10-24 20:19
引用:

 これは容易に防止できるバグです。
 ループの終了値が1個ずれるのは、定番のバグです。これは終了値とループする回数の関係を正確に把握していない、あるいは、正確にソースコード上に表現されていないことから入り込むバグだと思います。


そういった、勘違い・思い違いが引き起こす場合もあるのですが、ミスタイプによる場合もありますよね。
記述した本人は仕様を間違って把握しているわけではありませんから、その分誤りの発見が遅れます。

もちろん短いプログラムの方が、短い分だけそういった間違いが入る確率が減りまし、発見しやすいので、そういった意味では「短いプログラムを作るのは正しい」と言えると思います。
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2001-10-25 12:57
引用:

そういった、勘違い・思い違いが引き起こす場合もあるのですが、ミスタイプによる場合もありますよね。
記述した本人は仕様を間違って把握しているわけではありませんから、その分誤りの発見が遅れます。


 確かに、紛らわしいミスタイプを見落とすということはありますね。
 バグが出にくい手法はあっても、バグを完全に無くする手法は無いと思います。
 銀の弾丸は無いと言うことですね。

引用:

もちろん短いプログラムの方が、短い分だけそういった間違いが入る確率が減りまし、発見しやすいので、そういった意味では「短いプログラムを作るのは正しい」と言えると思います。


 その通り。同じ機能を持ったプログラムなら、いろいろな意味で短い方が扱いが楽です。

_________________
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2001-10-26 16:42
 実は私の議論の展開には致命的な突っ込み所があるのですが、誰も突っ込まないんですね。
 しょうがないので、自分で突っ込みます。(マゾ? )

 まず、元記事から参照した記事に以下の記述があります。 
引用:

 理論的には、プロパティとインデクサは、存在しなかったとしてもプログラムを記述できる機能である。実際、Javaにはプロパティもインデクサも存在しないが、実用ソフトがいくつも記述されている。しかし、すべてメソッドに頼ったコーディングは、ソースコードが長くなる傾向にある。

system.get_somethig().get_hoge(index)

 のような長い式は、直感的に把握しがたい。これを、

system.somethig[index]

 と書けるようになるだけで、把握しやすさが向上するとはいえないだろうか?


 それに対して、私が掲示板に書いた短さの定義は以下の通りです。
引用:

・ プログラムに持たせたい能力を「機能」と呼ぶ
・ 宣言、ステートメント、演算子などを「要素」と呼ぶ
・ 各種テストをパスし、実用上問題ない状態を「バグがない」と呼ぶ
・ 上記条件をクリアしない状態を「バグがある」と呼ぶ
・ 「機能」を実現し、「バグがなく」、「要素」の個数ができるだけ少ないプログラムを「期待されるプログラム」と呼ぶ


 すると、プログラムの短さとは、「要素」の個数が少ないことを意味しますが、以下の2つの記述は、記述された「要素」の個数としては同じになります。
コード:
system.get_somethig().get_hoge(index)


コード:
system.somethig[index]


 つまり、元記事で短いプログラムの方が読みやすいとして参照した記述そのものが、掲示板に書いた短さの定義を適用すると、短いとは言えなくなってしまうのですよ。
 ね? 矛盾してるでしょ?
 さて、これはどう考えたものでしょうね?

_________________
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2001-10-29 16:50
引用:

 つまり、元記事で短いプログラムの方が読みやすいとして参照した記述そのものが、掲示板に書いた短さの定義を適用すると、短いとは言えなくなってしまうのですよ。
 ね? 矛盾してるでしょ?
 さて、これはどう考えたものでしょうね?


 と書いたんですが、誰も自分の意見を書いてくれませんね。ちょっとカナシイ。
 基本的には……
引用:

H2さんの書き込み (2001-10-23 08:06) より:
読みやすいというのは、コメントが多すぎずそれでいて説明が十分なことです。
コード:
i++  //iに1を足す

なんて書かれてもしょうがないわけです。(へ〜、i++ってそういう意味だったんだ・・・と一人突っ込みますが)


 ということだと思います。ソースを分かりやすくするために長くなるのは良いのですが、自明のことや、重複することを書いては、かえって読みやすさを損なうわけです。上記の例だと、i++と書いたことで、iに1を足すという機能は十分に曖昧さ無く表現されており、それと同じことを書く意味はまったくありません。
 で、以下の場合に即して言うと。
コード:
system.get_somethig().get_hoge(index)


コード:
system.somethig[index]


 右辺値として出てくるなら、somethingやhogeが値の取得のために呼ばれているのは当たり前です。それに全部get_なんて付けても、当たり前のことを重複説明することにしかなりません。get_やGetが何個も並んで、横スクロールしないと読めなかったりすると、「うるせ〜〜〜」と言いたくなります。
 え? 誰が書いたソースを見てそう思ったのかって? 私に決まってるじゃありませんか
 自分で書いていても嫌になっちゃいますね

_________________
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2001-10-30 00:54
引用:
ソースを分かりやすくするために長くなるのは良いのですが、自明のことや、重複することを書いては、かえって読みやすさを損なうわけです。上記の例だと、i++と書いたことで、iに1を足すという機能は十分に曖昧さ無く表現されており、それと同じことを書く意味はまったくありません。



う〜ん、「自明」「当たり前」かどうかが、人によるのでは。
function(i++); と書くのがいいか、i++; function(i); と書くのがいいのか…
演算子の優先順位を明示的に指定する()なんかも同様。
このコンテキストでは「i++」は「iに1を足す」という以上の意味はないのでしょうが、実際はもう少し暗黙の意味もあったりするでしょう。

知っている人にはやるまでもない「常識」なのでしょうが、それをあえて、というのはよくあることではないでしょうか。

右辺値に出てくる obj.getFoo() についても似たようなもんで、Foo が obj 内のメンバなのかそうじゃないのかを、obj の利用者が全く気にしなくてもよいようにしょうというカプセル化の方法のひとつ、ではないでしょうか。

もちろん、「右辺に現れる obj.foo」を「obj に foo という public readable なメンバがあればそれを返し、そうでない場合は public な getFoo() の結果を返す」と解釈するようなコンパイラ、プリコンパイラ、インタプリタ、言語仕様は書けるのでしょうが。
「読みやすさ」なんてものは、読み手の知識によるもんなので。

# ちょっと elisp 書いてて思った。
# 短くてエレガントで効率の良い elisp 式は、えてして読みにくい。
# きっと生粋の elisper にはすかすかと良みやすいに違いない…

autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2001-10-30 13:10
引用:

しょむさんの書き込み (2001-10-30 00:54) より:
う〜ん、「自明」「当たり前」かどうかが、人によるのでは。
function(i++); と書くのがいいか、i++; function(i); と書くのがいいのか…
演算子の優先順位を明示的に指定する()なんかも同様。


 まず、function(i++); と、i++; function(i);については、必ずしも同等とは言えないので、1つにまとめることは自明とは言い難いと思います。(それに、結果が違うような気がするのは私だけ? )
 ()については、順番が紛らわしいケースでは、不要でも付けるのは当然でしょう。もともと「紛らわしい」なら「自明ではない」ので。

引用:

このコンテキストでは「i++」は「iに1を足す」という以上の意味はないのでしょうが、実際はもう少し暗黙の意味もあったりするでしょう。


 うーん、初めてソースを読む人に、暗黙の意味を解れといっても無理ですって。
 暗黙の意味があるなら、コメントに「iに1を足す」と書くより、それを書くべきでは?

引用:

右辺値に出てくる obj.getFoo() についても似たようなもんで、Foo が obj 内のメンバなのかそうじゃないのかを、obj の利用者が全く気にしなくてもよいようにしょうというカプセル化の方法のひとつ、ではないでしょうか。


 その通り。機能としてはカプセル化の1方法に過ぎないと思います。
 でも、実際にC#を使い込んでみて、明らかにJavaよりソースが短くなり、コーディングやデバッグが楽になったと感じています。情報量を減らさずに文字数が減っていることの効能だと実感してます。まあ、このあたりは、個人的経験に立脚する話なので、当然異論はあるでしょうが。

引用:

# ちょっと elisp 書いてて思った。
# 短くてエレガントで効率の良い elisp 式は、えてして読みにくい。
# きっと生粋の elisper にはすかすかと良みやすいに違いない…


 XPでは、プログラマにとって重要な意図が述べられている、ということを条件に付けていますね。短くてエレガントな表現が、プログラマにとって重要な意図を表現することを省略することで実現するなら、XP的な意味での「シンプル」には外れるかもしれません。

_________________
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2001-11-18 13:13
 リファクタリングをやっと読み始めましたが、疑問がふつふつと出てきました。

1) ローカル変数の除去
 ローカル変数を除去するためにメソッドを作ることを勧めているが、本当にそれでいいのか? ローカル変数は宣言されたスコープ内だけの存在だが、メソッドはprivateでもクラス内のどこからでも呼べるので、関係する可能性のある範囲がかえって広くなったりしないか?
 そもそも、メソッド数を最小にすることを求めるXPとの関係は?

2) switch文をポリモーフィズムで置き換える
 switch文をポリモーフィズムで置き換えることを勧めているが、本当に置き換えるべきか? あるいは置き換えられるのか?
 ポリモーフィズムで置き換えるメリットは、呼び出し側が処理内容の詳細を知る必要が無く、振る舞いを追加するのが極めて容易になることだと思います。しかし、実際に処理される内容がソースのあちこちに分散するため、何が処理されるかを把握するのは困難になります。振る舞いが追加される可能性が極めて低い場合は、無理にポリモーフィズムにしない方が分かりやすいソースになるような気がしますが、どうなんでしょう?
 また、XMLのDOMなどは、ノードの種類を値で持つので、ノードの種類ごとに処理を分けたい場合にswitch文で分類するのは定番ですが、これを無理にポリモーフィズムで置き換えると、かえって回りくどく、分かりにくくなるだけのような気がします。つまり、switch文のポリモーフィズムへの置き換えは、関連する箇所が全て自分の手で変更可能の場合は実現できるものの、変更できないインターフェースが値で扱うことを要求している場合は、必ずしも良い選択にならないのではないかと思うわけです。
 それに、ポリモーフィズムを使うと場合分けのケースごとにクラスを作るので、あまり本質的でない処理で多用すると、XPの求めるクラス数を最小にするという原則に逆らってしまいそうな気もしますが、どうなんでしょうか?

 うーん、良く分からない。
 この本の内容は、大筋では理解できるのですが、一部の方法で引っかかっています。


_________________
川俣晶

[ メッセージ編集済み 編集者: autumn 編集日時 2001-11-18 13:13 ]

スキルアップ/キャリアアップ(JOB@IT)