GTDのiOSアプリを作りましょう！パート１

*Swiftでクリーンアーキテクチャーの仕組みとTDDの作り方の実験*

今回はGTDのアプリを作ります。パート１は基本のモデルエンティティまで作ります。

#### GTDについて

GTDは仕事の進め方の手法です。特に複数のプロジェクトを同時にやる程忙しい方にはオススメです。GTDについての情報はこちら:

[GTDのウイキペディア](https://ja.wikipedia.org/wiki/Getting_Things_Done)

[GTDの日本語版（アマゾン）](https://www.amazon.co.jp/仕事を成し遂げる技術―ストレスなく生産性を発揮する方法-デビッド・アレン/dp/4893613332)

#### TDDについて

TDDは英語で言うと「Test driven development」です。日本語だと「テスト駆動開発」です。コードを書く前にそのコードの結果を証明できるテストを書くことです。そうすると以下のメリットがあります：

* コードを変更するときに、他のところに影響があればテストが失敗するのですぐわかります。
* 随分後からコードを見ると、テストが説明書になります。コードを書いたときに何を考えてたかはわかりやすくなります。
* 守ってくれるテストがあれば、変更の影響の心配なくリファクタリングができます。

[TDDのウイキペディア](https://ja.wikipedia.org/wiki/テスト駆動開発)

#### TDDのやり方

簡単にいうと、TDDの作り方はこんな感じです：

1. 一つだけの失敗するテストを作る。
2. テストが成功するまで実装する。
3. 繰り返しを除く（リファクタリング）。
4. 1-3を繰り返す。

まずはアプリの機能が依存する条件から始めましょう。その条件を見て、先に一つずつ条件が満たされたかどうかを自動で確かめるテストを作ります。実装はまだ書いていないため、テストは失敗することを確認する。

#### アプリの条件：

ホーム画面では５つの項目があります：

* Inbox（未処理項目）
* Current Actions（現在行動可能項目）
* Projects（プロジェクト一覧）
* Waiting On（〇〇待ち項目）
* Someday / Maybe（いつか・かもしれない項目）

このアプリの基本のエンティティはItem（項目）です。つまりまだやっていない一つのやる事です。

もう一つの基本のエンティティはProject（プロジェクト）です。Projectは複数のやることがあって、具体的に決められた結果も設定されてることです。一つ以上のやることをつけることが可能ですが、できれば次の一つだけのやることを決めた方がオススメです。計画しないとうまくいかないときは複数のやることを入れるのがオススメです。

Inboxは新しく思い付いたやることを入れるところです。まだ処理する暇はないけど、忘れたくないためとりあえず入れるという感じです。

Current Actionsは処理されたいつでもやれる項目の一覧です。優先度は順番で変えられます。

Waiting On（〇〇待ち項目）は誰かもしくは何かが終わらないと行動不可能の状態であるやることです。

Someday / Maybe（いつか・かもしれない項目）は現在やることが無理とか、優先低いとか、次は何をすればいいか全くわからないことなどのプロジェクトややりたいことの一覧です。いつかやれる時期が来たり、やれる方法を思い付いたりことがあるときのために取っておきたいことです。

#### Xcodeの準備
Xcode 9とSwift 4でやりましょう。

新しいプロジェクトを作成

1. (`⌘` + `shift` + `N`)を打つ
2. `Single View App`を選択し、`Next`をクリックする
3. `Product Name`に「CleanGTD」を入力（好きなタイトルでいいですが、これ以後の説明でCleanGTDで説明します。）
4. `Language`に`Swift`を選択する
5. `Use Core Data`のチェックを外す
6. `Include Unit Tests`をチェックする
7. `Include UI Tests`をチェックする
8. `Next`をクリックする
9. 場所を設定する
10. Gitはオススメですが、不要です

掃除

1. `ViewController.swift`を削除
2. `CleanGTDTests.swift`を削除
3. (`⌘` + `shift` + `,`)を打つとスキーム編集画面が表示する
4. `Test`を選択して、`CleanGTDUITests`のチェックを外す

#### 失敗するテスト

今回のアプリのモデルエンティティの中心にあるItemから始めましょう。

まずは`Item`を作ることができるかどうかのテストです。
##### Testクラス作成

1. (`⌘` + `N`)で`Unit Test Case Class`を選択する
2. `Next`をクリックする
3. ファイル名のところに「ItemTests」を入力する
4. `Next`をクリックする
5. ターゲットは`CleanGTDTests`だけがチェックされてるのを確認する
6. `Create`をクリックする

ItemTests.swiftで以下のコードを入力してください。

```swift
import XCTest
@testable import CleanGTD

class ItemTests: XCTestCase {
    func testItemCanBeCreated() {
        let _ = Item()
        
    }
}
```
(`⌘` + `U`)（テストを実行する）を打つとテストターゲットがビルドできません。


テストが成功するため、空の`struct`を作るだけで最初のテストが成功できます。

`CleanGTD`のターゲットに`Item.swift`を作成して、以下を入力してください。


```swift
import Foundation

struct Item {}
```

Itemには三つの項目があります：

* text
* notes
* lastModifiedDate

何かを変更する際に先に失敗するテストを作るか作ってあるテストを変更するのです。

```swift
class ItemTests: XCTestCase {
    func testItemCanBeCreated() {
        let _ = Item(text:"", notes:[], lastModifiedDate:Date())
        
    }
}
```

また失敗しました。


さあ、直しましょう。notesはノートの一覧です。いつかノートに項目をつけることになりそうなので、`Note.swift`で```Note```エンティティも作りましょう。

まずは`Item`の変更です。

```swift
import Foundation

struct Item {
    let text:String
    let notes:[Note]
    let lastModifiedDate:Date
}
```

そうして`Note`の`struct`ですね。

```swift
import Foundation

struct Note {}
```

また(`⌘` + `U`)を打つと成功ができました。

`Note`の項目はとりあえず`text`だけでいいので追加しよう。

```swift
import XCTest
@testable import CleanGTD

class NoteTest: XCTestCase {
    func testNoteHasText() {
        _ = Note(text:"test note.")
    }
}
```

(`⌘` + `U`)、また失敗。

```swift
struct Note {
	text:String
}
```

`text`を追加すると(`⌘` + `U`)で成功。

Projectは五つの項目があります。

* title
* lastModifiedDate
* expectedOutcome
* items
* notes
	
`Project`作成テスト

```swift
import XCTest
@testable import CleanGTD

class ProjectTests: XCTestCase {
    func testProjectCreation() {
        let _ = Project(title:"Project Title", lastModifiedDate:Date(), expectedOutcome:"Expected outcome.", items:[Item], notes: [])
    }
}
```

(`⌘` + `U`)でビルドできない。よし。

とりあえずの`Project`実装

```swift
import Foundation

struct Project {
    let title:String
    let expectedOutcome:String
    let lastModifiedDate:Date
    let items:[Item]
    let notes:[Note]
}
```

(`⌘` + `U`)で成功。

これで基本のエンティティの全部ができました。

次回のパート２はホーム画面のビジネスロジックの作り方を解説します。