まだiOS Clean Architecture で消耗してるの？ 爆速開発ツールを作ったのでご紹介

## 前置き
#### Clean Architecture について
Architecuture の一つで詳細は下記の記事に載っています。
[The Clean Architecture](https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html)

それを`iOS`開発に適用させるために参考になる記事を挙げます。
[まだMVC,MVP,MVVMで消耗してるの？ iOS Clean Architectureについて](http://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc)
[iOS CleanArchitectureを使ってみた感想](http://hachinobu.hateblo.jp/entry/2016/10/13/222316)
[これからクリーンアーキテクチャによるiOSアプリ開発をしようとしている人にオススメの4つの資料](http://dev.classmethod.jp/smartphone/going-to-create-a-ios-app-with-clean-architecture/)

## 本題
#### Clean Architecutre のデメリット
`Clean Architecture` は各レイヤーごとに役割と責任を分離するために必然的にファイル数・コード量が多くなってしまうのが欠点として挙げられます。
コード量が多くなることで記述する時間・ファイルを作成する時間がその分割かれます。
その問題を解決するライブラリ[Kuri](https://github.com/bannzai/Kuri)を開発したのでご紹介します。

## Kuri
[Kuri](https://github.com/bannzai/Kuri)はiOS Clean Architecture用に開発したCLIツールです。
[Kuri](https://github.com/bannzai/Kuri)はコマンド一発で各レイヤーのコードを自動で生成してくれてかつ`Xcode Project`にディレクトリ、ファイルを`import`してくれます。
さらに**Kuri** には柔軟にジェネレートするディレクトリやプロジェクト、その内容を変更できる仕組みを設けています。
この記事ではその方法を説明していきます。

### 導入
まず導入の説明をします。
**Kuri**はgithub上に公開されています 
そして一番新しくリリースされたバージョンのzipをダウンロードしてください。
https://github.com/bannzai/Kuri/releases

![image](https://qiita-image-store.s3.amazonaws.com/0/84459/c2e9fe7e-ba31-63da-3031-5ab0c9a96d72.png)

あとは展開したファイルをPATHが通っている場所に移動しましょう。
これで*kuri*コマンドをターミナル等のCLIで使う準備は終わりです。

### setup
**Kuri**の機能を使うために準備するものがあります。
`Kuri.yml`
`KuriTemplate` ディレクトリ
この二つがコードジェネレートするときに必要です。
これらを用意するコマンドが**Kuri**には備わっています。

実際にプロジェクトがあるディレクトリに作業ディレクトリを移してください。
```
$ cd YourProject
$ ls 
YourProject YourProject.xcodeproj YourProjectTests YourProjectUITests
```
環境によって異なりますが上記のように`ls`をしたら`YourProject.xcodeproj`があるディレクトリです。
作業ディレクトリを移動したら`kuri setup`とコマンドを実行してください。

```
$ kuri setup
created Kuri.yml.
created template for Entity
created template for DataStore
created template for Repository
created template for UseCase
created template for Translator
created template for Model
created template for Presenter
created template for View
created template for Wireframe
created template for Builder
Successfully setup!

$ ls 
Kuri.yml KuriTemplate, YourProject YourProject.xcodeproj YourProjectTests YourProjectUITests

```

以上で`Kuri.yml`と`KuriTemplate`の作成が完了しました。

### generate 
さて本機能である`generate`コマンドについて見ていきます。
とりあえず実行してみましょう。

```
$ kuri generate Kuri
created: ./YourProject/Kuri/Entity/KuriEntity.swift
created: ./YourProject/Kuri/Entity/KuriEntityImpl.swift
created: ./YourProject/Kuri/DataStore/KuriDataStore.swift
created: ./YourProject/Kuri/DataStore/KuriDataStoreImpl.swift
created: ./YourProject/Kuri/Repository/KuriRepository.swift
created: ./YourProject/Kuri/Repository/KuriRepositoryImpl.swift
created: ./YourProject/Kuri/UseCase/KuriUseCase.swift
created: ./YourProject/Kuri/UseCase/KuriUseCaseImpl.swift
created: ./YourProject/Kuri/Translator/KuriTranslator.swift
created: ./YourProject/Kuri/Translator/KuriTranslatorImpl.swift
created: ./YourProject/Kuri/Model/KuriModel.swift
created: ./YourProject/Kuri/Model/KuriModelImpl.swift
created: ./YourProject/Kuri/Presenter/KuriPresenter.swift
created: ./YourProject/Kuri/Presenter/KuriPresenterImpl.swift
created: ./YourProject/Kuri/View/KuriViewController.swift
created: ./YourProject/Kuri/View/KuriViewControllerImpl.swift
created: ./YourProject/Kuri/Wireframe/KuriWireframe.swift
created: ./YourProject/Kuri/Wireframe/KuriWireframeImpl.swift
created: ./YourProject/Kuri/Builder/KuriBuilder.swift
created: ./YourProject/Kuri/Builder/KuriBuilderImpl.swift
write in project: YourProject.xcodeproj
```

なにやらいっぱい作られたみたいですね。
実際にXcodeを開いてファイルインスペクターを見ると`Kuri`ディレクトリができてその下にファイルができていると思います。

<img height="300px" src="https://qiita-image-store.s3.amazonaws.com/0/84459/dc1a6abd-4601-2ef9-e591-ed7ae1a82b0d.png" />

`kuri generate XXX`で`XXX`をprefixとしたファイルが一気に`generate`され、
えさらにXcodeプロジェクトに`import`されていることが確認できたと思います。

これだけのファイルをコマンド一発で用意できるなんて便利ですね！

### generate 応用
ここでは**Kuri**に用意された**generate**コマンドの柔軟性について少し触れたいと思います。
まず前提として`setup`コマンドで用意した二つのものの解説をします。
**Kuri.yml**は`generate`するための設定が記述されています。
具体的にはどのプロジェクトのどのターゲットをどのパスにファイルを作成するかを決めるための情報が記載されています。
**KuriTemplate**にはファイルを`generate`するためのテンプレートがSwiftで書かれています。
今回はテンプレートの方に着目しましょう。
例えば`KuriTemplate/Implement/Repository/Repository.swift`の定義はこうなっています。

```swift
//
//  __REPOSITORY__Impl.swift
//  Kuri
//
//  Created by __USERNAME__ on __DATE__.
//  Copyright © 2016年 __USERNAME__. All rights reserved.
//

struct __REPOSITORY__Impl: __REPOSITORY__ {
    private let dataStore: __DATASTORE__

    init(
        dataStore: __DATASTORE__
        ) {
        self.dataStore = dataStore
    }

    func fetch() throws -> __ENTITY__ {
        return try dataStore.fetch()
    }
}
```

これと先ほど`generate`された`KuriDemo/Kuri/Repository/KuriRepositoryImpl.swift`と比較してみましょう。

```swift
//
//  KuriRepositoryImpl.swift
//  Kuri
//
//  Created by kingkong999yhirose on 2016/12/25.
//  Copyright © 2016年 kingkong999yhirose. All rights reserved.
//

struct KuriRepositoryImpl: KuriRepository {
    private let dataStore: KuriDataStore

    init(
        dataStore: KuriDataStore
        ) {
        self.dataStore = dataStore
    }

    func fetch() throws -> KuriEntity {
        return try dataStore.fetch()
    }
}
```

形が似ていますね。  
`KuriRepositoryImpl.swift`は`KuriTemplate/Implement/Repository/Repository.swift`を基にして(テンプレートとして)作られています。
つまり、テンプレートを編集すれば次回以降の`kuri generate XXX`コマンドから編集した内容が反映されます。

テンプレートをみて気づくと思うのですが、
`__REPOSITORY__`, `__DATASTORE__`
と言う文字列があります。
これは見比べてもらうとわかると思うのですが、
`kuri generate XXX`と実行するとそれぞれ
`XXXRepository`, `XXXDataStore`へと置きかわる変数の役割を果たしています。
以上のことを知っておけばテンプレート編集できます。
この機能を使用して自分のプロジェクトにあったテンプレを作成することが可能です。


## 締め
以上で**Kuri**の紹介を終わります。

より詳細なことはgithub上の`Documents`フォルダやREADEMEに記載されているのでそちらをごらんください
https://github.com/bannzai/Kuri/
https://github.com/bannzai/Kuri/tree/master/Documents

`generate`に関してもいくつかオプションが用意されているのでこちらを使うことで開発がよりスムーズになると思います。

まだ機能追加していくつもりですが、[issue](https://github.com/bannzai/Kuri/issues)
公開して間もないのでPRやissueや要望・質問をお待ちしております＾＾


## なぜKuri?
**Kuri**の名前の由来は
1. *Clean Architecture* → *クリーンアーキテクチャー* → Kuriーンアーキテクチャー
2. クリ(Kuri)スマスに公開したライブラリだから
と言うしょうもない親父ギャグです

\\(^o^)/