Page 1
iOS Anti Patterns & Refactoring
@kazu0620
Page 2
自己紹介
https://github.com/kazu0620
坂本 和大( @kazu0620 ) Sansan株式会社 Eight事業部所属
過去に個人で開発したアプリ - 秘密のアルバム(40万DL!) - にゃんこ(15万DL!)
Page 4
Anti Pattern• 問題に対する、不適切な解決策を分類したもの
• 今日はiOSの開発でよくある10のBad Partsを分類してご紹介します。
Page 5
Example No.1
UITableViewCellを継承したクラスの初期化処理です。
Exampleは、Objective-Cというイケてる言語で書かれています。
前提
Page 6
Example No.1
Anti Patternがいくつあるか考えてみましょう。(20秒)
Page 7
Anti Pattern 1
無意味な変数名の省略
Page 8
何が問題なのか?
• 一時変数ならまだ良いが、インスタンス変数や寿命が長い変数ならば前後の文脈から意味を推測する必要が出てくる。
• そもそも、省略するメリットは現在の開発環境ではほぼない。
Page 9
Cocoa向けコーディングライン (by Apple)
• 「使って構わない略語や頭文字」も記述してくれている。
Page 11
Anti Pattern 2
マジックナンバー
Page 12
何が問題なのか?
• 実装を読まないと何を意味するのかが理解できない。
• IDEで補完することもできない。
• 誤って別の数値を指定しても気付きづらい
Page 13
Refactoring
• 定数やEnumを利用して定義しましょう。
• 放置せず見つけたときに変更するべし。
Page 15
Anti Pattern 3
コードでViewをゴリゴリ書く
Page 16
何が問題なのか?
• 増え続ける多様なデバイスへの対応へのコスト
• ビルドしないとその座標が意図通りか確認できない
• 今時のAutoLayoutは結構優秀
Page 17
Refactoring• Storyboadに移行する。慣れてみると
Storyboad+AutoLayoutの方が大体の場合楽でした。
• 経験上、動的に表示を変更するという要件でも、frameをゴリゴリ操作するよりも最小限のConstraintをIBOutletで接続して必要な制約だけ変更する方が楽。
• しかし明らかに割りに合わない時は、仕様上の大きな変更など、replaceできる機を待つのもアリ
Page 19
Anti Pattern 4
過剰な責務
Page 20
• 何者にでもなることができるスゴイCell
何が問題なのか?
Page 21
• DetailCellは、状況に応じて何でも表示している
Page 22
• どうしてもコードの見通しが悪くなる(永遠と続く
case文やif分岐)
• 新しい振る舞いを追加するとき、変更が必要な箇所が散らばる
• 変更時にデグレが発生するリスクが高くなる。というか実際デグレる。
何が問題なのか?
Page 23
Refactoring
• 振る舞いごとにClassに切り分けられないか検討する
Page 25
Anti Pattern 5
責務が限定的でないクラス名
Page 26
• 抽象的すぎる名前
• 何を責務としているのか見てもわからない
• 本来意図した責務以外の処理を実装されるリスクもある(さっきの過剰な責務の話)
何が問題なのか?
Page 27
Refactoring
• 責務を限定した名前にリネームする。
• CardDeleteCellなど
• リネームしてビルドを通せば良い
• リスクなく簡単に修正できる
Page 28
僕がこのコードから見つけた Anti Patternは5つでした!
Page 29
俺はもっとたくさん見つけたぞ! って方は懇親会で教えてください!
Page 30
Example No.2
どこがAnti Patternなのか考えてみましょう。(3秒)
Page 31
Example No.2
どこがAnti Patternなのか考えてみましょう。(3秒)
Page 33
Anti Pattern 6
Fat View Controller
Page 36
何が問題なのか?
• 規模が小さいうちは良いが、Fatになるほどにメンテナンスや機能追加の難易度が上がる
• Modelが存在しない(or薄い)ので、状態の管理や監視の実装がどうしても複雑かつ見通しが悪くなってしまう(Model = NSDictionaryなど)
Page 37
Refactoring
「Objective-C プログラミングの概念」 より
• ModelとViewを仲介する処理
• LifeCycleの管理
以外の処理は別クラスへの切り出しを検討すべき
Page 38
Refactoring
Modelを切り出す
• NSDictionaryで情報 / 状態を持つコードはメンテナンスがツラい
• Controllerからビジネスロジックを剥がすことが出来る
• 複数のViewControllerで共通のModelを利用できる
Page 39
Refactoring
Viewを切り出す
• 割とシンプルなViewならStoryBoadでコード無しで作れる
• 必要なUIViewを継承したCustom Viewを作る
• 演出のためのアニメーション等複雑な処理をViewControllerから剥がすことが出来る
Page 40
Refactoring
その他のリファクタリング
• TableViewやCollectionViewはDataSourceDeleagteを別クラスに切り分けできないか検討する
• チュートリアル / ガイダンスの状態管理などはそれのみを責務としたクラスなどに分けることを検討する
• 複数のModelに対して複雑なデータ操作をしている場合などは、Serviceクラスに切り分けできないか検討する
Page 41
今回紹介したクラスは、フィード表示という複雑な処理を追加実装しましたが…..
Page 42
リファクタリングした結果、コード量は逆に500行程度にまで減りました。
Page 43
その他 よく見るiOSの Anti Pattern のご紹介
Page 44
Anti Pattern 7Fat App Delegate
Page 46
• AppDelegateの責務 = アプリ全体のライフサイクルを管理すること
• 本来はそれ以外の処理があるべきではない。が、AppDelegateをGodクラスとして使ってしまう場合がある。
Page 47
Refactoring
• それぞれの処理を、その責務を持ったクラスに委譲できないか検討する(Logging、APNSなど)
• NSNotificationCenterを利用し、ViewControllerでアプリのライフサイクルイベントを監視する
• 初期起動 -> 画面遷移を行うことを責務としたクラスを作る(Router,
Dispatcherクラス)
Page 48
Anti Pattern 8Fat Storyboad
Page 49
何が問題なのか?• コンフリクトする。
Page 50
Refactoring
• 文脈単位にStoryboadを切り分けることを検討する
• StoryBoard Reference を利用してみる
Page 51
Anti Pattern 9
不適切なイベント通知
Page 52
iOSのイベント通知方法
• Delegate
• KVO
• Notification
• Blokcs
Page 53
Anti Pattern
• とにかく何でもKVO / Notificationで通知する
• 関係が遠いクラスへのイベントをdelegateで通知する
Page 54
何が問題なのか?• 適切な方法で通知が実装されていないと、どのイベントがどこで発火して、誰が監視しているのかの見通しが悪くなる
• ので、メンテナンスするのが難しいコードになる
Page 55
Refactoring• 通知元:通知先が1:1の関係の場合はDelegateを利用したほうがわかりやすい(Ex. ViewControllerとViewなど)
• しかし、離れてる場合は、Delegateがクラス間でリレーされてしまい、見通しが悪くなりがち
• 通知元:通知先が1:Manyの関係の場合はNotificationを利用したほうがわかりやすい(Ex. 複数のControllerにModelが状態変化を伝える時など)
Page 56
Anti Pattern 10
クソコードとか文句言いながら放置する
Page 57
• 放置すれば状況は必ず悪くなる
• 苦労して悪しきコードを理解したとしても、後任者はまたコードを解読するところから始めることに。
• とはいえ、程度問題。リスクなくリネームだけで解決するなら気づいたときに対応すべき。
何が問題なのか?
Page 58
The Boy Scout Rule
• ボーイスカウトのルール「来た時よりも美しく
• checkoutしたときより美しくしてpushしよう!
Page 60
Copyright © Sansan, Inc. All rights reserved.
0
Sansanは一緒に新しい価値を作っていく 仲間をさがしています。
Ruby, Ruby on Rails (Webアプリケーション)
C#,ASP.NET MVC (Webアプリケーション)
iOS / Android アプリ
- 個人向け名刺管理アプリ「Eight」 - 名刺データ化分散処理システム
- 法人向け名刺管理サービス「Sansan」
- 法人向け名刺管理サービス「Sansan」
- 個人向け名刺管理アプリ「Eight」
エンジニア募集中
Sansan 採用 検索
[email protected] まで お気軽にご連絡ください。
興味のある方は