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.9k
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
580
Unityテスト活動のふりかえり
adarapata
1
580
Gather.townはいいぞ その後
adarapata
1
1.6k
Unityでの開発事例
adarapata
3
23k
どこのご家庭にもあるシーンマネージャーの話
adarapata
1
8.3k
Gather.townはいいぞ
adarapata
2
2.4k
宴はいいぞ
adarapata
0
1.5k
わかった気になるモブプログラミング
adarapata
1
120
モブワークっぽいのをやっている話/Trying mobwork
adarapata
2
1.3k
Other Decks in Programming
See All in Programming
AI駆動で0→1をやって見えた光と伸びしろ
passion0102
1
880
フロントエンド開発のためのブラウザ組み込みAI入門
masashi
7
3.6k
理論と実務のギャップを超える
eycjur
0
190
Server Side Kotlin Meetup vol.16: 内部動作を理解して ハイパフォーマンスなサーバサイド Kotlin アプリケーションを書こう
ternbusty
3
260
オンデバイスAIとXcode
ryodeveloper
0
260
コードとあなたと私の距離 / The Distance Between Code, You, and I
hiro_y
0
200
Google Opalで使える37のライブラリ
mickey_kubo
3
150
React Nativeならぬ"Vue Native"が実現するかも?_新世代マルチプラットフォーム開発フレームワークのLynxとLynxのVue.js対応を追ってみよう_Vue Lynx
yut0naga1_fa
2
1.8k
Claude CodeによるAI駆動開発の実践 〜そこから見えてきたこれからのプログラミング〜
iriikeita
0
360
Software Architecture
hschwentner
6
2.3k
他言語経験者が Golangci-lint を最初のコーディングメンターにした話 / How Golangci-lint Became My First Coding Mentor: A Story from a Polyglot Programmer
uma31
0
450
Temporal Knowledge Graphで作る! 時間変化するナレッジを扱うAI Agentの世界
po3rin
3
770
Featured
See All Featured
A better future with KSS
kneath
239
18k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.1k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.5k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Statistics for Hackers
jakevdp
799
220k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.7k
A Modern Web Designer's Workflow
chriscoyier
697
190k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
2.9k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
658
61k
Fireside Chat
paigeccino
41
3.7k
For a Future-Friendly Web
brad_frost
180
10k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
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