[Realm][感想文] DBに触ったことがないデザイナー兼iOSデベロッパーと、Realmを使って開発してみました

2015年の夏頃からとあるアプリ開発を、進めていて、Realmを使ってみた際の所感をつらつら書きます。

# 状況

- 自社アプリ開発
- 期限はだいたい2ヶ月
- 社内でのiOSアプリ開発は初
- 事前にCordovaを使ったハイブリッドアプリをテスト開発してみたが、細かいところに手が届かなかったり、Angularに慣れなかったりと不満が出たので、ネイティブ開発に移行 **（今思えばCordovaを追求しても良かったかもしれない....）**


## チームメンバー

- 意思決定者（社内にいる、コードは書かない）
- 配線からhtmlまでなんでもやる人 ←わたしです
  - 担当: バックエンド、クライアントのAPIレイヤー・DB・UI作成など諸々
- Apple好きなiOS開発好きなフロントエンドなデザイナー
  - 担当: デザイン全般、UIの細かい修正など

## Realmを導入した理由
デザイナーはクライアントでDBをつかったことがなく、Web開発でのバックエンドのことは担当外でしたが、それでもDBとのCRUD処理をバンバン書きながら開発してほしかった。

↓

より直感的に使えそうな気がしたRealmを導入
あとRealmBrowserがあるのも高評価でした

# 工夫したこと

## スケジュール調整と誰でもデータをいじれる環境作り

以下の様な感じで進めていきました。

|role|phase1|phase2|phase3|
|:-----------:|:------------:|:------------:|:------------:|
|Developer|スキーマ設計・実装（クライアントとサーバーを並行して）|wrapper?便利メソッドの実装、テストデータの用意|レビューしながら、メソッドやファイル構成などを修正の繰り返し|
|Designer|ワイヤー作成・提案・改善、UI設計|ViewControllerから実装|レビューしながら、フォームや一覧を実装|

### Phase1. まず最初にスキーマを組み立てる

データをみんなに簡単に扱ってもらうために、なによりもまずデータ構造をきっちり設計して実装しておきました。出来るまではUI設計を進めてもらって、実装に入るスケジュールを調整しました。


### Phase2. これを使って下さいというメソッドを用意

ViewControllerなどModelクラス以外からのRealmへの直接アクセスを禁止することを共有して、使うべきメソッドを予め用意しました。

よくありがちなことですが、viewにsqlを書いちゃう様なケースを避けたかったです。徹底していくうちに少しずつこういったケースは少なくなっていきました。

```swift:用意したメソッドの例
Hoge.all()
Hoge.filteredById()
Hoge.create()
Hoge.upsert()
Hoge.mine()
Hoge.not_this_day()
```

### Phase3. とにかくコードレビュー

データ周りに関してはとにかくレビューを繰り返しました。私自身もrealmを使ったのは初めてだったので、試行錯誤しながら進めました。みんなが心地よく使える様な環境を作ろうとファイル構成やメソッドをいじり続けました。

そんな感じで今もなお実装をすすめています。今ではデザイナーの方も自分からスキーマを書こうとするまでになりました！
Realmは簡単に使えるので、ゴリゴリのエンジニアでない人にとってとてもいい感じです。



# 悩んだこと

おもに0.96.0にアップデートしてから直面した問題です。トラブルというか悩んだことです。

## DoubleにOptionalを定義するときに一手間いる

```swift
class Hoge: Object {
    dynamic var double? = nil
    dynamic var Bool = false
```

↑のようにはいかず

```swift
class Hoge: Object {
    let double = RealmOptional<Double>(1.2)
    let bool = RealmOptional<Bool>(false)
}
```

↑こうする。

[ここに](https://realm.io/jp/news/realm-objc-swift-0.96.0/)書いてありました。が気付かずあれれとなっていました。

## tryしてもcatchするときどうしよう...

```swift
do {
  let realm = try Realm()
  realm.write { realm.add(myDog) }
}
catch {
  print("Error...")
}
```

↑の様に書いた際に、catchで何をしようか迷い続けました。場合にもよるでしょうが、try!を使って、エラーが出たらCrashさせておこうと決めました。あとから、Slackで以下のようなコメントを見つけ、安心しました。

<img width="566" alt="Screen Shot 2015-12-09 at 11.33.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/18705/0f7aa91e-b394-c088-aec6-0ac79072ce4b.png">


## Xcode7.1で realm-cocoa 0.96.0 をcarthageで入れようとしてもエラーが吐かれる

importしても↓のようなエラーがでしまいました。

```rb
error: module file was created by an older version of the compiler; rebuild 'RealmSwift' and try again
```

このバージョンはDynamic Frameworkを使ったインストールをして対応しました。

[StackOverflowのこの件](http://stackoverflow.com/questions/33311208/realm-with-swift-2-1-project-wont-build-when-importing-realmswift-module-file)とだいたい同じ内容だと思われるので、今では問題がなくなっている様ですが、まだ試していません。。。

## migrationがちょっとやっかい

モデル追加とかカラム名の変更とかなら簡単にすみますが、モデルの変更など大掛かりなものになるとmigrationファイルも汚れてきたり、処理が煩雑になってきてちょっと一歩踏み出せませんでした。サーバー側をRailsで作っているので、Railsのmigrationとくらべてしまうと物足りない気がしてしまいます。
なので、モデルオブジェクトの定義はカチッとするか、クライアントとサーバーのモデル構造の統一にこだわらない様にするかしています。
基となるDBはサーバー側において、クライアントの方はそのコピーという位置づけに考えたら、精神が安定しました。


# まとめ
DBに入門する前のデザイナーの方と、Realmを使ったiOS開発について、感想をつらつらと書きました。おそらくRealmを使ったからスムーズな開発が可能だったと思います。ある程度の下準備やフォローは必要でも、実装に問題なく使えるレベルに上げるまでの期間はかなり短かったです。

他にも、スレッドをまたいだときのことや、Android-iOS-Serverでのスキーマ統一やデータのやりとり、migrationでがんばったことなど、またいつか書きます。