メソッドにサフィックス付けた奴出てこい


はじめに

この記事は一人のSEのストレスを発散する記事です。
内容によっては、どなたかの役に立つかもしれません。

何するの?

正規化に失敗したRDBMSを、ストレス発散のためにリフレクションを使ってソースをスッキリさせます。パフォーマンスは考えない。

実際どんなのか

決してホスト等のレガシー技術を批判したいわけではないことを、最初に断らせて頂きます。
ホストでのセグメント?にサフィックスを付けることがよくあるようです。
昨今ではホスト⇛Webのダウンサイジング案件は少なくなっているそうですが、直近で私がダウンサイジング案件でお目に掛かった正規化の失敗に対する、個人的なストレス発散です。

ダウンサイジングの際に、項目01~05みたいなのが一つのテーブルにホストの考えそのままに持ち込まれてしまったことが諸悪の根源です。

例)
TBL名
 口座管理店舗テーブル
カラム
 店舗コード(PK)
 支店01
 支店02
 支店03
 支店04
 支店05

といった感じに、口座を管理する親店舗の下に支店をぶら下げる構成にしたかったのです。
が、本来ならちゃんと正規化を行って、「親店舗コードにぶら下がる支店テーブル」を作るべきです。
支店が増えたときの変更にとても脆いですよね。

とはいえ

私もエンジニアの端くれです。そして雇われの身ですので、変えられないものはそうとしてなんとか飲み込み、うまく対応するのを目指す大人(30半ば)です。

こんな感じでどうや

まずはsuffix付きのgetterを用意。
ただ長いだけなので畳んでおきます。

suffixMethods
suffixMethods.java
package suffixMethodsCall;

public class suffixMethods {


    private static String RETURN_CODE_A = "A";
    private static String RETURN_CODE_B = "B";
    private static String RETURN_CODE_C = "C";
    private static String RETURN_CODE_D = "D";
    private static String RETURN_CODE_E = "E";
    private static String RETURN_CODE_F = "F";
    private static String RETURN_CODE_G = "G";
    private static String RETURN_CODE_H = "H";
    private static String RETURN_CODE_I = "I";
    private static String RETURN_CODE_J = "J";

    public String getReturnCode01() {
        return RETURN_CODE_A;
    }

    public String getReturnCode02() {
        return RETURN_CODE_B;
    }

    public String getReturnCode03() {
        return RETURN_CODE_C;
    }

    public String getReturnCode04() {
        return RETURN_CODE_D;
    }

    public String getReturnCode05() {
        return RETURN_CODE_E;
    }

    public String getReturnCode06() {
        return RETURN_CODE_F;
    }

    public String getReturnCode07() {
        return RETURN_CODE_G;
    }

    public String getReturnCode08() {
        return RETURN_CODE_H;
    }

    public String getReturnCode09() {
        return RETURN_CODE_I;
    }

    public String getReturnCode10() {
        return RETURN_CODE_J;
    }
}

実行クラスを作りました。

suffixMethodsCaller.java
package suffixMethodsCall;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class suffixMethodsCaller {

    /**
     * <pre>
     * suffixMethodsに含まれる、suffix付きのgetterを全て実行し、
     * 冒頭のmatchTargetCodeが含まれるか検証する.
     * </pre>
     */
    public static void main(String[] args) {

        // マッチング対象の文字列
        String matchTargetCode = "J";
        // suffix付きのメソッドから取得できたコードリスト
        List<String> codeList = new ArrayList<String>();

        // クラス、メソッドを文字列で指定
        suffixMethods sm = new suffixMethods();
        String clazz = sm.getClass().getName();
        String baseSuffixMethod = "getReturnCode";
        int suffixPartStart = 1;
        int suffixPartEnd = 10;

        // リフレクションを利用して、suffix付きのメソッドを実行
        try {
            Class<?> c = Class.forName(clazz);
            Object myObj = c.newInstance();

            // suffix部分をループさせてコードリストに突っ込む
            for ( ; suffixPartStart <= suffixPartEnd; suffixPartStart++) {
                // 実行メソッドの設定
                Method m = c.getMethod(baseSuffixMethod + String.format("%02d", suffixPartStart));
                // コードリストに詰め込む
                codeList.add(m.invoke(myObj).toString());
            }
        } catch(ReflectiveOperationException e) {
            e.printStackTrace();
        }

        // マッチング対象の文字列が、suffix付きメソッドの実行結果リストに含まれるのかboolで出力
        System.out.println(codeList.contains(matchTargetCode));
    }
}

ちょっとまだ汚いところがありますが、とりあえずの目標は達成できました。

今回のケースはsuffix付きのメソッドが10個を例に挙げたのですが、もっと数が増えるとパフォーマンスが気になります。

実行部分までを別メソッドに切り出して、よりスッキリさせることはできます。
が、リフレクションAPIへのアクセスと、ハードコーディングして全部String.equalsでマッチさせた場合はどっちが高パフォーマンスなんでしょう。

また検証してみます。

さいごに

今回はストレス発散を目的としてコーディングしましたが、リフレクションを使う機会が今までそんなになかったので、思いのほか時間が掛かってしまいました。

ダウンサイジングやマイグレーションPJはいつも本当に頭を悩ませます。愚直にやればできるけど、、なぁ、、、というのがたくさんありますよね。