SwiftでRealmを使う時のTips(1) アクセサとエンティティ編

#目次

[SwiftでRealmを使う時のTips まえがき](http://qiita.com/nakau1/items/a591d9cc34e5b575ceb5)
[SwiftでRealmを使う時のTips(1) アクセサとエンティティ編](http://qiita.com/nakau1/items/21ed81e7f38c104f760e)
[SwiftでRealmを使う時のTips(2) 生成とオートインクリメント編](http://qiita.com/nakau1/items/0323807abed795a43393)
[SwiftでRealmを使う時のTips(3) NSPredicate編](http://qiita.com/nakau1/items/40865299dacc50d71604)

# アクセサ(DAO)とエンティティ(DTO)

データを扱うときは `DAO`と `DTO` という設計概念がありますね
厳密に正しいかどうかわかりませんが
ざっくりいうと「データを管理するヤツ」 と 「データそのもの」 は分離させる設計概念です

まぁ、健全なみなさんはちゃんとやってますよね・・・
これがたまにごっちゃにして書いている人がいるので
たまにソースを読んでてこちらもごっちゃになります

Realm自体には、こいつらを分離させるためのクラス体系はありません
なので、最初に自分で分離させておくことは少なくとも大事だと感じました

```NBRealmEntity.swift
public class NBRealmEntity: RealmSwift.Object {
    
    public static let IDKey       = "id"
    public static let CreatedKey  = "created"
    public static let ModifiedKey = "modified"
    
    public dynamic var id : Int64 = 0 // = NBRealmEntity.IDKey
    
    public dynamic var created = NSDate() // = NBRealmEntity.CreatedKey
    
    public dynamic var modified = NSDate() // = NBRealmEntity.ModifiedKey
    
    public override static func primaryKey() -> String? {
        return NBRealmEntity.IDKey
    }
}
```
```NBRealmAccessor.swift
import UIKit
import RealmSwift

public class NBRealmAccessor<T: NBRealmEntity> {
    
    public typealias Entity = T
    
    public var realm: Realm { return try! Realm() }
    
    public init() {}
}
```

実装は上記のとおり2種類のクラスを用意します

ちなみにプレフィックスの`NB`は自分の屋号からとってきたもので特に意味はありません
(外してもらってもいいです)

##エンティティ

データそのものを指すクラスは `"エンティティ"` という名前にしています
他にも「オブジェクト」や「VO」「データ」「レコード」といった名前で
呼ぶ人もおられると思いますが、
ここではそのように名づけました


`ID`を `Int64`型にしていますが
よほどのことがない限りは`Int`でもリソースの枯渇はないと思います
なので `Int64`型 にこだわる必要はまったくないですが
ここではそのままにしています

##アクセサ
データを管理するクラスは `"アクセサ"` という名前にしています

基底クラスでジェネリクスをとらせてますので
こいつは「あるエンティティ専用のアクセサ」として使うことができます

こんな感じですね

```swift

class UserEntity: NBRealmEntity {
    // something
}

class UserAccessor: NBRealmAccessor<UserEntity> {
    // something
}
```

`UserAccessor` は `UserEntity` に関するお仕事しかしないと
これで決めてやったも当然です
責務が狭まったこのクラスは、これであまりソースが散らかることがなくなります (本当かな?)


で、このアクセサは、狭義のモデルクラスになります
オブジェクトの死滅が早いコントローラに、モデルを所持させてはよくないです
ゆえに、呼び出しは下記のように実装すべきですねぇ

```swift
// こちらはダメな例
class ViewController: UIViewController {
    public override func viewDidLoad() {
        super.viewDidLoad()
        
        let userAccessor = UserAccessor()
        userAccessor.hoge()
    }
}
```
```swift
// こういう感じにしておきたい
class Model {
    static let userAccessor = UserAccessor()
}

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        Model.userAccessor.hoge()
    }
}
```

##両者の関係性

ここでエンティティとアクセサの両者を使う時のルールを確認します

- **エンティティは必ずアクセサによって作られる**

```swift
let user = UserEntity()
```
みたいなことができるのは唯一アクセサクラスだけというのを徹底します
たとえば、コントローラやビューに書いていては行けませんし、
モデルクラスであっても無関係な処理をしてるクラスでは絶対にインスタンス化をしません

これで 「`UserEntity` をうんぬんかんぬんしてるってことは・・・、`UserAccessor` だ!」と
メンテナンスの時に安心できますよね

- **エンティティをデータベースに保存するのは必ずアクセサ**

エンティティはただの変数の器。データの固まり
こいつ自身が単独で恒久的データをいじってしまうのはあまりよくないです

なかなか悩ませるのがRealmのオシャレな(?)機能である
リアルタイムアップデートというやつです
オブジェクトの値を変えると、KVOによってそのままデータベースも書き変わるというもの
まぁ便利なんだけど、逆に不便な場面が色々と出てきました

そこは場面によって使い分けも必要かと思いますが、
原則論としては、データベースの書き換えはアクセサ経由でないとやらせない
というルールをしっかりしておけば
`CRUD`が散らかることが減るかなぁと個人的には思っております