iOS開発でClean Architectureを採用した際のイイ感じのディレクトリ構成とは


Clean Architectureを採用しているとファイル数が膨大になってしまうため、**イイ感じ**にグルーピングして管理したいですが、レイヤ単位で分けるか画面とそれ以外で分けるか悩むと思います。（悩みました🙋）

2,3の構成を試し、その中で一番**イイ感じ**に運用できた構成を紹介します。

その前によく見られているであろうリポジトリ※ のディレクトリ構成をパターン分けしてみました。
※「ios clean architecture」でググった際の結果とGitHub検索で出た上位結果


## ディレクトリ構成のパターン

上記でさらっと挙げたように大きく２つのパターンがあると思います。
「レイヤ単位で分けているパターン」と「画面とその他で分けているパターン」です。

ここでは参考に上記の２つのパターンに分けて構成をまとめます。

以下では基本的にフォルダ名のみ記載します。
フォルダ名のみだと把握しにくいと判断したものはファイル名も記載しています。
ファイル名が記載されてないファルダの直下は同役割のファイルが全て共存していると捉えてください。

マイノリティーな命名がされているものには隣に括弧で補足しています。
（とはいえマイノリティかマジョリティかは確証がありませんのでご容赦ください。）

### レイヤ単位（Data, Domain, Presentaion）で分けているパターン

