Dartからきた
BLoCの話
Roppongi.js #2
2018/5/29
自己紹介
- 西田雅博
 - 2018/2 ~ merpay
	
- go, React
 
 - ~ 2018/1 Bizreach
	
- Scala, Angular4, React
 
 

BLoC? 🤔
BLoC
Business Logic Component
※ Component は React, Vueでいうアレじゃなくて純粋に部品とかって意味
Google AdWordsチームが発表
- DartConf 2018
 - Google I/O '18
 


BLoC
- もともとの動機
	
- Web (Angular Dart)とMobile (Flutter)でビジネスロジックのコードを共有したい
 
 - 言語・プラットフォームを問わないビジネスロジック(状態管理)設計パターン
 - 今日はコードの共有というより状態管理パターンとして話します
 - React, RxJSを使ったサンプルアプリ
 
BLoC概念図

BLoCざっくり
- ビジネスロジックをコンポーネントツリーと別の場所に置く
 - BLoCの外部へのインターフェースはStream(Observable)だけ
 
BLoCざっくり
- RxJSで言うと
 - Observable.subscribe
 - Observer.next
 

BLoCコード例
class TodoBloc {
  private _todos = new BehaviorSubject<Todo[]>([]);
  public get todos = this._todos.asObservable();
  private _addTodo = new Subject<string>();
  public get addTodo(): Observer<string> {
    return _addTodo;
  }
  
  constructor() {
    this._addTodo.subscribe(text => {
      const current = this._todos.getValue();
      this._todo.next([...current, { text, id: newId() }]);
    })
  }
}const todoBloc = new TodoBloc();
class Todo extends React.Component {
  this.state = {
    todos: []
  };
  componentDidMount() {
    todoBloc.todos.subscribe(todos => {
      this.setState({ todos });
    });
  }
  render() {
    return (
      <>
        <TodoInput onAddTodo={todoBloc.addTodo.next} />
        <TodoList todos={this.state.todos} />
      </>
    )
  }
}BLoCコード例
const todoBloc = new TodoBloc();
class Todo extends React.Component {
  this.state = {
    todos: []
  };
  componentDidMount() {
    todoBloc.todos.subscribe(todos => {
      this.setState({ todos });
    });
  }
  render() {
    return (
      <>
        <TodoInput onAddTodo={todoBloc.addTodo.next} />
        <TodoList todos={this.state.todos} />
      </>
    )
  }
}- todoBlocのインスタンスを作成
 - todoBloc.todosをsubscribeして、自分のstateに設定する
 - Todo追加はaddTodo.next
 
class TodoBloc {
  private _todos = new BehaviorSubject<Todo[]>([]);
  public get todos = this._todos.asObservable();
  private _addTodo = new Subject<string>();
  public get addTodo(): Observer<string> {
    return _addTodo;
  }
  
  constructor() {
    this._addTodo.subscribe(text => {
      const current = this._todos.getValue();
      this._todo.next([...current, { text, id: newId() }]);
    })
  }
}- 実際は
	
- Contextなどを使ってComponentに与える
 - Observableのsubscribeはreact公式のcreate-subscriptionパッケージが使えるかも
 
 
BLoCコード例
const todoBloc = new TodoBloc();
class Todo extends React.Component {
  this.state = {
    todos: []
  };
  componentDidMount() {
    todoBloc.todos.subscribe(todos => {
      this.setState({ todos });
    });
  }
  render() {
    return (
      <>
        <TodoInput onAddTodo={todoBloc.addTodo.next} />
        <TodoList todos={this.state.todos} />
      </>
    )
  }
}- 公開しているのは2つのStream
	
- todos: Observable<Todo[]>
 - addTodo: Observer<string>
 
 - todosをsubscribeしてTodoのリストを受け取ってもらう
 - 新しいTodoが追加されたときにaddTodo.nextを実行してもらう
 
class TodoBloc {
  private _todos = new BehaviorSubject<Todo[]>([]);
  public get todos = this._todos.asObservable();
  private _addTodo = new Subject<string>();
  public get addTodo(): Observer<string> {
    return _addTodo;
  }
  
  constructor() {
    this._addTodo.subscribe(text => {
      const current = this._todos.getValue();
      this._todo.next([...current, { text, id: newId() }]);
    })
  }
}BLoCにすると
- ビジネスロジック(状態)とのIFはすべてStream(Observable)
 - BLoCからのデータの取得はObservable#subscribe
 - BLoCへのデータの送信はObserver
 
BLoCにすると
- BLoC側はin/outのStreamを管理するだけ
 - ComponentはStreamからデータを受け取る・Streamにデータを追加するだけ
	
- Flux/Reduxと同じ
 
 - 関心を分離できる
 - Angularやってるとこういうふうになる説
 
個人的なBLoCの
いいところ
- BLoCは単なるクラスなのでいろいろできる
 - 簡単にMockと切り替えられる
 - constructor injection
	
- 他のBLoCを受け取る
 - 言語によって出力を切り替える
 - Local Storageを使って初期状態を取得
 
 
- Stream(Observable)を使っている
 - RxJSの豊富なオペレータを使える
	
- 他のBLoCのStreamと自分のStreamを混ぜる
 - ユーザーの入力を500ms debounceさせてAPIにクエリを投げた検索結果のStream
 
 
個人的なBLoCの
いいところ
Reduxと比べて
- 個人的にReduxに持っていた不満点を解消してくれる
	
- combineReducerで結合するreducer間でアレコレできない
 - combineReducerと同じ粒度のselector書くとか二度手間じゃない…?
 - Action, reducerの冗長感
 - TypeScriptと相性がイマイチ
 - などなど・・・
 
 
BLoC Cons
- 設計パターンなのでReduxみたいにライブラリやれば道が決まるわけではない
 - Stream(Observable)慣れが必要
 - 今のとこGoogleさんしかやってない
 - 言語、FWにStreamの仕組みが必要
 - など
 
まとめ
- Dart/Flutterでビジネスロジックのコードを共有するBLoCという設計パターン
 - 言語・FWを問わず適用できる
 - Webフロントエンドでも使える
 - In/OutをStreamにするのがキモ
 
おわり
DartからきたBLoCの話
By adwd
DartからきたBLoCの話
- 8,222