Observable.justとObservable.createのストリームを流す時の微妙な動作の違い

# はじめに
昔あったなーという話をちょっとずつ投稿してみるテスト。
あと、RxSwiftを触っている人は知ってることだと思いますし、そうではない人はあまり意識しない、微妙にニッチというか隙間な話だと思います。

# Observable.justとObservable.create
Observableを生成してストリームを流す時、Observable.justとかObservable.createを利用します。
例えば下記のように、subscribeすると「1」が流れるObservableがあります。

```

// 1. justに1を入れる
Observable.just(1)

// 2. 空の値をjustに流し、mapで1を流す
Observable.just().map {1}

// 3. 1を流すObservableを生成する
Observable.create { observer in
        observer.on(.next(1))
        observer.on(.completed)
        return Disposables.create()
    }
}

// subscribe時は、いずれも1が流れます
```

この3つの方法ですが、いずれもsubscribe時は1を流してくれます。
結果が同じなら気にしなくてもいいのでは？と思いますが、宣言部分とsubscribe部分を分けた上で、複数回subscribeをした時に少し挙動が違ってくることがあります。

# 複数回subscribeをした時の挙動の違い

例えば宣言を変数に格納し、数回subscribeをした場合に違いが出てきます。
下記にあるように、ランダムな数字を流すコードを実行をしてみるとわかるのですが、こんな違いが出てきます。

サンプル
https://github.com/kirou/RxSwiftQiita2

```
// 宣言
let testRand1 = rand1()
let testRand2 = rand2()
let testRand3 = rand3()

// testRand1のsubscribe 1回目
testRand1
    .subscribe(onNext: { dump($0) })
    .addDisposableTo(disposeBag)

// testRand1のsubscribe 2回目
testRand1
    .subscribe(onNext: { dump($0) })
    .addDisposableTo(disposeBag)

// testRand2のsubscribe 1回目
testRand2
    .subscribe(onNext: { dump($0) })
    .addDisposableTo(disposeBag)

// testRand2のsubscribe 2回目
testRand2
    .subscribe(onNext: { dump($0) })
    .addDisposableTo(disposeBag)

// testRand3のsubscribe 1回目
testRand3
    .subscribe(onNext: { dump($0) })
    .addDisposableTo(disposeBag)

// testRand3のsubscribe 2回目
testRand3
    .subscribe(onNext: { dump($0) })
    .addDisposableTo(disposeBag)

/*
 * Observable外で、arc4random_uniformを実行する
 */
func rand1() -> Observable<UInt32> {
    
    let rand = arc4random_uniform(10)
    return Observable.just(rand)
}

/*
 * 空の値がmapに伝わり、map内でarc4random_uniformを実行し、値を流す
 */
func rand2() -> Observable<UInt32> {
    
    return Observable.just()
        .map {　arc4random_uniform(10)　}
}

/*
 * 空の値がmapに伝わり、map内でarc4random_uniformを実行し値を流す
 */
func rand3() -> Observable<UInt32> {
    
    return Observable.create { observer in
        observer.on(.next(arc4random_uniform(10)))
        observer.on(.completed)
        return Disposables.create()
    }
}
```

* ストリームに流れた値 (実際に実行した時に落ちた値)

| 回数 |testRand1|testRand2|testRand3|
|:--- |:---|:---|:---|
| 1回目 | 4 | 5 | 3 |
| 2回目 | 4 | 7 | 2 |

実行してもらうとわかるのですが、testRand1は何回実行しても同じ値が流れ、testRand2と3は毎回変わった値が流れます。

この違いは何かと言うと、宣言時の動作に違いがあるからです。

testRand1では、乱数の生成処理がObservable外にあるため、宣言時の段階で乱数を生成されます。それをObservable.justに格納しています。
subscribe時はその格納された値が流れるため、結果が同じです。
(もちろん、再度宣言をし直したら値は変わります。あと、subscribe時はObservable内の要素を観測するため、subscribeごとに乱数生成の処理をすることはありません)

testRand2と3は、Observableで囲われているため、宣言の段階で処理が動くことはありません。subscribeされた時に実行されるので、subscribeされるたびに乱数が生成されます。 
(これも下記のよう、shareReplay(1)をすれば何度も乱数生成の処理が動くことはありません。Hot変換ですね)

```

// shareReplayなどのHot変換がある場合は
// testRand1のように、何度subscribeしても初回に乱数を生成した時の値が流れてくる
func rand4() -> Observable<UInt32> {
    return Observable.create { observer in            
        observer.on(.next(arc4random_uniform(10)))
        observer.on(.completed)
        return Disposables.create()
    }
    .shareReplay(1)
}
```
こうしてみると、testRand2とtestRand3はほぼ同じですが、testRand2はjust()を挟んでいるので無駄処理かなあという感じです。


# まとめ

まとめるとこんな感じになります。

| 工数 |testRand1|testRand2|testRand3|
|:--- |:---|:---|:---|
| 宣言時 | Observable外にあるarc4random_uniformを実行する | 何もしない | 何もしない |
| subscribe | Observable内の処理が実行される(宣言時に実行した値が流れるだけ) | Observable内の処理が実行される | Observable内の処理が実行される |
| 複数回実行した時 | Observable内の処理が実行される (宣言時に実行した値が流れるだけ)  | Observable内の処理が実行される | Observable内の処理が実行される |

今年の春あたりはこのあたりふわふわしていたので、Observable外の処理が宣言時に実行されてしまい、動作がおかしいことがありました。 
このことに気づいてからは、ああ、だからみんなObservable.createで囲ってるんだなと納得した記憶があります。
(ちゃんとRxを理解していない&そもそもalamofireのrequest().requestしなければよかったという話でもありますが。。)