第18章 開発
18.1. 方法論の概要
以下の図は、OptaPlanner ソースコードの全体的な構造を示します。
上の図では、設定とランタイムクラスの明確な境界を理解することが重要です。
開発体系には、以下が含まれます。
- 再利用: 例は、統合テスト、ストレステスト、およびデモで再利用されます。ドキュメントのイメージはスライドで再利用されます。
-
一貫した用語: 各例には
App
クラス (実行可能なクラス)、Dao
(Data Access Object)、Panel
(swing UI) が使われています。 -
一貫性した構造: 各例では同じパッケージが使われています (
domain
、persistence
、app
、solver
、およびswingui
)。 - 現実世界の有用性: 例ではすべての機能が使用されています。ほとんどの例は、実在する制約を使用した実在するユースケースで、多くの場合、実在するデータが使用されています。
- 自動テスト: ユニットテスト、統合テスト、パフォーマンス不具合テスト、およびストレステストがあり、テスト対象は広範囲です。
- フェイルファーストと理解可能なエラーメッセージ: 無効な状態は、できるだけ早く確認されます。
18.2. 開発ガイドライン
フェイルファーストには段階がいくつかあります (重大度は、下になるほど悪くなります)。
-
コンパイル時の失敗。たとえば、
String
またはInteger
が必要な場合に、Object
をパラメーターとして取りません。 -
起動時の失敗。たとえば、設定パラメーターに正の
int
が必要な場合に負の値を設定すると失敗します。 -
ランタイム時の失敗。たとえば、リクエストで
0.0
から1.0
までの二重階層が必要な場合に、1.0
より大きい値を設定すると失敗します。 - アサーションモードにおけるランタイム時の失敗 (検出のパフォーマンスコストが高い場合)。たとえば、低水準の反復後に必ず変数 A を B の 平方根にする必要がある場合は、アサートフラグが true に設定されている場合に限りそれを確認します (通常は EnvironmentMode で制御)。
-
コンパイル時の失敗。たとえば、
例外
メッセージ例外
メッセージには、以下のように、関連する変数の名前およびステータスが含まれます。if (fooSize < 0) { throw new IllegalArgumentException("The fooSize (" + fooSize + ") of bar (" + this + ") must be positive."); }
出力では、問題が明確に説明されています。
Exception in thread "main" java.lang.IllegalArgumentException: The fooSize (-5) of bar (myBar) must be positive. at ...
-
可能な限り、
例外
メッセージにはその背景が含まれます。 修正方法が明らかではない場合は、
例外
メッセージにアドバイスが含まれます。アドバイスは通常、行が変わり、 maybe という単語から始まります。Exception in thread "main" java.lang.IllegalStateException: The valueRangeDescriptor (fooRange) is nullable, but not countable (false). Maybe the member (getFooRange) should return CountableValueRange. at ...
maybe という単語は、そのアドバイスがすべてのケースで正しいことが保証できないことを示しています。
-
ジェネリック型。しばしば、
Solution
クラスがジェネリック型パラメーターとしてサブシステムに渡されます。PlanningEntity
クラスがジェネリック型パラメーターとして渡されることはほとんどありません。