Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ワタシはSingletonがキライだ

第50回Cocoa勉強会関西の発表資料です。

  • Login to see the comments

ワタシはSingletonがキライだ

  1. 1. ワタシはSingletonがキライだかねうちてつや / @kaniza2013.6.1 第50回 Cocoa勉強会関西
  2. 2. 自己紹介かねうちてつや @kaniza id:kanizaCocoa勉強会関西2代目代表(2012年まで)元Java屋さん(5年くらい前)
  3. 3. Singleton おさらいGoF デザインパターンの1つオブジェクトの単一性を保証する頻繁に利用される[HogeManager sharedInstance] とか
  4. 4. よくある光景エンジニア仲間とビールを飲むさらに飲むSingleton を dis りはじめるまわりが困る
  5. 5. なぜ困るのか問題意識が共有できない解決策が見えないろれつが回っていない
  6. 6. 今日のゴールろれつが回らなくなる前に問題意識を共有して解決策を提案する
  7. 7. 前提となる価値観単体テストしたいでもできてないグローバル変数は悪≒ 密結合は悪
  8. 8. よい設計疎結合高凝集適切な名前変更時の影響範囲が予測可能かつ最小限
  9. 9. Big Ball of Mud最も人気のあるソフトウェアアーキテクチャは Big Ball of Mud(大きな泥だんご)である
  10. 10. 設計のイメージMainViewControllerSongStoreSongManagerDetailViewControllerArtworkGenerator結合度: 低
  11. 11. 現実の実装MainViewControllerSongStoreSongManagerDetailViewControllerArtworkGenerator結合度: 高Big Ball of Mud
  12. 12. Singletonの誘惑設計上、離れた場所にある”コンポーネント”への参照が欲しくなったときManaged Object Context とかHogeManager とかクラスメソッドならどこからでも見える
  13. 13. 典型的な実装+ (id)sharedInstance{static HogeManager *instance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance = [[self alloc] init];});return instance;}このクラスメソッドでのみアクセスさせる
  14. 14. これってグローバル変数
  15. 15. 単体テストクラスごと、メソッドごとにテストコードを書いて自動化するそれにはオブジェクトが「単体」で動く必要があるファイルシステムやネットワークは邪魔
  16. 16. static 結合はテストの敵MyClassFileManagerConnectionManagerstaticstaticテストコードからはファイルやネットワークアクセスを防げないTest Code
  17. 17. dynamic 結合なら何とかなるMyClassMockFileManagerMockConnManagerdynamicdynamicテストコードからモックオブジェクトに差し替え可能Test Code
  18. 18. Singleton と static 結合Singleton は static な結合を招くインスタンスの数は問題ではないアクセス方法を static に規定するのが悪static 結合はテスト不能なクラスへの道
  19. 19. Singleton は単体テストの敵
  20. 20. キライになってきた?
  21. 21. 解決策
  22. 22. DI: Dependency Injection依存性注入オブジェクトが依存先を解決しない必要なものは与えられる。取りに行くな取りに行くときにSingletonの誘惑が....
  23. 23. DI コンテナ専用のコンテナオブジェクトにコンポーネントの情報を登録コンポーネントの依存関係を解決して生成コンポーネントインスタンスの数も管理(普通は1個でいいはず)原則、コンポーネントの alloc init は不要に
  24. 24. DIコンテナの依存性解決ABCCが必要になったらA, B, Cの順に生成してくれる依存依存依存
  25. 25. オブジェクト生成は大仕事あるオブジェクトを生成するのに必要なオブジェクトを えるのはけっこう大変他のオブジェクトを生成するためだけに依存関係が発生してしまうことも大変なのでコンテナに任せてしまおう
  26. 26. Cocoa 向け DI コンテナ
  27. 27. Typhoon Framework
  28. 28. Typhoon Framework元 Java 屋に親しみやすいデザインコンポーネント情報を Block で書けるコンポーネント側をほぼいじらないっぽいTyphoonAssembly のサブクラスにコンポーネント情報を記述、TyphoonFactoryから取得
  29. 29. Cocoa Singleton あるあるNSManagedObjectContextAppDelegate から取得?NSBundlemainBundle
  30. 30. CoreDataBooks onTyphoon
  31. 31. CoreDataBooks on TyphoonApple のサンプルコードを Typhoon ベースに変換AppDelegate の Core Data Stack コードを一掃コンポーネントは他のコンポーネントへの参照を注入されるサブクラス化して細かいパラメータ初期化
  32. 32. DIの気持ち悪さ別名 IoC (Inversion of Control: 制御の反転)取りに行くのではなく与えられる自分でやってた部分を他人に任せる中身がよく見えなくなる
  33. 33. IoC はオブジェクト指向の基本フロー型からイベントドリブンへの流れはまさに「制御の反転」viewDidLoad とかapplicationDidFinishLaunching:とかだんだん気持ち良くなる
  34. 34. DI コンテナの誤解コンポーネントを取得するためにコンテナへのアクセスが多発するコンテナへのアクセスはごく一部。基本的に注入されたコンポーネントを使う生成が必要ならファクトリオブジェクトをコンポーネントとして注入する
  35. 35. DI コンテナの誤解テストコードでもコンテナを使うふつう使わない。テストコードから直接モックオブジェクトなどを注入するinitializer が長くなる本当かも。でも自分で呼ばないし!
  36. 36. まとめSingleton は現代のグローバル変数。結合度が高くテストしにくいコードを招くSingletonでやりたいことはTyphoon などの DIコンテナを使えば美しく実現できる疎結合でテストしやすいコードバンザイ

×