asatoの技術的な日常日記

「成長に最大の責任をもつ者は、本人であって組織ではない。自らと組織を成長させるためには何に集中すべきかを、自らに問わなければならない」  非営利組織の経営 - ピーター・ドラッカー

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

コード進化パターン:要求変更からコード進化パターンへ

一つ前の記事は、Java での コード進化のパターン の一つとして「View コードの変更」があることを紹介した。

このパターンを簡単に言えば、いわゆる Model-View-Controller (MVC) のビューに関するコードを変更するということ。

何も変化がなければ、この進化パターンは起こらない。実際にどんな要求仕様の変更があったのか?


具体的に何かというと、僕が今作ってるゲーム(不思議のダンジョン系)での要求変更。一人で作っているので、僕が「ユーザ」と「開発者」の二つの役割を持ってる。

見た目の変化は次の画像からわかるように「クリティカル率」を「必殺率」に変えた点。

見た目変更前:
view_change_before.png


見た目変更後:
view_change_after.png




ユーザと開発者の仕様の変更のやりとりはこんな感じ:

ユーザ「もっとステータス画面うまく表示できないですかね? クリティカル率って他のと比べて長くないですか?」

開発者「分かりました。クリティカルじゃなくて、じゃあ、同じような意味の必殺でいいですかね? 文字数もちょうどそろいますし」。

ユーザ「それでいいんじゃないですか」



で、実際にどの部分のコードが変更されたか。StatusViewDrawer クラスがこのステータス画面の見た目を描画してる。

変更前のコード:


public class StatusViewDrawer implements GameViewDrawer {

private GameManager gameManager ;

public StatusViewDrawer(GameManager gameManager ) {
this.gameManager = gameManager;
}

public void draw(Graphics g) {

...

Player player = env.getPlayer();

drawStringWithShadow(g, "攻撃力     " + player.getAttackPoint(), baseX + 20, baseY + 30);
drawStringWithShadow(g, "防御力     " + player.getGuardPoint(), baseX + 20, baseY + 60);
drawStringWithShadow(g, "命中率     " + player.getStatus().getHitRate(), baseX + 20, baseY + 90);
drawStringWithShadow(g, "回避率     " + player.getStatus().getAvoidRate(), baseX + 20, baseY + 120);
drawStringWithShadow(g, "クリティカル率 " + player.getStatus().getCriticalRate(), baseX + 20, baseY + 150);

drawStringWithShadow(g, "経験値 " + player.getEXP(), baseX + 20, baseY + 180);

int nextLvExp = env.getPlayer().getNextExp() - env.getPlayer().getEXP();
drawStringWithShadow(g, "次のレベルまで " + nextLvExp, baseX + 20, baseY + 210);
...
}
...
}



変更後のコード:


public class StatusViewDrawer implements GameViewDrawer {

private GameManager gameManager ;

public StatusViewDrawer(GameManager gameManager ) {
this.gameManager = gameManager;
}

public void draw(Graphics g) {

...

Player player = env.getPlayer();

drawStringWithShadow(g, "攻撃力 " + player.getAttackPoint(), baseX + 20, baseY + 30);
drawStringWithShadow(g, "防御力 " + player.getGuardPoint(), baseX + 20, baseY + 60);
drawStringWithShadow(g, "命中率 " + player.getStatus().getHitRate(), baseX + 20, baseY + 90);
drawStringWithShadow(g, "回避率 " + player.getStatus().getAvoidRate(), baseX + 20, baseY + 120);
drawStringWithShadow(g, "必殺率 " + player.getStatus().getCriticalRate(), baseX + 20, baseY + 150);

drawStringWithShadow(g, "経験値 " + player.getEXP(), baseX + 20, baseY + 180);

int nextLvExp = env.getPlayer().getNextExp() - env.getPlayer().getEXP();
drawStringWithShadow(g, "次のレベルまで " + nextLvExp, baseX + 20, baseY + 210);
...
}
...
}




考察:

この要求変更の場合、運よくコードへの変更は、一つのクラスの一つのメソッドだけが対象となっている。でも、場合によっては、複数のビュークラスを変更しなければならない場合もある。現実的にはありえないけど、たとえば、次のコードのそれぞれの行に対して、クラスを割り当てている場合など。



drawStringWithShadow(g, "攻撃力 " + player.getAttackPoint(), baseX + 20, baseY + 30);
drawStringWithShadow(g, "防御力 " + player.getGuardPoint(), baseX + 20, baseY + 60);
drawStringWithShadow(g, "命中率 " + player.getStatus().getHitRate(), baseX + 20, baseY + 90);
drawStringWithShadow(g, "回避率 " + player.getStatus().getAvoidRate(), baseX + 20, baseY + 120);
drawStringWithShadow(g, "必殺率 " + player.getStatus().getCriticalRate(), baseX + 20, baseY + 150);



このことからは、モジュール(この場合はクラス)を分割しすぎると、変更がしにくくなるかもしれないことを意味する。

また、ビュー以外のコードも変更になるかもしれない。

view_code_change.png

スポンサーサイト

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://asatohan.blog77.fc2.com/tb.php/87-5abdbdb6
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。