TDD
GTD
クリーンアーキテクチャ
swift4
Xcode9

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

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

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

GTDについて

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

GTDのウイキペディア

GTDの日本語版(アマゾン)

TDDについて

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

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

TDDのウイキペディア

TDDのやり方

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

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

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

アプリの条件:

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

  • 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. LanguageSwiftを選択する
  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で以下のコードを入力してください。

import XCTest
@testable import CleanGTD

class ItemTests: XCTestCase {
    func testItemCanBeCreated() {
        let _ = Item()

    }
}

( + U)(テストを実行する)を打つとテストターゲットがビルドできません。

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

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

import Foundation

struct Item {}

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

  • text
  • notes
  • lastModifiedDate

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

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

    }
}

また失敗しました。

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

まずはItemの変更です。

import Foundation

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

そうしてNotestructですね。

import Foundation

struct Note {}

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

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

import XCTest
@testable import CleanGTD

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

( + U)、また失敗。

struct Note {
    text:String
}

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

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

  • title
  • lastModifiedDate
  • expectedOutcome
  • items
  • notes

Project作成テスト

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実装

import Foundation

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

( + U)で成功。

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

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