著作一覧 |
wildcatsさんの「私が思うリファクタリングとリストラクチャリングの違い」を読んでいて(というか、そのコメント欄でのやり取りを読んでいて)考えた。
概念的にフレンドアクセスとそれ以外の2つに分けて、フレンドにはclassを触らせることを許可して、それ以外にはinterfaceしか触らせないようにする。ではどうだろうか?
classにpublicなメソッドがあっても、それがinterfaceに定義されていない場合、それはフレンド用であって外部には触らせないということだ。すなわちpublicではあるが非published。
この場合、javadocはinterfaceのものしかpublishしない(javapして解析して呼ぶような相手の場合は、そもそも考慮しても無駄だから置いておくことにする)。
パッケージ0 → パッケージ1 ← パッケージ2
として、パッケージ1はinterfaceが定義されていてJavadocのpublish対象。
パッケージ0は実装そのもの。パッケージ2はパッケージ0の利用者(しかしパッケージ1経由でしか利用できない)。
以前だとパッケージ1にはパッケージ0に対するファクトリを入れておく必要があったと思うし、その呼び出しの手間とか考えるとパッケージ2の開発者から拒否反応が出そうな気もするが、今であればパッケージ1とパッケージ0のマッピングはDIによって実現できるからそのほうが(ファクトリの実装を不要化できるから)お互いに楽だと思う。
ただ、複数の責務を持つpublishedなメソッドって別に構わないと思うので(サービスだ)そこは違和感を覚えた。レイヤー分けの問題に過ぎないと思うからだ。具体的にはpublishedなメソッドの中で複数の単責務なメソッドを呼び出すという考え方を取れば良いし、その単責務なメソッドを同一パッケージ内の複数のクラスやあるいは同一クラスの複数のメソッドとして分ければよいのではなかろうか? というか、外部へ公開するということはそういうことだと思う。複数のメソッドの呼び出しには呼び出し順序の依存やステートの遷移が伴う。したがって、1回の呼び出しで済ませられるのであればそのほうが単に呼び出し側の利便性が向上するだけではなく、状態遷移の制御も単純化できると思う。(追記:ファサードのことだな)
追記:だから、そういう風に再構成すれば、外部インターフェイスは変わらないよね? そこがなぜ、他のクラスに影響を与えることになるのか不思議なのだが。
public void createHTML(String fileName) { Bean bean = new Bean(); // Beanに対する設定 // HTMLの作成 VelocityContext context = new VelocityContext(); context.put("bean-name", bean); BufferedWriter writer = new BufferedWriter(new FileWriter(fileName)); Template template = Velocity.getTemplate(vmName); template.merge(ctx, writer); writer.flush(); }を
public void createHTML(String fileName) throws IOException { Bean bean = buildBean(); writeToHtml(fileName, bean); // 追記:メソッド名を変えた } public Bean buildBean() { Bean bean = new Bean(); // Beanに対する設定 return bean; } public void writeToHtml(String fileName, Bean bean) throws IOException { // HTMLの作成 VelocityContext context = new VelocityContext(); context.put("bean-name", bean); BufferedWriter writer = new BufferedWriter(new FileWriter(fileName)); Template template = Velocity.getTemplate(vmName); template.merge(ctx, writer); writer.flush(); }
と変えても外部インターフェイスは変わらないと思うんだけど。
ジェズイットを見習え |
ご指摘の通りで<br>・createHTMLメソッドをpublished<br>・buildBean・writeToHTMLをpublic<br>だとすれば責務としては問題ないですね。<br><br>あとはcreateHTMLメソッドのテストケースを<br>buildBean・writeToHTMLメソッドに対応させればOKです。
たびたびすいません。<br><br>このリファクタリングだと1クラスに複数の責務があるので<br>buildBean・writeToHTMLは別のクラスにしたほうがいいですね。
>buildBean・writeToHTMLは別のクラスにしたほうがいいですね<br>Beanについてはbuildreがいたほうが良さそうに思いますが、設定内容次第かも知れません。<br>でもwriteToHtmlっていろいろ考えられるような気がします。<br>1. HTMLの出力はVelocityが実行している=元のクラスは利用者の立場で一貫しているからこのままで良い<br>2. Beanが自分のHTML表現を出力するように実装するのが良い<br>3. VeolocityとBeanを結合してHTMLを出力するクラスがいるべき<br>どうなんでしょうね? (僕だとリファクタリングという点からは1を選択するかな)
すみません。やっぱり1は汚いかも知れませんね。<br>こういう大雑把な決め方が属人性がどうしたというような話題になるのかな。