型を厳密にしてコンパイル時に全部検出したい

適当な書き方でコード書いてます イメージです

まずこういうテーブルがあるとする

usersテーブル
--------------
| id | name    |
| 1  | tanaka  |
| 2  | yamada|
---------------

次にこのテーブルを対象としたORMがある

// Users entity
class UserEntity
{
   public int $id;
   public string $name;

   // なんかいい感じにGetterがある
}

// ORM
class UsersOrm
{
  // なんかいい感じにクエリ発行してくれるすごいやつ
  private orm $orm;

  public function getUser(int $id): UserEntity
  {
    $user_entity = $this->orm->selectQuery()->where('id', $id)->exec();
    return $user_entity;
  }

  public function getUserId(string $name): int
  {
    $user_entity = $orm->selectQuery()->where('name', $name)->exec();
    return $user_entity->getUserId();
  }
}

ORMを使うクラスがある

// ORM使うやつ
class Hoge
{
  public function hoge()
  {
    orm $users_orm = new UsersOrm();
    int $user_id = $users_orm->getUserId('tanaka');

    UserEntity $user = $users_orm->getUser(1);
    string $user_name = $user->getName();
  }
}

これの型を超厳密にしたい

  • intを継承した?UserId型を作りたい type UserId = int;
  • stringを継承した?UserName型をつくりたい type UserName = string;

↑こんな感じ

コードにすると以下

ORM

// Users entity
class UserEntity
{
   public UserId $id;
   public UserName $name;

   // なんかいい感じにGetterがある
}

// ORM
class UsersOrm
{
  // なんかいい感じにクエリ発行してくれるすごいやつ
  private orm $orm;

  public function getUser(UserId $id): UserEntity
  {
    $user_entity = $this->orm->selectQuery()->where('id', $id)->exec();
    return $user_entity;
  }

  public function getUserId(UserName $name): UserId
  {
    $user_entity = $orm->selectQuery()->where('name', $name)->exec();
    return $user_entity->getUserId();
  }
}

ORM使うクラス

// ORM使うやつ
class Hoge
{
  public function hoge()
  {
    orm $users_orm = new UsersOrm();
    UserName $name = 'tanaka';
    UserId $user_id = $users_orm->getUserId($name);

    UserId $id = 1;
    UserEntity $user = $users_orm->getUser($id);
    UserName $user_name = $user->getName();
  }
}

なんでこれやりたいか

今後DBに別のID(alias_idでも、office_idでもなんでもいい)が増えた場合に、全てが同じint型だと実装ミスが起きる可能性がある

int $user_id = 1;
int $office_id = 1;
// 本来$user_idを渡す必要があるが、同じintなので実行するまで気付けない。実行後も気付けない可能性がある(レコード取得できる可能性有)
$orm->getUser($office_id);

これが厳密な型にできたら、コンパイル時にエラーを検知できる

UserId $user_id = 1;
OfficeId $office_id = 1;
// UserId型を期待しているのにOfficeId型を渡しているのでコンパイルエラー
$orm->getUser($office_id);

そもそも設計上の問題があるとか、引数名でわかるだろ とかは当然あるけど、どうしても人間ミスがあるからこれを未然に防げるようにしたかった。

で、何をするか

elmで出来そう

なのでelmをやります(100日後にはelmをやっていたことを忘れるワニ)