Swiftではじめる日本語プログラミング

# はじめに
プログラミング初学者にとって初見のコードは難解です。しかも大抵は英語（簡易的な）で書かれておりさらに難易度は高くなっています。書くときもまた英語なのでキャメルケース？スネークケース？動詞？形容詞？3人称単数のSは必要だっけ？など悩むことも多いはずです。

そんなあなたに朗報です！！変数名やメソッド名は日本語で書くことができます。そう、swiftならね。

今回は初学者にもわかりやすいように、できる限り日本語でアプリを作成してみました。

# つくったもの
つくったものはここ

* [通常版](https://github.com/adventam10/JapaneseSample/tree/en)
* [日本語版](https://github.com/adventam10/JapaneseSample/tree/master)

以下の機能を持ったアプリをつくりました。

* 通信してQiita記事を一覧表示する
* 記事タップすると外部ブラウザで記事を表示する

こういうやつ

![jp](https://user-images.githubusercontent.com/34936885/69006995-1cfa1400-097b-11ea-9832-e1dd743cf8ec.gif)

[簡単な画面仕様](https://github.com/adventam10/JapaneseSample/blob/master/画面仕様.md)

単体テストも書こうかと思いましたが、脱線しそうだったので今回はやめておきました:bow:

# 環境
* Xcode 11.0
* swift 5.1
* 最小ターゲット iOS 13.0

# ソース解説
## ソース
とりあえずソース見ないとわからないと思うのでViewControllerのソースを載せておきます。

ぜひswift初学者に見ていただきたいです。なんとなく何をしてるかわかるのではないでしょうか？

```swift
final class 記事一覧画面: 画面 {

    @IBOutlet private weak var プログレス: 画面表示部品!
    @IBOutlet private weak var インジケーター: インジケーター! {
        didSet {
            インジケーター.停止中は非表示にする = 正誤(true)
        }
    }
    @IBOutlet private weak var 検索バー: 検索バー! {
        didSet {
            検索バー.検索バー操作通知を受信するやつ = self
            検索バー.キャンセルボタンを表示する = 正誤(true)
            検索バー.テキスト（仮） = 文字列("記事検索ワード")
        }
    }
    @IBOutlet private weak var テーブル: テーブル! {
        didSet {
            テーブル.テーブルに表示するデータを生成するやつ = self
            テーブル.テーブル操作通知を受信するやつ = self
        }
    }

    private let 記事一覧用モデル = 記事一覧モデル()
    
    override func 画面表示完了した() {
        super.画面表示完了した()
        記事一覧用モデル.記事一覧モデル通知 = self
        プログレスを非表示にする()
        データなしラベルを表示する()
    }
    
    private func プログレスを表示する() {
        インジケーター.アニメーションを起動する()
        プログレス.非表示にする = 正誤(false)
    }
    
    private func プログレスを非表示にする() {
        インジケーター.アニメーションを停止する()
        プログレス.非表示にする = 正誤(true)
    }
    
    private func データなしラベルを表示する() {
        テーブル.非表示にする = 正誤(true)
    }
    
    private func データなしラベルを非表示にする() {
        テーブル.非表示にする = 正誤(false)
    }
    
    private func アラートを表示する(タイトル: 文字列, メッセージ: 文字列, ボタンタイトル: 文字列 = 文字列("OK"), ボタン押下時の処理: (() -> Void)? = nil) {
        let 警告 = アラート.アラートを作成する(タイトル: タイトル, メッセージ: メッセージ, スタイル: .アラート)
        let アクション = アラートアクション.アクションを作成する(タイトル: ボタンタイトル, スタイル: .標準, ボタン押下時の処理: ボタン押下時の処理)
        警告.アクションを追加する(アクション)
        画面を表示する(警告, アニメーションさせる: 正誤(true))
    }
}

extension 記事一覧画面: テーブルに表示するデータ {
    func テーブル(_ テーブル: テーブル, セクション内行数 セクション: 整数) -> 整数 {
        return 記事一覧用モデル.記事一覧.要素数
    }
    
    func テーブル(_ テーブル: テーブル, セル セクションと行数: セクションと行数) -> テーブルセル {
        let セル = テーブル.再利用セルを作成する(識別子: 文字列("記事"), セクションと行数: セクションと行数) as! 記事テーブルセル
        セル.タイトルラベル.テキスト = 記事一覧用モデル.記事のタイトル(行数: セクションと行数.行数)
        return セル
    }
}

extension 記事一覧画面: テーブル操作 {
    func テーブル(_ テーブル: テーブル, セルを選択した セクションと行数: セクションと行数) {
        if let url = 記事一覧用モデル.記事のURL(行数: セクションと行数.行数) {
            アプリケーション.共通のやつ.URLを開く(url)
        }
    }
}

extension 記事一覧画面: 検索バー操作 {
    func 検索バーの検索ボタンをクリックした(_ 検索バー: 検索バー) {
        検索バー.キーボードを閉じる()
        プログレスを表示する()
        記事一覧用モデル.検索する(検索ワード: 検索バー.テキスト, 完了時の処理: { [weak self] (検索結果) in
            メインスレッドで処理する {
                self?.プログレスを非表示にする()
                switch 検索結果 {
                case .成功した(let 検索ワード, let 記事一覧):
                    self?.記事一覧用モデル.検索ワード = 検索ワード
                    self?.記事一覧用モデル.記事一覧 = 記事一覧
                case .失敗した(let エラー):
                    if case let .通信環境(通信エラー) = エラー {
                        ログを表示する(文字列("通信環境エラー： ") + 通信エラー.エラー内容)
                    }
                    self?.アラートを表示する(タイトル: 文字列("取得失敗"), メッセージ: エラー.エラー内容!, ボタン押下時の処理: {
                        self?.検索バー.テキスト = self?.記事一覧用モデル.検索ワード
                    })
                }
            }
        })
    }
    
    func 検索バーのキャンセルボタンをクリックした(_ 検索バー: 検索バー) {
        検索バー.キーボードを閉じる()
        検索バー.テキスト = 記事一覧用モデル.検索ワード
    }
}

extension 記事一覧画面: 記事一覧モデル通知 {
    func モデル(_ モデル: 記事一覧モデル, 記事一覧を更新した 記事一覧: 配列<記事>) {
        if 記事一覧用モデル.記事一覧がある == 正誤(true) {
            データなしラベルを非表示にする()
        } else {
            データなしラベルを表示する()
        }
        テーブル.スクロール位置を調整する(位置(.zero), アニメーションさせる: 正誤(false))
        テーブル.再描画する()
    }
}
```

120行ちょっとです。`class`, `func`といった予約語以外は全部日本語にできたのではないかと思います。

## つくり方
まず既存クラス、構造体を日本語でラッピングしていきます。今回は全部やるのは大変なので、使う部分だけ丁寧にラッピングしていきました。`UILabel`はこんな感じです。

```swift
class ラベル: UILabel, 画面表示部品の共通機能 {

    var テキスト: 文字列? {
        set {
            text = newValue?.値
        }
        get {
            return 文字列(text)
        }
    }
}

protocol 画面表示部品の共通機能: AnyObject {
}

extension 画面表示部品の共通機能 where Self: UIView {
    var 非表示にする: 正誤 {
        set {
            isHidden = newValue.値
        }
        get {
            return 正誤(isHidden)
        }
    }
}
```

`String`とかの`struct`はこんな感じです。

```swift
protocol ValueWrapper {
    associatedtype 値の型
    var 値: 値の型 { get set}
    init?(_ 値: 値の型?)
    init(_ 値: 値の型)
    init()
}

extension ValueWrapper {
    init(_ 値: 値の型) {
        self.init()
        self.値 = 値
    }
    
    init?(_ 値: 値の型?) {
        guard let 値 = 値 else {
            return nil
        }
        self.init()
        self.値 = 値
    }
}

protocol EquatableValueWrapper: ValueWrapper, Equatable {
}

struct 文字列: EquatableValueWrapper {
    typealias 値の型 = String
    var 値: String = ""
    init() {
    }
    
    var 空である: 正誤 {
        return 正誤(値.isEmpty)
    }
}

func + (lhs: 文字列, rhs: 文字列) -> 文字列 {
    return 文字列(lhs.値 + rhs.値)
}
```

`値`プロパティを持たせて頑張ったんですがもっといい方法ないだろうか...

# 日本語プログラミングの利点
日本語で書く意味ってなんやねん？と思う人もいるかと思うのでここでいくつか日本語で書く利点について書いておきます。

1. ネーミングに迷わない  
例えばボタンを表示するフラグの変数名を考える場合、通常なら`isShownButton`?, `isButtonShown`?など語順に迷うかもしれませんが、日本語であれば`ボタンを表示するフラグ`とそのまま書けるので迷う必要がありません。
2. メソッドや変数の意味がすぐ伝わる  
例えば`var elapsed: Timeinterval?`という変数があったとすると「えらぷすど？？」となるかも知れません。`var 経過時間: Timeinterval?`とすればだれにでもすぐに伝わるでしょう。
3. 初学者であってもある程度何をやっているか読める  
例えばキーボードを閉じる処理で`searchBar.resignFirstResponder()`は一見何をしてるかわかりませんが、`検索バー.キーボードを閉じる()`とすれば一目瞭然です。
4. 仕事の囲い込みができる  
全てコードを日本語で書けばそのコードを保守するのは日本語話者にしか難しくなるので、海外に仕事が流れていくのを回避することができます。

実際のコーディングでも日本語で命名する方がいい場合もあるようです。

[もっと日本語でSwiftプログラミングを](https://qiita.com/codelynx/items/9af94d8f9f24cee339e2)

これはなるほどと思いました。

# さいごに
利点はつくってから無理やり色々考えましたが、新人研修とかで使うと面白いんじゃないかなと思いました。（とりあえず日本語でつくってみたかっただけです:sunglasses:）

もっとこうした方がイケてるとかネーミングがまだあまいとか気になるところがあればコメントか[github](https://github.com/adventam10/JapaneseSample)で伝えていただけると幸いです。

(プログラミング必修化されるらしいしUIKitを完全に日本語化すると教材として面白そうとか思ったり...)