[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 12355] Re: ズームイン Java(6/10) の予習について



村山です.

> > p.148で「無名クラスは全く再利用ができません」と断言していますが、
「オブジェクト指向プログラミングの確信は再利用性にあります.そのため,再
利用不可能なクラスを宣言することは,オブジェクト指向エンジニアリングの原
理に反します.」
> このあたりの本文の説明は、言い過ぎなように思えます。
同じく.

ここでいう「再利用」は,いわゆる「差分プログラミング」としての
『再利用』を指しているんじゃないでしょうか.

オブジェクト指向における継承が『再利用の道具』だと思っている場合は
 「これは正常に動作しますが全くオブジェクト指向的ではありません」
ということになるんでしょうが,
  オブジェクト指向における再利用≒差分プログラミング
だったのは昔の話ですよね.

そもそもこういう「オブジェクト指向原理主義者」ってのは,開発現場からは
ちょっと敬遠される存在だと思いますね.オブジェクト指向というのが現場の試
行錯誤の中で,同時多発的に生まれて来たプログラミングパラダイムの集大成
に過ぎず,極論すれば使い易ければ使うし,開発の邪魔になるなら使わなければ
いいという程度のものです.『原理主義』の主張には,そういう視点が欠けてい
るんですよ.


あとは思いつくままに挙げときます.

○6章 無名クラス
全般として論理の展開や使っている用語がモデル屋/原理主義者っぽい.
どうやら過度に継承階層に依存した設計を好んでいるように見える.ただし,
これは原著者のせいではなく,翻訳者の癖の可能性もある.

・P150 6.4の直前
「クラスのインスタンス変数にアクセスする積極的な必要性がないならば,
可能な限りネストクラスをstaticにすることをお奨めします.」
と断言するほどstaticなネストクラスが良いものだろうか?

プログラミング言語Java第3版5.1.1より
「staticのネストしたクラスは,トップレベルのクラスと同様に振る舞います.」
"A static nested class acts just like any top-level class."

トップレベルのクラスと同じならそれこそトップレベルクラスを使えばいいだけ
で,ネストさせる意味がないように思います.

・P152 6.5「しかし,インターフェース内でネストクラスを宣言すべきではあり
ません.インターフェースは概念の抽象化であり,概念の実装ではありません.
そのため,実装の詳細はインターフェース外に出すべきです.」

「インターフェース内でネストクラスを宣言すべきである」とする肯定的な理由
も思いつかないが,上記の理由はこれに反対する根拠として正しいものだろうか?
「インターフェースは概念の抽象化である」としても,「これからの逸脱は一切
認められない」と言い切っていいものだろうか?

・P153 上から2つ目の段落内 ネストインターフェースを使用する理由として,
「しかしその理由の一つとして,合成オブジェクトの実装を制限することなく合
成関係をモデル化することが挙げられます.」「合成関係をモデル化するイン
ターフェースが必要になり...」

ここでいう「モデル化」とは?
ひょっとして「モデルを作って,モデルをクラス設計にマッピングする」と
いう設計手法を仮定しているのか?

・P153 6.6.2の最後の段落
「結局のところ,インターフェース内でのネストクラスやインターフェースの使
用は,オブジェクト指向プログラミングではなんら意味を持たないので,おそら
くコンパイラがブロックすべきでしょう.」

ここでいう「オブジェクト指向プログラミングでは」が具体的にどういう「オブ
ジェクト指向」なのかは知らない.しかし基本的にはSyntax Sugarでしかないの
で,良くも悪くも「セマンティクス的に意味がない」のは当然のことで,批判に
は当たらない.

「コンパイラがブロックすべき」というのも表現がおかしくて,使うべきでない
なら言語仕様から削除すべきですね.そうでないなら,せいぜい警告を発する以
上のことはできません.


○7章 定数の全て

・P156 下から二つ目の段落.しかしMIN_INTERESTは〜
「最低利率は変更される可能性があり,この利率はコード内で2度使用されてい
るからです.」

これについては,一度目の時からMIN_INTEREST_RATEあたりにしておいた方が良
いのでは.二度目が使用されないことが保証されているなら良いが,さもないと
二度目に使おうと思った時に「今が二度目以降かどうか.」「もし二度目以降で
あるのなら,既に使用されている箇所を全て洗い出して入れ替える」という作業
が必要になる.

この手のシステムでは二度,三度と使うのは予想されるので,一つ目の時から定
数に切り分けた方が良いと思う.

ただし行きすぎるのは逆効果です.「定数と見なせる全ての数値はきちんと別項
目に切り分け,常に仕様書などのドキュメントを整備し,新規追加/変更の際に
は課長と部長の許可を得て押印してもらうこと」なんてことをやり始めたら,生
産性も品質もがた落ちになります.
#現場の開発者は知ってるもんだけどね.

