🤖

DDDのValueObjectをCSVから一括生成する「UnitGeneratorTemplate」をリリースしました

2022/05/19に公開約2,600字

私はValueObject好きなんですが、でも実装って案外面倒ですよね。

recordが登場してだいぶ楽になりましたが、それでも不十分な側面が多くあります。

それらの課題を解決してくれるライブラリーとしてUnitGeneratorがあります。

非常によくできていて痒い所に手が届くのですが、それで大量に作ると大変です・・・

というわけで、CSVに設定を定義すると一括生成してくれるテンプレートライブラリー「UnitGeneratorTemplate」をリリースしました!

UnitGenerator

UnitGeneratorTemplateはCSVに設定を記載することで、UnitGeneratorを利用したValue Objectを一括で自動生成するためのテンプレートパッケージです。

T4テンプレートとCSVを利用して、任意のUnitを一括で作成できます。

Getting Started

UnitGeneratorとUnitGeneratorTemplateをNuGetからインストールします。

Install-Package UnitGenerator
Install-Package UnitGeneratorTemplate

パッケージをインストールすると、2つのファイルが追加されます。

  • UnitGenerator.csv
  • UnitGenerator.tt

UnitGenerator.csvに生成したいUnitを定義し、UnitGenerator.ttでコードを生成します。

こちらはCSVをVisual Studio Codeの「Edit csv」拡張で開いたものです。

CSVにはつぎのように指定します。

説明 指定例
Name 生成する構造体の名称 UnitId
Type 値の型 int
Description 生成する構造体のTypeコメント UnitのIDを表す値オブジェクト
Format ToString時のフォーマット {0:###,###,###}
ImplicitOperator以降 UnitGeneratorに指定する属性 指定しない場合は空。指定する場合はそれ以外。

CSVを編集したあと、UnitGenerator.ttファイルを開いて「Ctrl+s」を押すか、UnitGenerator.ttのコンテキストメニューから「カスタムツールの実行」を押します。

すると次のようにUnitGenerator.ttの下にUnitGenerator.csファイルが作成されます。

Validate

Validateの利用方法は、ほかのOptionとはやや異なります。

Validateを使う場合、判定ルールをつぎのいずれかの方法で指定します。

  1. CSVのValidate列に判定条件を記載する
  2. Validateメソッドをpartialに独自実装する

CSVのValidate列に判定条件を記載する

たとえばint型のUnitの場合に、値を10未満とする場合、Validate列に次のように記載します。

Name Type Validate
UserId int value < 10

この時、例外クラスとメッセージを変更したい場合、UnitGenerator.ttファイルを編集します。

<#@ template debug="false" hostspecific="true" language="C#" #>
...
<#  
var validateException = "InvalidOperationException";
var validateExceptionMessage = "Invalid value range: {value}";
#>

validateExceptionとvalidateExceptionMessageを任意の値に変更してください。

Validateメソッドをpartialに独自実装する

この場合、CSVにはつぎのように有効化のみ指定します。

Name Type Validate
UserId int

1文字以上、5文字以下の文字列であれば何を指定してもかまいません。

6文字以上の場合は、式が指定されているとして判断します。

Validateメソッドは、つぎのようにpartialとして実装してください。

public partial struct UserId
{
    private partial void Validate()
    {
        if (5 < value) throw new InvalidOperationException($"Invalid value range: {value}");
    }
}

Discussion

ログインするとコメントできます