システムを1から作るときに考えていること

## はじめに

はじめまして、iruca3 と申します。
VR法人HIKKYでインフラ・バックエンド開発部に所属しております。
この記事は [HIKKYアドベントカレンダー](https://qiita.com/advent-calendar/2024/hikky) 14日目の記事となります。

この記事は、同僚のエンジニアさんや友人のエンジニアさん向けの記事です。
私がシステムを1から作るときに、どういう順番で何を考えてシステムを設計・実装しているのかを書き連ねてみようと思います。

似たような記事やもっと良質な記事は世の中にたくさんあると思いますので、それらも参照するとよいかと思います。



## 1. システムを作るときに一番最初に考えること

### どんな人が、どういう目的で、使う？

よく、ペルソナを考えてユーザストーリーを作って、みたいな流れがあると思います。私の場合はまず、自分自身をペルソナとして、あるいは自分自身を役者として考えます。例えば、ペルソナが「海外のアニメを見たいけど日本では配信されていなくて困っている人」とするなら、私自身がその人を演じる役者だったら、と考えます。そうすると、「こういうことを考えているかも」とか、「こういう行動をとっているかも」という予想がたくさん湧いてくるので、それを温めておきます。

### どんな風に使われる？

次に、システムが「既に存在するもの」として、頭の中で(想像上で)使ってみます。その想像が、すべて現実味のあるユーザストーリーだと思っています。自分はこの想像の過程をめちゃくちゃ大事だと考えています。なので、うまく想像できない箇所があれば、それはそもそも要件が詰まっていないと言えますし、想像内容に違和感があるなら、それは技術的に実現が難しいことかもしれません。そういうポイントを必ず解消してから次の工程に進みます。もし解消しないと、想像ですらうまくいかないので、現実で進めても到底うまくいくとは思えません。

### 技術スタックに目星をつける

いろんなユーザストーリーを思い浮かべる中で、「この部分にはあの技術が使えそう」みたいな目星を立てます。想像に限らずリアルでも、いろんなシステムを観察していると、「これってどうやって実現しているんだろう」と思う機能があると思います。それを調べたりして、「こんな技術があるのか！」と関心することも多いです。あるいは、勉強会などで仕入れた技術知識などもそうですね。そういう技術ストックを活用して、「これって実現可能なの？」と疑問に思う箇所も含めて、「実現できそう」という目星をつけていきます。

逆に実現できそうになさそうなものは、似たようなものを実現している事例がないかを調べて調査したりします。

## 2. 次に、システムを設計してみる

### どんなデータを使う？

さて、この時点でシステムがどんな感じのものか、ほぼくっきりはっきりしているはずです。画面の細かいデザインなどはもちろんまだですが (そもそもその辺はデザイナの範疇とも言えますが)、少なくとも必要な「機能」は出揃っているはずです。そうすると、どんなデータを扱っているのかも必然的に分かるはずです。例えば「最初にシステムにログインする」というストーリーがあれば、ログインIDやパスワードを扱いそうだなとか。「見たいアニメを検索する」というストーリーがあれば、アニメのデータを管理する必要があるな、とか。

私はいつも、ここからデータベース設計をやっています。上記なら、「ユーザテーブル」とか「アニメテーブル」とかが出てきて、ユーザテーブルはユーザIDとパスワード(ハッシュ値)のフィールドを持っていて、みたいな。この辺は少し経験値が必要なところかもしれませんが、テーブル構成は大体パターンが決まっているので、そのパターンである程度は作れると思います。よくあるフィールドを少し例示します。

- `id`: 一意に識別するID。通し番号。
- `created_at`: 作成日時
- `updated_at`: 更新日時
- `deleted_at`: 削除日時。論理削除する場合に使うケースが多いです。
- `status`: 状態を表す。文字列や数値で管理され、例えば `disabled` (無効) とか `active` (有効) とか、そのモデルの状態を管理する場合に便利。ステートマシン図も作っておくと分かりやすい。

### ストーリーを更に具体的にする

今の状態だと、ストーリーは頭の中の想像だけなので、このまま作るには(小さいシステムならいいですが大きいシステムとかだと)ちょっと大変です。なので、ストーリーをシーケンス図で表したり、画面遷移図にしたりします。あるいは「誰が」「何をする」が分かれば文字でもいいんですが、図の方が見やすいです。この情報を元に、 **API仕様** と **ページ仕様** を決めます。

例えばユーザがログインするというストーリーだと、「ユーザがログインIDとパスワードを入力してログインボタンを押すと、サーバで入力内容をチェックされ、認証できればログイン後の画面を表示し、認証できなければエラーページを表示する」と具体化します。これは、「ユーザが」「アカウント情報を入力すると」「バックエンドが」「認証する」という、「誰が」「何をする」が2つセットになっているストーリーだと分かります。

これを全ストーリー分、やります。システムの規模によっては、これだけで相当な量になると思いますが、余すことなく全部やります。そうしないとシステムは動きません。

### フロントとサーバで役割分担

これで、「誰が」「何をする」が具体化されます。この「何をする」という部分は、人がやることもあれば、システムがやることもあります。システムがやる場合、「フロント」がやるのか「サーバ(バックエンド)」がやるのかを決めてやります。「フロント」がやる場合、システムによりますが、Webページだったり、アプリだったりが行います。「サーバ(バックエンド)」だった場合は、サーバに乗っけるサービスが行います。

フロントでやるのかサーバでやるのかはシステムの制約等にもよりますが、大体は以下の内容で判断できると思います。

- 基本はフロントでやる (サーバは利用者全員の影響を受けるため、できるだけ負荷は減らしたいから)
- ただし、データが改ざんされると困る場合はサーバでやる (不正防止)
- 秘密情報などを扱い、フロントにそれが漏れると困る場合もサーバでやる

### API仕様設計

サーバでやることが決まったものについては、APIの設計を行います。APIの設計は、いろんなAPI仕様書を見ていれば分かると思うのでここでは詳細は割愛しますが、自分は基本的にRESTfulな設計を心がけています。また、エラーがあるときは200 OKでエラー内容を含める、みたいな形は避け、ちゃんとエラー内容に応じたステータスコードでエラー内容を返すようにします。

## 3. 実装する

ここまできたら、お手軽実装の場合は後はほぼほぼ作業です。データモデルのスキーマを書いたりテーブルを作ったりして、ルーティングを書いて、APIの機能を実装して、あるいはテストを実装して、動作確認もしたりして、という流れ作業になります。Ruby on Railsとかならこれでもいいんですが、例えばClean Architectureに沿って実装しようとか思ったりすると、ちゃんと各層を分けて設計・実装する必要があると思います。今回の記事の範疇を超えるのでこの辺は割愛しますが、クリーンなコードを書きましょう。


長々と書きましたが、大体考えていることは、こんなところです。


## ところで

1番の工程 (どんな人が、どういう目的で、使う？) をやっていないエンジニア、いませんか？
あるいは、1番の工程が甘いエンジニア、いませんか？
この工程をちゃんとやらないと、**めちゃくちゃ使いにくいシステム**ができたり、**誰が使うのか分からないシステム**ができたりします。だって、目的が不明瞭なシステムが、どうして目的を持った人を導けるでしょうか。


## まとめ

コードを書いたり設計資料を作るのだけがエンジニアの仕事じゃないです。個人的には、1番の工程にあるような、「使う人のことを考える」部分が一番大事な仕事じゃないかなと思っています。もっというと、「限られた予算と時間の中で、使う人の本当の目的を引き出し、それを最大限叶えてあげられるシステムを考える」のが仕事上ではCoolなエンジニアなんじゃないでしょうか。私はそういうエンジニアになりたい。
(もちろん、運用のことも考えて。システムは、作って終わりではないので。)


## 余談

実はSECCON CTFの作問とか昔やってたので、CTFに関する記事を書こうかなって思ったりもしたんですが、今回の記事の内容を伝えたい人が身近にいたので、CTFの記事はお蔵入りしました。代わりに、CTFの問題を置いておきました。よかったら解いてみてね。(下記の画像ファイルが問題ファイルです。)

![ctf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81207/0aee3faa-8521-6d0c-63b0-5a256fca2d17.png)

- フラッグは `FLAG{英数字文字列}` の形になっています。
- フラッグは 2 つ隠されています。
- writeup やネタバレは2025年までは書かないでください。:pray: