Angularのシンプルな状態管理ライブラリ Akita について

## はじめに

この記事は、[Angular Advent Calendar 2018](https://qiita.com/advent-calendar/2018/angular)の7日目の記事です。

ここではngrxと比べればまだ認知度が低い、Akitaという状態管理ライブラリをご紹介します。

## Akitaって？

![assets%2F-LDIcOEJiLYk8yWho34E%2F-LHClIF5qciDQfD0m-qQ%2F-LHClK11ZuAPlZtWGAJl%2FA.png](https://qiita-image-store.s3.amazonaws.com/0/19111/3fc56af7-0647-96f9-eb83-cabf60d9cfa5.png)


[Introduction - State Management Tailored-Made for JS Applications](https://netbasal.gitbook.io/akita/)

> Akita is a state management pattern, built on top of RxJS, which takes the idea of multiple data stores from Flux and the immutable updates from Redux, along with the concept of streaming data, to create the Observable Data Store model.

秋田犬のロゴがかわいくて癒やされますね。

AkitaはFluxから複数のデータストア、Reduxからimmutable updates, streaming dataのコンセプトを取り入れた、RxJSのObservableに最適化された状態管理パターンだと謳っています。

## Akitaの特徴
* Store, Query, Serviceの役割が明確に分かれている
    * Storeを直接触ることはできなくて、
    * 読み込みはQueryを通じて行う
    * 書き込みはServiceを通じて行う
    * コマンド・クエリ分離原則に則っていて治安がよい
    * ファイルの置き場所・ディレクトリ構成に悩まないのが楽
* 気の利いたAPIがデフォルトで実装されている
    * Storeの`createOrReplace`メソッド
    * Queryの`isEmpty` `selectAll`メソッド
    * などなど自分でいちから実装することがあまりない
    * ファイル・コードが冗長で管理が大変というReduxにありがちな問題を回避できる
* 関数型ではなくオブジェクト指向のデザイン設計
    * Query, Serviceなどはクラスで実装されている
    * 型安全で治安がよい
* CLIが用意されている
    * https://github.com/datorama/akita/tree/master/cli
    * ファイル作成が簡単でよい

公式ドキュメントに記されているアーキテクチャ図も以下に載せておきます。

![assets%2F-LDIcOEJiLYk8yWho34E%2F-LEFMbbD5BNkHxecdUde%2F-LEFMe1nMjDF-0kBdGY5%2Fakita-arc.jpg](https://qiita-image-store.s3.amazonaws.com/0/19111/1d6ea12f-4b94-4f3f-e8ee-ebbbaf4dc09c.jpeg)

## コード例

CLIを試すと、以下のようなコードが生成されます。
コードを見ると、Akitaの設計がより理解しやすいかと思います。（ここでは`todo`という名前を仮で指定しました）

### todo.model.ts
```ts
import { ID } from '@datorama/akita';

export interface Todo {
  id: ID;
}

export function createTodo(params: Partial<Todo>) {
  return {

  } as Todo;
}
```

### todo.query.ts
```ts
import { Injectable } from '@angular/core';
import { QueryEntity } from '@datorama/akita';
import { TodoStore, TodoState } from './todo.store';
import { Todo } from './todo.model';

@Injectable({ providedIn: 'root' })
export class TodoQuery extends QueryEntity<TodoState, Todo> {

  constructor(protected store: TodoStore) {
    super(store);
  }

}
```

### todo.service.ts
```ts
import { Injectable } from '@angular/core';
import { ID } from '@datorama/akita';
import { TodoStore } from './todo.store';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class TodoService {

  constructor(private todoStore: TodoStore,
              private http: HttpClient) {
  }

  get() {
    // this.http.get().subscribe((entities: ServerResponse) => {
      // this.todoStore.set(entities);
    // });
  }

  add() {
    // this.http.post().subscribe((entity: ServerResponse) => {
      // this.todoStore.add(entity);
    // });
  }

}
```

### todo.store.ts
```ts
import { Injectable } from '@angular/core';
import { EntityState, EntityStore, StoreConfig } from '@datorama/akita';
import { Todo } from './todo.model';

export interface TodoState extends EntityState<Todo> {}

@Injectable({ providedIn: 'root' })
@StoreConfig({ name: 'todo' })
export class TodoStore extends EntityStore<TodoState, Todo> {

  constructor() {
    super();
  }

}
```

## まとめ

すごく簡単にAkitaについて紹介しました。

個人的にはngrx(Redux)の冗長さに疲弊していたので、このAkitaのシンプルさはとても気に入ってます。できることや自由度は減ってるけど、「そうそうこれくらいでいいんだよ」感があってとてもいいですね。

Akitaの公式ドキュメント・ブログが充実しているので、興味をもった方はぜひチェックしてみてください :eyes:

* https://netbasal.gitbook.io/akita/
* https://netbasal.gitbook.io/akita/entity-store/blog-posts