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