技術とか戦略とか

証券レガシーシステムを8年いじってから転職した普通の文系SEによるブログ。技術のみではなく趣味の戦略考察についても。

10000STEPのクラスを作ってしまった話

「1クラス1000STEPを超えたらクラス分割を考える」という話をどこかで見たり聞いたりした記憶がありますが、金融業界の実務では10000STEP越えのクラスを目にすることは少なくありません。
そして、私も趣味(ゲームの戦闘部分の作成)で10000STEP越えのクラスを作ってしまったので、どのようにして10000STEP越えのクラスが出来上がったのか記録として残したいと思います。
 
1クラスのSTEP数を減らすには「共通処理の部品化」「別クラスとして切り出し」「ロジックの見直し」といった方法があると思うのですが、これらの方法を全て検討した上で10000STEPを超えました。
 
【クラスの内容】
魔法・技コード毎に処理を記述するクラスで、10000STEPを超えました。
以下のような分岐が100個近くあり、それを1つのクラスにまとめたので、STEP数が増加しました。
 
switch (魔法・技コード) {
case 1:
    // コード1の処理の記述
    break;
case 2:
case 65:
    // コード2・コード65の処理の記述
    break;



 
【検討した対応方法】
1.共通処理の部品化
 全ての魔法・技コードで共通で使われる処理は既に部品化した後です。
 (これを部品化しなければSTEP数は3~5倍になります)
 
2.別クラスとして切り出し
 魔法・技コード毎に別クラスとして切り出すことは考えましたが、没にしました。
 この方法で1つのクラスのSTEP数を減らしても、
 全体としての複雑性は変わりません。
 それだけでなく、切り出すとクラスが100個近くになるので、
 ソース管理が大変になります。
 
 実務だとクラス毎に別々の開発者を割り当て、
 並行作業でコーディングできる強みはあるかもしれません。
 しかし、開発者毎で実装にバラつきが出ると品質管理が困難になります。
 元々のルールが複雑なので、少しのバラつきでも混乱の元になります。
 また、バラつきが出ないように厳しくコードレビューすると、
 レビュー工数や手戻り工数がかかることになります。
 実務だとしても、クラスを切り出さずに1人の開発者に実装を任せたいです。
 
3.ロジックの見直し
 複数の魔法・技コードで同じ処理をしている箇所はあります。
 そのため、以下のようにif文で細かく分岐を作ればSTEP数を減らせるのですが、
 この案も結局没にしました。
 
 // 初期処理
 if (魔法・技コード == 1 || 魔法・技コード == 30){
     // コード1・コード30の処理の記述
     if (魔法・技コード == 1) {
         // コード1でのみ行われる処理
     }
 } else if …
 :
 :
 :
 // ダメージ計算処理
 if …
 :
 :
 :
 // 追加効果処理
 if …
 :
 :
 :
 
 if文で分ける方式だと確かにSTEP数は減りますが、
 これでは処理が複雑になり保守性が低下します。
 例えば、魔法・技コード1がどのような処理を行うのか、
 クラス全体の分岐を追わないとわからなくなります。
 (俗に言うスパゲッティコードのようになります)
 
 if文で分ける方式だと重複した記述は少なくなるので、
 テストケースを減らして工数削減ができる可能性はあります。
 しかし、結局どこかのタイミングで全ての魔法・技コードを試さざるを得ないので、
 劇的にテストが楽になるわけではありません。
 
 処理の簡潔さとテストケースの少なさを天秤にかけて、
 今回は処理が簡潔になるswitch~case方式を採用することにしました。
 元々ルールが複雑だったので、実装で余計に複雑にするのは避けました。
 if文で分ける方式の場合、
 ドキュメントを整えてロジックを整理しないとテスト以前に実装がままならず、
 テスト工数を減らせたとしても結局実装の準備で工数を取られてしまいます。
 
【実装を終えての感想】
元々のルールが複雑だと、STEP数を減らすのには限界があると思いました。
金融業界も法令や金額計算のルールが複雑なので、10000STEP越えのクラスが出てくるのも必然だと思いました。
STEP数を減らすことを第一目的にするなら減らすことは可能です。
しかし、元々のルールが複雑なので、実装で余計に複雑にするのは避け、STEP数が増えても良いのでルール通りに愚直にビジネスロジックを実装するのが重要だと思いました。