・P157サンプルコード buildlogMessage()メソッド内.
たとえば後者のように書いた方が若干楽.
-----------
		StringBuffer buf = new StringBuffer(200);
		StackTraceElement[] elements = ex.getStackTrace();
		buf.append("The exception ");
		buf.append(ex.getClass().getName());
		buf.append(" occurred at ");
		buf.append(Calendar.getInstance().getTime().toString());
		buf.append(" on line ");
		buf.append(elements[0].getLineNumber());
		return buf.toString();
-----------
		StackTraceElement[] elements = ex.getStackTrace();
		return 	"The exception " + ex.getClass().getName() +
				" occurred at " +
				Calendar.getInstance().getTime().toString() +
				" on line " + elements[0].getLineNumber();
-------------
どちらを使うべきかはケースバイケース.

ただ,この次で可読性を重視しているわりに,ここでは可読性や記述性を
無視した記述をしているのは,どうにもバランスが悪い.

・7.1.2 国際化の性能の改善
全般的に正しい主張と言えるのか.

確かにオーバーヘッドもあるし面倒ではある.

だが文字列定数を使って置き換えることが,その解決策と言えるだろうか.オー
バーヘッドは柔軟にするための避けられない代償だし,そのコストも十分に許容
範囲内.使い勝手が悪いのは事実だが,これは文字列定数を使ってもさほど改善
されない.

GCで回収されると言う点については,リソースは再利用されることが多いので,
単に到達不可能になったものを全て回収/再生成することがはたして効率的とい
えるか疑問.むしろWeak Referenceなどを使って,ある程度能動的に制御すべき
では.ざっと見た限りではそこまで考慮しているようには見えない.

・ビットフィールド
余談になるが,C言語や2進数を理解していない人だと,この説明だと
理解するのは難しいのでは.

・ビットフィールドの問題点.
ビットフィールドを生で使っていることを仮定しているらしいが,普通はビット
フィールドはクラス内部の実装の一つで,生で見せることは滅多にしないのでは
ないか.制約についても拡張性の制限についても,これらはフィールドを隠蔽せ
ずに直接外部から触れるようになっていれば,ビットフィールドであろうと無か
ろうと同様の問題が発生する.

・オプション定数
要するにC言語ではenumで実現するようなもの?
挙げられている欠点もenum型と同じ.

結論としては
「このような欠点が問題となる場合はTypeSafeEnumを使いましょう」
「詳細はEffectiveJava参照.」
かな?

Errata 168を見る限り,どうやらそうらしい.
きっと同じツッコミがあったんでしょう.
著者はEffectiveJavaを読んでいなかったのかも.
----------
<168> First paragraph after the heading Constant Objects
Before the last sentence in the paragraph that reads: 
To understand how constant objects work, look at the constant object
class in Example 7-8.Add the following as a note: 

    The Constant Object paradigm is a further development of a concept
    known as the メTypesafe Enum Patternモ introduced by Josh Bloch in his
    book Effective Java. For those of you familiar with this pattern,
    The constant object paradigm expands on it significantly by
    introducing re-use, serialization, lookup and much more.  
----------
#日本語版のP172,一つ目の段落直下に相当

・P175 1つ目のサンプルコード直下.
「このコードは2つのメモリ位置の比較になります.」

毎度お馴染みのセリフだけど,これは実装依存でメモリ位置の比較になるとは限
らない.特に分散メモリマシンではメモリ位置の比較に意味はなくなる.ただし
コスト的にはほとんどの場合で,それと同等なものになると考えられる.

・P179 2つ目の段落
「メモリ位置を元に決定されるハッシュコードが異なることです.」
毎度お馴染みのセリフだけど,これはおそらく間違い.

そういう実装だと,同じオブジェクトでもGCでメモリ位置が移動するたびにハッ
シュ値も変わってしまう.

・P185 2つ目の段落
「これにより定数オブジェクトの持つオブジェクト指向パラダイムが侵害される
ことです.」

訳や表現の問題かもしれないが「オブジェクト指向パラダイムが侵害される」と
はなんぞや?

たしかに不変オブジェクトは扱いやすく,不変オブジェクトとして設計され利用
されているオブジェクトが,後から可変に変更されることは好ましくない.だが
最初から可変として設計されているなら,なんら問題はない.

・P185, 3つ目の段落
「混在モードのオブジェクトを使用した際に」

「混在モード」或いは「モード」とはなんぞや.
前後の文脈から言いたいことは予想できるが,あまりに漠然としすぎている.


-- 
murayama <locutus@xxxxxxxxxxxxxxxx>