Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Zenjectを導入する前に
Search
いも
December 19, 2019
Programming
0
3.7k
Zenjectを導入する前に
2019/12/19 Roppongi.unity #6 のLT資料です
いも
December 19, 2019
Tweet
Share
More Decks by いも
See All by いも
UnityプログラミングバイブルR6号宣伝&Unity Logging小話
adarapata
0
350
Unityテスト活動のふりかえり
adarapata
1
500
Gather.townはいいぞ その後
adarapata
1
1.4k
Unityでの開発事例
adarapata
3
22k
どこのご家庭にもあるシーンマネージャーの話
adarapata
1
7k
Gather.townはいいぞ
adarapata
2
2.3k
宴はいいぞ
adarapata
0
1.2k
わかった気になるモブプログラミング
adarapata
1
77
モブワークっぽいのをやっている話/Trying mobwork
adarapata
2
1.2k
Other Decks in Programming
See All in Programming
メモリ最適化を究める!iOSアプリ開発における5つの重要なポイント
yhirakawa333
0
420
Developer Joy == Developer Productivity (really!)
hollycummins
1
210
Kotlin 2.0 and Beyond
antonarhipov
2
150
サーバーレスで負荷試験!Step Functions + Lambdaを使ったk6の分散実行
shuntakahashi
6
1.6k
Modular Monolith Go Server with GraphQL Federation + gRPC
110y
1
580
GoのIteratorに詳しくなってしまう
inatonix
1
200
LangChainでWebサイトの内容取得やGitHubソースコード取得
shukob
0
160
The Sequel to a Dream of Ruby Parser's Grammar
ydah
1
220
Rubyとクリエイティブコーディングの輪の広がり / The Growing Circle of Ruby and Creative Coding
chobishiba
1
270
Boost Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
470
GraphQL あるいは React における自律的なデータ取得について
quramy
11
3k
A New Era of Testing
mannodermaus
2
510
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
5
480
Reflections from 52 weeks, 52 projects
jeffersonlam
346
20k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
43
2k
Web development in the modern age
philhawksworth
205
10k
YesSQL, Process and Tooling at Scale
rocio
167
14k
10 Git Anti Patterns You Should be Aware of
lemiorhan
653
58k
Robots, Beer and Maslow
schacon
PRO
157
8.2k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.2k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
8.9k
Put a Button on it: Removing Barriers to Going Fast.
kastner
58
3.4k
Build The Right Thing And Hit Your Dates
maggiecrowley
30
2.3k
Rails Girls Zürich Keynote
gr2m
93
13k
Transcript
━━━━━━━━━━━━━━━━━ Zenjectを導⼊する前に いも(@adarapata) ━━━━━━━━━━━━━━━━━ 2019/12/19 Roppongi.unity #6 1
⾃⼰紹介 いも (@adarapata) adarapata.com 仕事でUnity触ってるエンジニア テスト、DIとかよく話すおじさん 2019/12/19 Roppongi.unity #6 2
宣伝 「ZenjectチョットワカルBook」 基礎的な使い⽅を纏めた本 多分⽇本で唯⼀のZenject本 boothで電⼦版販売中 後編もうちょっとまって 2019/12/19 Roppongi.unity #6 3
はなすこと DIフレームワークを導⼊するその前に考えること Zenject内部の話はあんまりしない 対象者 すでに動いているプロダクトにZenjectを導⼊しようとしている⼈ 2019/12/19 Roppongi.unity #6 4
Zenject is 便利 シングルトン無くせる! 疎結合な設計ができる! テスタビリティ⾼い! わが社もDIフレームワークでイケイケ開発だ! 2019/12/19 Roppongi.unity #6
5
既存プロダクトにZenjectを⼊れる 動いてるものにライブラリを⼊れるのドキドキするよね ミニマムにスタートしたくなるのが⼼情 特定のクラスだけDIするとかから始めたい 2019/12/19 Roppongi.unity #6 6
Zenject対応の⼀例 シングルトン依存 動的に作られるFoo public class Foo { public void DoFoo()
{ var some = BarSingleton.Instance.SomeLogic(); // some でなんやかんや } } テストを書きやすくしたい! シングルトン依存を無くしたい! 2019/12/19 Roppongi.unity #6 7
interfaceをBindしてDIだ! public class Foo { private IBarSingleton _bar; public Foo(IBarSingleton
bar) { _bar = bar; } public void DoFoo() { var some = _bar.SomeLogic(); // some でなんやかんや } } Container.Bind<Foo>().AsCached(); Container.Bind<IBarSingleton>().To<BarSingleton>().AsSingle(); 2019/12/19 Roppongi.unity #6 8
動的に作られるならFactoryにしないといけないよね public class Foo { private BarSingleton _bar; public Foo(BarSingleton
bar) { _bar = bar; } public void DoFoo() { var some = _bar.SomeLogic(); // some でなんやかんや } public class Factory : PlaceholderFactory<Foo> {} } Container.BindFactory<Foo, FooFactory>(); Container.Bind<IBarSingleton>().To<BarSingleton>().AsSingle(); 2019/12/19 Roppongi.unity #6 9
Fooを⽣成してたところもZenject対応必要だよね public class FooSpawner { private Foo.Facotry _factory; public FooSpawner(Foo.Factory
factory) { _factory = factory } public void Spawn() { // var foo = new Foo(); 今までこうだった var foo = _factory.Create(); } } Container.Bind<FooSpawner>().AsCached(); // 追加 Container.BindFactory<Foo, FooFactory>(); Container.Bind<BarSingleton>().AsSingle(); 2019/12/19 Roppongi.unity #6 10
FooSpawnerに依存しているクラスもZenject対応必要だよね ↑に依存してるやつも必要だよね ↑に依存してるやつ(ry ↑に依存し(ry ↑(ry 結局シーンのオブジェクト全部対応必要じゃね? 影響範囲やばい 1クラスを綺麗にしたかっただけなのに 2019/12/19 Roppongi.unity
#6 11
Zenject対応の⼀例 循環参照 public class Fizz { private Buzz _buzz; public
Fizz(Buzz buzz) { _buzz = buzz; } } public class Buzz { private Fizz _fizz; public Buzz(Fizz fizz) { _fizz = fizz; } } Zenjectはコンストラクタインジェクションの循環参照を許さない 2019/12/19 Roppongi.unity #6 12
フィールドインジェクションなどで頑張ることになる public class Fizz { [Inject] private Buzz _buzz; }
public class Buzz { [Inject] private Fizz _fizz; } 対応はできるがZenject以外の⽅法でこのクラスを扱うことは難しくなる 2019/12/19 Roppongi.unity #6 13
Zenjectを使おうとして明らかになることがある ⾃分のコードはどのような依存関係を持っているのか それは適切なものなのかが如実に表れる 循環参照があるとしんどくなる 1クラスに⼤量の依存があるとしんどくなる 階層がめっちゃ深くてもしんどくなる この部分だけZenjectみたいなつまみ⾷いは割と⼤変 これらを強引にZenjectの機能で解決しようとすると苦戦を強いられ導⼊コストと 運⽤コストが跳ね上がる 2019/12/19
Roppongi.unity #6 14
あなたのコードはDIできますか? DIフレームワークはコードを綺麗にしてくれない ⼈間がDIフレームワークを活⽤してコードを綺麗にする DIできる状態じゃないとDIできない禅問答 Zenjectを使う前に、そもそもZenjectを使えるような作り⽅にしないとい けない 2019/12/19 Roppongi.unity #6 15
Zenjectでしか解決できない問題はそんなにない スコープを狭めれば⼿動でDIはできる public class FooSpawner { public void Spawn() {
var foo = new Foo(BarSingleton.Instance); // Non Zenject //var foo = _factory.Create(); } } テストを書きやすくしたい! => シングルトン依存を無くしたい! => 2019/12/19 Roppongi.unity #6 16
インタフェースに依存させれば循環参照を無くせる public interface IFizz { } public class Fizz :
IFizz { private Buzz _buzz; public Fizz(Buzz buzz) { _buzz = buzz; } } public class Buzz { private IFizz _fizz; public Buzz(IFizz fizz) { _fizz = fizz; } } 2019/12/19 Roppongi.unity #6 17
Zenjectを使う = 設計と向き合うこと 導⼊しただけでは何も変わらない、導⼊できるかもわからない 疎結合になるのではなく、疎結合にしていかないといけなくなる リファクタリングはほぼ必須 リファクタリングの際にテストが活きてくる 2019/12/19 Roppongi.unity #6
18
Zenjectを導⼊する前に 銀の弾丸ではないことを理解する DIパターンを適⽤できるコードなのか⾒直す できない状態であるなら、今後どういうアプローチを取るのか考える 地道なリファクタリングしましょう Zenjectに依存しないこと 2019/12/19 Roppongi.unity #6 19
Zenjectに依存とは? コードレベルで⾒ると依存は避けられない(assembly的な意味で) ではなく、設計レベルで解決しなければならないものをZenjectを使って解決す ることを Zenjectに依存する と考えている 循環参照をフィールドインジェクションでねじ伏せる ProjectContextでグローバルなBindを⼤量展開 単⼀責任原則を⼤きく違反していてもInstallerで⼿軽に⼤量Bindできる ようにする
etc.. 鎮痛剤としては使えないことを理解する 2019/12/19 Roppongi.unity #6 20
それでもZenjectはいいぞ Zenjectを⼊れずとも運⽤するアプリなら設計とは向き合わなければならない そこでDIという選択肢が増えるのはよいこと 導⼊時のコストは未来への先⾏投資 OSSなので集合知がある。あなたの悩みは誰かが解決してる 誰かの悩みをあなたが解決できる 巨⼈の肩に乗っかろう 2019/12/19 Roppongi.unity #6
21