きり丸の技術日記

技術検証したり、資格等をここに残していきます。

【設計論】文字列だと単純にラップした型でも便利

ちょっとポエム寄りのお話です。

プリミティブ型をラップした型を作成することは、対象の業務を表現できることがメリットです。たとえば、主キーのIDが文字列だった場合に、次の制約があった場合でもプリミティブ型では伝えられません。

  • 頭文字3桁がシステム略称名
  • 全体で10桁
    • 例:ABC0000001

他にも本はISBN型を所持しています。ISBNは次の制約を持っていますが、プリミティブ型の場合は伝えられません。

  • 10桁か13桁
  • 末尾1桁がチェック用数値

型を自作すると、システムで使用している大事な概念に対して命名でき、システムで異常値が入らないような制約をかけることができて安全に開発を進められることがメリットです。


今までの私は、業務を表現することのみに対して型を作成しようとしていました。もちろん、それも大事な概念です。しかし、制約を掛けるという点に着目すると、業務を表現しなくてもよいのではないのかと考えました。

Javaの場合、nullの文字列を結合すると「null」という文字列になってしまいます。以前、Javaで文字列結合時に「null」とならないようにするための記事を書きました。

コンストラクタでnullだった場合、空文字に置換するラップ型を作成することで、文字列結合で「null」にならないように回避できます。

public class AppString implements Serializable {
  private String value;

  public AppString(String value){
    if (value == null) {
      this.value = "";
    } else {
      this.value = value;
    }
  }

  public String getValue() {
    return value;
  }
}

ただ、「null」回避のためだけに型を用意するのは変換の手間もあり、可読性が落ちてしまいます。このユースケース単体だと私は採用しません。

他のユースケースとして、バリデーションがあります。自分のシステムでは問題ないものの、帳票印刷するシステムと連携したときに印刷不可能文字が含まれていると、文字化けしてしまうためにバリデーションをかける必要があります。

たとえば、SJISに変換できない文字バリデーションかけるとします。

public class AppString implements Serializable {
  private String value;

  public AppString(String value){
    if (isIllegal(value)) {
      throw new RuntimeException("許容不可能な文字が含まれています");
    }
    if (value == null) {
      this.value = "";
    } else {
      this.value = value;
    }
  }

  public static boolean isIllegal(@Nullable String value) {
    if (value == null) {
      return false;
    }
    try {
      if (!value.equals(new String(value.getBytes("SJIS"), "SJIS"))) {
        return true;
      }
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
    return false;
  }

  public String getValue() {
    return value;
  }
}

このように表現することで、「システムで扱える文字列」であると制約を表現できます。ここまで採用できたら、かなり有用ではないでしょうか。

本来であれば、この概念について適切な名前があるとうれしいのですが、私は思いつきませんでした。アプリケーションの文字列型という意味での「AppString」、システムの文字列型という意味での「SystemString」等々よりも適切な文字列が浮かびませんでした。異常値であれば「禁則文字列」という表現もできるのですが「正常文字列」は意味が分かりませんですしね…。

終わりに

類似情報に記載しているアノテーションでのバリデーションを実装しようとしたときに、バリデーションロジックと概念の凝集度が低かったので、処理を寄せるためのシステム文字列を思いつきました。

一流エンジニアの方々は、どうやって凝集度を高めたり、命名しているんですかね。プリミティブな型の方が使いやすいのは間違いないので、インタフェースで絶対受け取らないようにガードして、ビジネスロジック側はプリミティブ型で扱っているのでしょうか。

完全な思い付きの記事ではあるので、もし便利な点や実際に使ってみての使用感等々を会話してみたいです。

類似情報

一緒に読むと、オススメの記事です。