DomainObjectからValueObjectを自動生成するOSS作ってみた ~ ts-vo-generator~

初めに

こんにちは。

PS/SLの佐々木です。

最近輪読会でDDDについての書籍を扱っているのですが、その中でValueObjectを作るのか作らないのか論争が巻き起こっています。

私自身作るに越したことはないと思うのですが、実装量が多くなるのと、必要なものだけ作ればいいのではないかと思う反面、作る作らないの判断が人によると一貫性のないコードになってしまう懸念点があります。

そこで今回はTypescriptでDomainObjectaのコンストラクタで定義されているプロパティからValueObjectを自動生成する ts-vo-generatorというライブラリを作成してみました。

ts-vo-generatorの使い方

こちらのライブラリはnpmとyarnで公開しています。(npm registry)

今回はnpmでインストールする例を紹介します。

npm install -g ts-vo-generator

使用する際には

npx typescript-value-object-generator <input_file> <output_directory>

このように使用します。

input_fileには解析対象のclassのパスを指定し、output_directoryにはValueObjectを生成するディレクトリを指定します。

実際に使用してみる

今回は以下のようなクラスからValuObjectを自動生成してみます。

type MountainType = {
    id: number;
    name: string;
    elevation: number;
    description?: string;
    range: string; 
}

// Mountain.ts
export class Mountain {
    private constructor(
        private id: number,
        private name: string, 
        private elevation: number,
        private range: string,
        private description?: string
    ) {}

    static new(props: MountainType): Mountain {
        return new Mountain(
            props.id,
            props.name, 
            props.elevation, 
            props.range,
            props.description
        );
    }

    public genMessage(): string {
        return `${this.name} の標高は ${this.elevation} mです。`;
    }
}

以下のコマンドを実行します。

npx ts-vo-generator ./src/model/Mountain.ts ./src/ValueObject

実行すると

/src/ValueObject 配下にDescription.tsId.tsが生成されていることが確認できます。


// Id.ts
export class Id {
    private constructor(private readonly value: number) {}

    static create(value: number): Id {
        if (!Id.isValid(value)) {
            throw new Error('Invalid value');
        }
        return new Id(value);
    }

    getValue(): number {
        return this.value;
    }

    private static isValid(value: number): boolean {
        // validation logic here
        return true;
    }
}

生成されたコードを見てみると上記のようなValueObjectのスケルトンコードが生成されています。

この後は好きなロジックを追加していきます。

また一度生成したものに関して再度生成しようとすると上書きするか処理をスキップするかを聞かれます。

今後の展望

現在のts-vo-generator ではValueObjectを作成後、元のClassの方にも手動でValueObjectを定義しないといけません。

近いうちにこちらの対応も行っていきたいと思います。

最終的には以下のようなところまで自動で生成したいと思っています。(現時点ではこの修正は手動です)

import { Id } from '../ValueObject/Id';
import { Description } from '../ValueObject/Description';
import { Elevation } from '../ValueObject/Elevation';
import { Name } from '../ValueObject/Name';
import { Range } from '../ValueObject/Range';

type MountainType = {
    id: Id;
    name: Name;
    elevation: Elevation;
    description?: Description;
    range: Range; 
}

// Mountain.ts
export class Mountain {
    private constructor(
        private id: Id,
        private name: Name, 
        private elevation: Elevation,
        private range: Range,
        private description?: Description
    ) {}

    static new(props: MountainType): Mountain {
        return new Mountain(
            props.id,
            props.name, 
            props.elevation, 
            props.range,
            props.description
        );
    }

    public genMessage(): string {
        return `${this.name.getValue()} の標高は ${this.elevation.getValue()} mです。`;
    }
}

終わりに

最後まで読んでいただきありがとうございました。

もしよろしけべばStarやコントリビュートお待ちしています。

gihtub

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です