- [まだMVC,MVP,MVVMで消耗してるの？ iOS Clean Architectureについて - Qiita](http://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc)
	- [GitHub - koutalou/iOS-CleanArchitecture](https://github.com/koutalou/iOS-CleanArchitecture)

- [iOS Clean Architectureで遊んでた話 – kage’s blog](https://www.kagemiku.com/blog/archives/442)
	- [GitHub - kagemiku/ios-clean-architecture-sample: iOS Clean Architecture Sample](https://github.com/kagemiku/ios-clean-architecture-sample)

```
├── Application
│   ├── Builder
│   └── Wireframe
├── Data
│   ├── DataStore
│   ├── Entity
│   └── Network
├── Domain
│   ├── Model
│   ├── Repository
│   └── UseCase
│		  └── Translater
├── Presentation
│   ├── Presenter
│   └── UI
│		  ├── Cell
│   	  ├── View
│   	  ├── ViewController
│   	  └── ViewModel
└── Util
```


- [iOS Clean Architecture - 騒音のない世界 BLOG](http://noiselessworld.hatenablog.jp/entry/ios-clean-architecture)
	- [GitHub - a-beco/iOS-CleanArchitecture-Example: Clean Architecture example for iOS.](https://github.com/a-beco/iOS-CleanArchitecture-Example)

```
├── Data
│   ├── DataType(Entity)
│   ├── Gateway(DataStore)
│   └── Repository
├── Domain
│   ├── Entity
│   ├── UseCase
│   └── ValueObject(Translator)
└── Presentation
	  ├── AAA
	  │   └── Adapter(Presenter)
	  ├── BBB
	  │   └── Adapter
	  └── ViewData(Model)
```


- [iOS CleanArchitectureを使ってみた感想 - hachinoBlog](http://hachinobu.hateblo.jp/entry/2016/10/13/222316)
	- [GitHub - hachinobu/CleanQiitaClient](https://github.com/hachinobu/CleanQiitaClient)

```
├── DataLayer
│   ├── DataStore
│   │   └── Request
│   ├── Entity
│   └── Repository
├── DomainLayer
│   ├── Model
│   ├── UseCase
│   └── ValueObject(Translator)
├── PresentationLayer
│   ├── Presenter
│   │   ├── AAA
│   │   └── BBB
│   ├── Routing
│   │   ├── AAA
│   │   └── BBB
│   ├── View
│   │   ├── AAA
│   │   └── BBB
│   └── ViewModel
│   	  ├── AAA
│   	  └── BBB
└── Utility
```



### 画面とその他で分けているパターン

- [RxSwift+CleanArchitectureで構成をキレイにしよう - Qiita](http://qiita.com/tamayuru/items/618ba3cf20be373f7455)
	- [GitHub - kirou/RxSwiftCleanArchitecture: RxSwift CleanArchitecture](https://github.com/kirou/RxSwiftCleanArchitecture)

```
├── Data 
│   ├── QiitaItem
│   │   ├── QiitaItemDataStore.swift
│   │   ├── QiitaItemEntity.swift
│   │   ├── QiitaItemRepository.swift
│   │   └── QiitaItemRequest.swift
│   └── Utility
│       ├── ApiClient.swift
│       └── ArrayTransform.swift
├── Environment 
│   ├── Const.swift
│   └── UIStoryboard+Util.swift
├── Scenes 
│   ├── List // リストページ
│   │   ├── ListConfigurator.swift
│   │   ├── Domain
│   │   │   ├── ListModel.swift
│   │   │   ├── ListTranslater.swift
│   │   │   └── ListUseCase.swift
│   │   └── Presentation
│   │       ├── Cells
│   │       │   └── ListTableViewCell.swift
│   │       ├── ListPresenter.swift
│   │       ├── ListRouter.swift
│   │       └── ListViewController.swift
│   └── Utility
│       └── Dependencies.swift
└── Storybords
    └── List.Storyboard
```


- [GitHub - sergdort/CleanArchitectureRxSwift: Example of Clean Architecture of iOS app using RxSwift](https://github.com/sergdort/CleanArchitectureRxSwift)
	- Networkパターンのみ

```
├── Domain  // I/F
│   ├── Entries
│   └── UseCases
├── Network // Implemented
│   ├── API
│   ├── Entries
│   ├── Network
│   └── UseCases
├── Scenes
│   └── AllPosts
│       ├── PostTableViewCell.swift
│       ├── PostsNavigator.swift(Wireframe)
│       ├── PostsViewController.swift
│       └── PostsViewModel.swift
└── Utility
```


- [Clean Swift iOS Architecture for Fixing Massive View Controller](http://clean-swift.com/clean-swift-ios-architecture/)
	- [GitHub - Clean-Swift/CleanStore: A sample iOS app built using the Clean Swift architecture. Clean Swift is Uncle Bob’s Clean Architecture applied to iOS and Mac projects. CleanStore demonstrates Clean Swift by implementing the create order use case described by in Uncle Bob’s talks.](https://github.com/Clean-Swift/CleanStore)


```
├── Models
│   ├── Order.swift
│   └── ManagedOrder.swift
├── Scenes
│   ├── CreateOrder
│   │   ├── CreateOrderInteractor.swift
│   │   ├── CreateOrderModels.swift
│   │   ├── CreateOrderPresenter.swift
│   │   ├── CreateOrderRouter.swift
│   │   ├── CreateOrderViewController.swift
│   │   └── CreateOrderWorker.swift
│   └── ListOrders
│       ├── ListOrderInteractor.swift
│       ├── ListOrderModels.swift
│       ├── ListOrderPresenter.swift
│       ├── ListOrderRouter.swift
│       ├── ListOrderViewController.swift
│       └── ListOrderWorker.swift
├── Services
│   ├── OrdersAPI.swift
│   └── OrdersMemStore.swift
└── Workers
    └── OrdersWorker.swift
```


## （個人的に）イイ感じだと思った構成

- 1.  [まだMVC,MVP,MVVMで消耗してるの？ iOS Clean Architectureについて - Qiita](http://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc) 
- 2. [RxSwift+CleanArchitectureで構成をキレイにしよう - Qiita](http://qiita.com/tamayuru/items/618ba3cf20be373f7455) 
- 3. 全て画面単位

上記の3つパターンを試してみましたが [RxSwift+CleanArchitectureで構成をキレイにしよう - Qiita](http://qiita.com/tamayuru/items/618ba3cf20be373f7455) さんの構成が一番イイ感じに運用できました。

まず、1つ目のパターンだとレイヤ毎に全てのフォルダが表示されるのでプロジェクトナビゲータが嵩張ります。
又、場合にもよりますがフォルダを開閉する際も3箇所を操作しないといけないので手間がかかりました。
表示範囲や操作回数はなるべく小さくしたいのでこのパターンは好ましくありませんでした。

逆に全てを画面単位でまとめると、横断して担うDataレイヤや各種オブジェクトが何処かに偏ってしまうので流石にこれも好ましくありませんでした。

ということで最終的にData層のみ切り分ける2の構成が一番無難に運用できています。

ちなみに自分は以下のように構成しています。（2を元に記載）

```
├── Application
│   └── AppDelegate.swift
├── Data 
│   └── QiitaItem
│       ├── QiitaItemDataStore.swift
│       ├── QiitaItemEntity.swift
│       ├── QiitaItemRepository.swift
│       └── QiitaItemRequest.swift
├── Scenes
│   └── List
│       ├── ListBuilder.swift
│       ├── ListWireframe.swift
│       ├── Domain
│       │   ├── ListModel.swift
│       │   ├── ListTranslater.swift
│       │   └── ListUseCase.swift
│       └── Presentation
│           ├── ListPresenter.swift
│           └── View
│               ├── Cell
│               │   ├── ListTableViewCell.swift
│               │   └── ListTableViewCell.xib
│               ├── ListViewController.swift
│               └── ListViewController.storyboard
└── Utility
```


## 最後に

Clean Architectureと括っても、+αでBuilderパターンやWireframe、Routing、一部にMVVMを採用していたり、プロジェクト（≒人）によって色々な実装方法や細分化があるので結局これといったベストプラクティスはないと思いました。

例えば、 [まだiOSアプリのArchitecture選定で消耗してるの？ - Qiita](http://qiita.com/koutalou/items/0f4b220662d2c95d7a92)の `一見複雑そうな機能を持つアプリでも、1画面1APIのようなI/F設計をしている場合は、サーバ側がロジック部を担保することになるのでClean ArchitectureのようなModel層の細分化はかなり冗長になると思います` の通り、1画面1API程度で採用した場合は画面毎に全てまとめたほうが余計なフォルダを開かなくて済みます。

Clean Architectureの構成に限らず、ディレクトリ構成による手間を減らすテクニックなどがあれば共有していただけると幸いです。


## 最後の最後に

プロジェクト内検索でファイルを開いたほうが早いことも多いのでXcodeのショートカットを覚えましょう。
**ショートカット**： `command + shift + o`

ちなみに開いた後に`command + shift + j` を押すとプロジェクトナビゲータが移動します。