はじめに

おばんです、今朝はWWDC17のジャケットを着てオレンジジュースを飲んで、西海岸を思い出してイキっていた田中です。

このエントリーはtry! Swift Tokyo 2018のセッション 「関心の分離と単純化のためのSwiftコードの最適化」(Javier Soto) のまとめになります。

講演内容

公式サイトより引用。

関心の分離は、コードが再利用されないときには時期尚早な最適化とみなされることがよくありますが、我々がコードが何をしているのかを理解することに対しては大きく影響します。Swiftにおけるこの実例を紹介します。

このセッションの要約

コードは書くよりも読む時間の方が長いので、可読性を高める必要がある

Swiftはコーディングの原則(Coding Principle)との親和性が高い

いくつかの具体例をコードとともに紹介します 紹介する例はTwitterのアプリをイメージするとわかりやすい



講演資料

バックグラウンド

大規模なプロジェクトで働いている

コードレビューは大事 コードレビューが好きです 同僚のコードを読むと学べる



コーディングの原則を意識する

コーディングの原則 Simplicity / 単純 Conciseness / 簡潔 Clarity / 明確 これはSwiftのコーディング理念とも通じるものがある

単純化が大事

関心の分離

コードは書かれることよりも読まれることの方が多い 自分自身でコードを書くときも、人に聞かれたときに簡潔に答えられるようにすることが大切

How から Whatを切り離す その実装が「どう行われているか」でなく「なんなのか」を示す Swiftに適用したときに拡張しやすい作りにする



Example1

文字の数が範囲内かどうかというのを確認するコード

Before

sendButton.isEnabled = true となる条件がぱっと見で理解しづらい

After

characterCountUsingBackendPolicy という変数に切り出して、 utf16.count に意味をもたせた

という変数に切り出して、 に意味をもたせた let characterLimit = 140

sendButton.isEnabled = characters <= characterLimit この書き方によって、文字数がリミット内かどうかでsendButtonを押せるかどうかが決まることがわかりやすくなった



Example2

リプライ一覧を取得するコード

Before

成功時の結果でブロックしているユーザーのリプライは出さないようにしている

ネストも深く、とても複雑で読みにくい

After

filteringBlockedContent という変数をprotocol extensionで定義することによって、複雑さをなくせた

Example3

NSLayoutAnchorを設定しているコード

Before

とても冗長

After

変数に代入するような感覚でanchorを操作できるようにオペレータを実装した

より馴染みのある書き方/読み方になった

Example4

activeなconstraintに応じてviewのhiddenを管理するコード

headerVisible の条件に制約の状態を利用している

Example5

セルに代入するテキストを場合分けするコード

Before

あらかじめ決められたindexに対して入れる値を場合分けすることは、意味のまとまりがない

冗長である。セルのタイプが増えたら、その分長くなる？

After

Rowsをenumで定義して、cellのindexPath.rowに対応させる形でtitleをenumに保持させることでより意図が分割され、明確になった

tableView:cellForRowAt 内をスッキリさせられる

Example6

UserDefaultsに保持した初回起動フラグによって、処理を分岐させるコード

Before

「チュートリアルを見たことがあるかどうか」という意味だが、UserDefaultsにアクセスしてデータを取って......というのを直接記述しているため可読性が落ちる

After

hasSeenTutorialという変数を用意して、「チュートリアルを見たことがあるかどうか」をそのまま表現することができるようになった

Example7

iOS 11.0以上の場合、safeAreaLayoutGuideに対して制約を加えるコード

Before

After

iOS11とiOS10でsafeareaに制約をつけるかどうかという話

safeAreaLayoutGuide

Example8

押しやすい、最低限のサイズのボタンを作っているコード

Before

44 * 44というコードからすぐに意図が伝わる形になっていないので、コードで補足している

After

MinimumHitAreaButton という命名でクラス化することでコメントに頼らず意図を伝えられる

という命名でクラス化することでコメントに頼らず意図を伝えられる 「押せる」ということを func hitTest で担保している。(44 * 44以下のサイズのボタンは「押せない」)

Example9

ボタンの表示非表示に応じて addSubview と removeFromSuperview を制御しているコード

Before

UI要素ごとにこの設定を行うととても大変

After

UIStackViewの、中のUI要素の isHidden がfalseだった場合は非表示にする性質を利用して記述を簡易化している

Example10

ProfileViewController user detailsを持つViewControllerではなく どのuserIDのuser detailsを持つかという構成に変更した

また、load状態などはenumでState管理することにした

これにより、画面の状態管理が読みやすくなった

Summary

ローカルスコープの可読性の最適化には価値がある

DRY

Swift enums are awesome

田中の感想「Swiftらしく読みやすいコードはカッコいい！」

可読性や責務の分離については 『リーダブルコード』 が有名です。簡潔にまとめられた良書として長く、多くの人々に読まれています。

より良い表現の方法は言語によって変わります。Swiftであればenumを活用したり、iOSの領域を含めればUserDefaultsやUIまわりでよく行う実装方法などはいくつかあります。 この発表は明日から使える有用なTipsと、発想を与えてくれました。正直かっこいい。

より良いコードをかくために、手始めに、この発表で紹介された10の方法と考え方を念頭においてコードを改善していこうと思いました。