Open10

DTO作るとき、パラメーター多すぎ問題どうしよう。【PHP】

@tyamahori@tyamahori
<?php

namespace Tyamahori\Sample;

use InvalidArgumentException;

class TyamahoriDto
{
    /**
     * 型チェックはコンストラクトで行い、完全コンストラクタにする
     *
     * phpdocでも配列の型定義を書いて固くする
     * @see https://tech-blog.rakus.co.jp/entry/20210326/php#%E9%85%8D%E5%88%97%E5%9E%8B
     * @param array {
     *  id: string,
     *  }
     *  $parameter
     */
    public function __construct(
        private array $parameter
    ) {
        // とりあえず簡易的なチェック。
        // VOにしたらもっと固く出来そう。
        if (empty($parameter['id'])) {
            throw new InvalidArgumentException('id is required.');
        }
    }

    /**
     * @return string
     */
    public function id(): string
    {
        return $this->parameter['id'];
    }
}

$dto = new TyamahoriDto([
    'id' => 'someString'
 ]);

var_dump($dto->id());
@tyamahori@tyamahori

結論

  • 配列で良いのでは?
  • VOを配列に入れておくと良さそう
  • 配列の方をphpdocで行っておきたい
  • コンストラクタできちんと配列チェックを行って予期しないものが来たら例外を投げる。
  • 完全コンストラクタの方向が良さそう!
@tyamahori@tyamahori

横着するならこれかな。

<?php

namespace Tyamahori\Sample;

use InvalidArgumentException;
use Throwable;

class TyamahoriDto
{
    private string $id;

    private SampleValueObject $value;

    /**
     * 型チェックはコンストラクトで行い、完全コンストラクタにする
     *
     * phpdocでも配列の型定義を書いて固くする
     * @see https://tech-blog.rakus.co.jp/entry/20210326/php#%E9%85%8D%E5%88%97%E5%9E%8B
     * @param array {
     *  id: string,
     *  value: SampleValueObject
     *  }
     *  $parameter
     */
    public function __construct(
        array $parameter
    ) {
        try {

            $this->id    = $parameter['id'];
            $this->value = $parameter['value'];

        } catch (Throwable $throwable) {
            throw new InvalidArgumentException($throwable->getMessage());
        }
    }

    /**
     * @return string
     */
    public function id(): string
    {
        return $this->id;
    }

    /**
     * @return SampleValueObject
     */
    public function sampleValue(): SampleValueObject
    {
        return $this->value;
    }
}
@tyamahori@tyamahori

これのほうがいい感じがする

<?php

namespace Tyamahori\Sample;

use InvalidArgumentException;

class TyamahoriDto
{
    private string $id;

    private SampleValueObject $value;

    /**
     * 型チェックはコンストラクトで行い、完全コンストラクタにする
     *
     * phpdocでも配列の型定義を書いて固くする
     * @see https://tech-blog.rakus.co.jp/entry/20210326/php#%E9%85%8D%E5%88%97%E5%9E%8B
     * @param array {
     *  id: string,
     *  value: SampleValueObject
     *  }
     *  $parameter
     */
    public function __construct(
        array $parameter
    ) {

        if (empty($parameter['id'])) {
            throw new InvalidArgumentException('id is required.');
        }

        if (empty($parameter['value']) || !$parameter['value'] instanceof SampleValueObject) {
            throw new InvalidArgumentException('id is required.');
        }

        $this->id    = $parameter['id'];
        $this->value = $parameter['value'];
        
    }

    /**
     * @return string
     */
    public function id(): string
    {
        return $this->id;
    }

    /**
     * @return SampleValueObject
     */
    public function sampleValue(): SampleValueObject
    {
        return $this->value;
    }
}
@tyamahori@tyamahori

DTO パラメータは VOクラスの方が良さげ。数が多ければ配列に入れ込んでコンストラクタでチェックや!