妄想設計とは
妄想設計とは実装はしたことないが、こんな設計良さそう、という妄想の結果の設計である。
もちろん実用性などはない(キリ)。
$_POST の値
APIを書いていると$_POSTからデータを取ってくることがある。
$age = $_POST['age'];
だが、$_POSTに入っているデータはユーザーからの投稿データであり、基本的にデータは信用できない。
そのため、サニタイズやバリデーションが必要になる。
上記のageだったらサニタイズは
$age = intval($age);
if ($age === 0) {
// 0歳児はサポート外
throw new \Exception('invalid age value');
}
で可能だが、これをさっきのコードに書くと
$age = $_POST['age'];
$age = intval($age);
if ($age === 0) {
// 0歳児はサポート外
throw new \Exception('invalid age value');
}
となるわけだが、ageだけでなくweightも必要だとすると、
$age = $_POST['age'];
$age = intval($age);
if ($age === 0) {
throw new \Exception('invalid age value');
}
$weight = $_POST['age'];
$weight = intval($age);
if ($weight === 0) {
throw new \Exception('invalid weight value');
}
こんな感じでダラダラと書くことになってしまう。
はー、ダラダラするのは開発者だけでいいんですよ。コードはキリっとしてないとダメです。
APIごとにデータを検証するクラスを書く。
フレームワークなどはモデルというクラスがあって、そのモデルでデータを検証したりする。
フレームワークを使う場合は投稿データはモデルに突っ込んでデータ検証すればいい。
だが、なにも$_POSTのデータはすべてモデルに入れてデータベースに保存するわけではない。
保存しないデータもあるが、それももちろん検証と無害化はしないといけない。
よってAPIごとに$_POSTのデータを包むクラスを書くという妄想をする。
PostPersonData
class PostPersonData {
function __construct($ary) {
$this->age = $ary['age'];
$this->weight = $ary['weight'];
}
function sunitize() {
$this->age = intval($this->age);
$this->weight = intval($this->weight);
}
function validate() {
if ($this->age <= 0 || $this->age >= 200) {
throw new \Exception('invalid age');
}
if ($this->weight <= 0 || $this->weight >= 500) {
throw new \Exception('invalid weight');
}
}
}
こんなクラスをAPIのURLごとに用意する。
するとさきほどのコードは以下のように書くことができる。
$data = new PostPersonData($_POST);
$data->sunitize();
try {
$data->validate();
} catch (\Exception $e) {
die($e->getMessage());
}
うーん、エレガント!すき!だいしゅき!
フレームワークを使っていてモデルへデータを変換する場合は以下のようなメソッドも定義できるだろう。
$person = $data->to_model();
$person->save();
だが、データのバリデーションはモデルにも書くし、そうすると二度手間になる。
モデルにデータの検証を書いているのに、$_POSTのクラスにも検証方法を書かないといけないのかい! となる。たしかに~。
おわりに
今日の妄想はここまでとする。
妄想を現実にして実装する日は近い。かもしれない。