PHPやTypeScriptを書くサーバーサイドエンジニアがCodable(Vapor)で感動した話

Swift アドベントカレンダー2020 10日目の記事になります。

9日目の記事はこちら→ [SVProgressHUDのimageにtintColorを反映させないようにする](https://qiita.com/repepe2en/items/72181e2e99a17f2f10b8)



ApexやらVやらにうつつを抜かして全然技術的な知見が溜まってないので、感想文です(; ;)



## まとめ

チームのLT会で発表した資料があります。  

https://speakerdeck.com/sunyryr/server-side-swift-codable  

技術的な部分はほぼこのスライドままで、すごいから使ってみようぜ！って内容になります。



## 本文

私はサーバーサイドエンジニアで、主にPHP(Laravel)やTypeScript(Express)を書いています。

最近はGraphQLの時もありますが、基本的にJSONの受け渡しをしていました。

そこで出てくるこんなコード

```typescript
async function handler(req, res, next) {
  const limit = req.body.limit  // string|qs.ParsedQs|string[]|qs.ParsedQs[]
  const type = req.body.type    // string|qs.ParsedQs|string[]|qs.ParsedQs[]
  ...
}
```

```php
class HogeController extends Controller
{
    public function register(HogeRequest $request)
    {
        $account = $request->input('login_id'); // mixed
        $id = $request->input('device_id');     // mixed
        ...
    }
}
```

型がついてないので、TypeScriptなら `as Type` 、PHPなら `/* var Type VarName */` などを使い、強制的に型をつけることが必要になってきます。([注](https://qiita.com/bitrinjani/items/d60bdac10e5ced126d1a#typescriptで型指定すると))


```typescript
async function handler(req, res, next) {
  const limit = req.body.limit as string  // string
  const type: string = req.body.type      // string
}
```

```php
class HogeController extends Controller
{
    public function register(HogeRequest $request)
    {
        /** @var string $account */
        $account = $request->input('login_id'); // string
        /** @var string $id */
        $id = $request->input('device_id');     // string
    }
}
```

型チェックなしでこんなをコード書くのはかなりやばいですが、大抵のプロジェクトではバリデーションを取り入れているので、強制的に型をつけたコードでもはほとんど問題はないです。パラメータが増えるとちょっとめんどくさいですけどね。
自分も、型ないけどまぁ付ければ良いかってくらいの認識でした。Codableを知るまでは。



SwiftのフレームワークVaporで書くとこうなります

```swift
app.get("sample") { (req) -> void in
    let sample = try req.content.decode(Sample.self) // <- これ
    print(sample.id)   // string
    print(sample.name) // string
}
```

2行目の時点で `sample` はSample型のオブジェクトになっているので、補完も出るし型がついています。
これだけでJSONのパースをし、後述するバリデーションも簡単に導入できるし、何より言語の標準機能でできるってところに感動しました。



この機能はVaporでは[Contentとして紹介されています](https://docs.vapor.codes/4.0/content/)が中身としては[Codable](https://developer.apple.com/documentation/swift/codable) を利用しています。
すごいのでたくさん記事が上がっています。
[Swift4 Codableがすごすぎた件](https://qiita.com/UJIPOID/items/2c436a80f1167f7bcac0)
[【Swift】Codableについて備忘録](https://qiita.com/s_emoto/items/deda5abcb0adc2217e86)
[Codableについて色々まとめた[Swift4.x]](https://qiita.com/_ha1f/items/bf1aad5ea3e927f59f9d)



TSやPHPでもJSONパーサー・バリデーターを追加し、上記のように処理できます。しかしコストの問題なのかやっているプロジェクトはあまりありませんでした。外部のライブラリが必要になるので、会社標準などにしないと案件ごとに差異が出てめんどくさいですしやってないんでしょう。
しかし、CodableはSwift標準なので、VaporだけでなくPerfectなどどのフレームワークでも基本的に同じように使えます。学習コストも下がる！すごい！



バリデーションの導入も簡単です。

```swift
app.get("sample") { (req) -> void in
    try Sample.validate(content: req) // <- これ
    let sample = try req.content.decode(Sample.self)
}

extension Sample: Validatable {
    static func validations(_ validations: inout Validations) {
        validations.add("email", as: String.self, is: .email); // <- 追加していく
    }
}
```

パースに使うオブジェクトにバリデーションを追加できるので、一箇所にまとめて見やすくもできます。
また、Vaporのバリデーションはすべてのバリデーションチェックをしてくれるのも便利です。



## 終わりに

ServerSideSwiftはまだ実際の案件では選ばれない選択肢ですが、型は一回使ったら戻れない魅力を持ってると思うのでどんどん布教して案件でも使えるようにしていこうと思ってます。

そのためにも趣味でどんどんキャッチアップして **ServerSideSwiftを布教するシリーズ** をもっと増やしていきます



アドベントカレンダー、こんな感想文でお茶を濁してしまってすまない〜〜〜〜〜〜〜〜ってなってます。Apexはダイヤ3の闇に飲まれてしまっているので、今度はこっちを精進するぞ。