今のプロジェクトでの構成管理

とりあえずSVNのフォルダ構成はこんな感じ。単一リポジトリ複数trunk型ですね。僕がこのプロジェクトに入った時点でこうなってた。僕は単一リポジトリ単一trunk型がいいと思っていたんだけど、こっちのほうがいいかも。プロト置き場は必要だけど別にドキュメントとかと同期させる必要無いしね。

http://.../svn/ProjectA/
    |
    |---prototype/ プロトタイプソース置き場
             |---trunk/
             |---tags/
             |---branches/
    |---doc/ ドキュメント置き場
             |---trunk/
             |---tags/
             |---branches/
    |---src/ 本番用ソース置き場
             |---trunk/ 
                         |--sample-project/            
                                      |
                                      |--build.properties
                                      |--build.xml
                                      |--build-common.xml  macrodefなど共通のターゲットを定義したビルドスクリプト
                       |--sample-common/ 共通的に用いられるユーティリティクラスなどの置き場
                                      |
                                      |--build.properties
                                      |--build.xml
                                      |--.classpath
                                      |--.project
                                      |--.settings/
                                      |
                                      |--lib/ ライブラリ
                                      |
                                      |--libsrc/ ライブラリのソース
                                      |
                                      |--testlib/ テストライブラリ
                                      |
                                      |--src/
                                             |--main/
                                                    |--java/ プロダクトコード
                                                    |--resources/ プロダクトリソース

                                             |--test/
                                                    |
                                                    |--java/ テストコード
                                                    |--resources/ テストリソース
                       |
                       |--sample-web/ webアプリ(sample-commonに依存している)
                                      |
                                      |--build.properties
                                      |--build.xml
                                      |--.classpath
                                      |--.project
                                      |--.settings/
                                      |
                                      |--lib/ ライブラリ
                                      |
                                      |--libsrc/ ライブラリのソース
                                      |
                                      |--src/
                                             |--main/
                                                    |--java/ プロダクトコード
                                                    |--resources/ プロダクトリソース
                                      |--WebContent
                                             |
                                             |--WEB-INF/
                                                    |
                                                    |--page/  JSP置き場
                                                  
             |---tags/
             |---branches/
    
    

当初はプロダクトコードとテストコードのプロジェクトを分ける構成としたが(テストコードのライブラリにプロダクトコードが依存しちゃってもEclipseではコンパイルエラーにならない問題をさけるため)いまは同じにしている。

理由はプロジェクト数が増えすぎて見通しが悪くなったことや、テストコードのプロジェクトがどのプロジェクトに依存するかを判断しビルドスクリプトをメンテしていくのが面倒だったため。

ビルドスクリプトは下記にならってmacrodefを使ってjavacタスクなどを共通化してみた。クラスパスをrefidで受け取る感じ。他にも完全に共通なターゲットをくくりだして、使用側でimportしてつかっている。macrodefで良くなったかは微妙。タイプ量がそんなに減るわけでもないし。

ThoughtWorksアンソロジー ―アジャイルとオブジェクト指向によるソフトウェアイノベーション

ThoughtWorksアンソロジー ―アジャイルとオブジェクト指向によるソフトウェアイノベーション

テスト用のビルドスクリプトコンパイル、パッケージング用のビルドスクリプトは分けずに1つにしている。前回のプロジェクトではこれを分けたせいかビルドスクリプトがいっぱいになってよくわからなくなったから。

DBのIPアドレスのようにローカル環境と結合環境での違いが出るものは、replacetokenとreplacevalueで置換しているがreplacevalueに${db.it.url}のようにプロパティを指定できないため、べた書きになってる。これがイマイチ。複数あるし。

前回のプロジェクトでは下記の本を読んだ影響で、Antのsqlタスクを使ってビルドのたびにDBも作り直すという継続的データベースインテグレーションもどきもやっていた。

継続的インテグレーション入門

継続的インテグレーション入門

今回のプロジェクトではAntのsqlタスクを使う代わりにDBFluteのReplaceSchemaを使っている。ただしReplaceSchemaはデフォルトではインタラクティブなコンソールアプリなので非インタラクティブになるように環境変数answerをyにする。ローカル環境と結合環境での違いは環境変数 DBFLUTE_ENVIRONMENT_TYPEで切り替える。テストデータはExcelです。一部DBUnitも使ってます。DBUnitも新しいバージョン使うとログライブラリにslf4j使ってるせいかアプリのログが出なくなったので古いバージョン使ってる。あとOracleのTimeStampの問題にハマったりもした。

クリーンビルド、DBの作り直し、カバレッジ取得も含めて現状のビルドは約440のテストケースで30分弱かかっている。遅いよね。ちなみに実際にDBアクセスもしている。

一部FTPサーバが必要だったりする箇所があったのでモックも考えたけど、コードがstaticメソッドのみのユーティリティでメソッドのなかでnewしているのであきらめて@ignoreしてる。でもこれHudsonのレポートに表示されないんだよな。Antの問題らしいけど。もしテストするとすればファクトリーメソッドのなかでnewするようにして、サブクラスでダミーに差し替えてテストするかんじか。staticメソッドはオーバーライドできないのでstaticメソッドはなしにする。djunit使えばnewしててもモックかけられるけど前のプロジェクトはそれやっていろいろとアレだったのでそれはしない。つうかdjunit使わないとダメだという時点でテストしにくいコードなんだろう。

まあこんなかんじです。