a l y t i c s E n a b l e d 2 i m p o r t F i r e b a s e A n a l y t i c s 3 s t r u c t A n a l y t i c s { … } 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 l e t a n a l y t i c s = A n a l y t i c s ( ) 8 a n a l y t i c s . s e n d E v e n t ( ... ) 9 # e n d i f
i f A n a l y t i c s E n a b l e d 2 i m p o r t F i r e b a s e A n a l y t i c s 3 s t r u c t A n a l y t i c s { … } 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 l e t a n a l y t i c s = A n a l y t i c s ( ) 8 a n a l y t i c s . s e n d E v e n t ( ... ) 9 # e n d i f
n a l y t i c s E n a b l e d 2 i m p o r t F i r e b a s e A n a l y t i c s 3 s t r u c t A n a l y t i c s { … } 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 l e t a n a l y t i c s = A n a l y t i c s ( ) 8 a n a l y t i c s . s e n d E v e n t ( ... ) 9 # e n d i f
A n a l y t i c s E n a b l e d 2 i m p o r t F i r e b a s e A n a l y t i c s 3 s t r u c t A n a l y t i c s { … } 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 l e t a n a l y t i c s = A n a l y t i c s ( ) 8 a n a l y t i c s . s e n d E v e n t ( ... ) 9 # e n d i f
i f A n a l y t i c s E n a b l e d 2 i m p o r t F i r e b a s e A n a l y t i c s 3 s t r u c t A n a l y t i c s { … } 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 l e t a n a l y t i c s = A n a l y t i c s ( ) 8 a n a l y t i c s . s e n d E v e n t ( ... ) 9 # e n d i f
A n a l y t i c s E n a b l e d 2 i m p o r t F i r e b a s e A n a l y t i c s 3 s t r u c t A n a l y t i c s { … } 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 l e t a n a l y t i c s = A n a l y t i c s ( ) 8 a n a l y t i c s . s e n d E v e n t ( ... ) 9 # e n d i f import が絡むと依存解決など複雑化する‧‧‧
n a l y t i c s E n a b l e d 2 l e t a n a l y t i c s = A n a l y t i c s ( ) 3 a n a l y t i c s . s e n d E v e n t ( ... ) 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 i m p o r t F i r e b a s e A n a l y t i c s 8 s t r u c t A n a l y t i c s { … } 9 # e n d i f 1 i m p o r t A n a l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 }
a l y t i c s E n a b l e d 2 l e t a n a l y t i c s = A n a l y t i c s ( ) 3 a n a l y t i c s . s e n d E v e n t ( ... ) 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 i m p o r t F i r e b a s e A n a l y t i c s 8 s t r u c t A n a l y t i c s { … } 9 # e n d i f After 1 i m p o r t A n a l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } Analytics をインスタンス化するときも AnalyticsEnabled のチェックが必要
i c s E n a b l e d 2 l e t a n a l y t i c s = A n a l y t i c s ( ) 3 a n a l y t i c s . s e n d E v e n t ( ... ) 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 i m p o r t F i r e b a s e A n a l y t i c s 8 s t r u c t A n a l y t i c s { … } 9 # e n d i f 改善前と改善後の⽐較 04 ゴールイメージの共有 Before After 1 i m p o r t A n a l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } AnalyticsEnabled が有効なときしか FirebaseAnalytics を import できない
l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } 改善前と改善後の⽐較 04 ゴールイメージの共有 Before モジュールとして Analytics 機能を分離し import することで利⽤する After 1 # i f A n a l y t i c s E n a b l e d 2 l e t a n a l y t i c s = A n a l y t i c s ( ) 3 a n a l y t i c s . s e n d E v e n t ( ... ) 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 i m p o r t F i r e b a s e A n a l y t i c s 8 s t r u c t A n a l y t i c s { … } 9 # e n d i f
i m p o r t A n a l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } Before 1 # i f A n a l y t i c s E n a b l e d 2 l e t a n a l y t i c s = A n a l y t i c s ( ) 3 a n a l y t i c s . s e n d E v e n t ( ... ) 4 # e n d i f 5 6 # i f A n a l y t i c s E n a b l e d 7 i m p o r t F i r e b a s e A n a l y t i c s 8 s t r u c t A n a l y t i c s { … } 9 # e n d i f
m p o r t A n a l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 }
l y t i c s 2 3 i f l e t a n a l y t i c s : A n a l y t i c s P r o t o c o l = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } オプション機能の参照コード 05 仕組みを紐解く 具象クラスを参照しないよう Protocol を定義して抽象化する import による複雑化 テストしづらい デバッグしづらい コンパイルされない
m p o r t A n a l y t i c s 2 3 i f l e t a n a l y t i c s : A n a l y t i c s P r o t o c o l = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } create() AnalyticsFactory.swift
m p o r t A n a l y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14
デバッグしづらい コンパイルされない i m p o r t A n a l y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Analytics Protocols モジュール AnalyticsFactory.swift
y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Analytics モジュール 05 仕組みを紐解く import できるか AnalyticsFactory テストしづらい import による複雑化 デバッグしづらい コンパイルされない
y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import できるか AnalyticsFactory Analytics モジュール 05 仕組みを紐解く import できるなら AnalyticsImpl のインスタンスを返却 テストしづらい import による複雑化 デバッグしづらい コンパイルされない
y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import できるなら AnalyticsImpl のインスタンスを返却 Analytics モジュール 05 仕組みを紐解く Analytics Impls モジュール AnalyticsImpl.swift import できるか AnalyticsFactory テストしづらい import による複雑化 デバッグしづらい コンパイルされない
m p o r t A n a l y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import できるなら AnalyticsImpl のインスタンスを返却 Analytics Impls モジュール AnalyticsImpl.swift
y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Analytics モジュール 05 仕組みを紐解く Analytics Impls モジュール AnalyticsImpl.swift テストしづらい import による複雑化 デバッグしづらい コンパイルされない import できるか AnalyticsFactory import できない場合には nil を返却
m p o r t A n a l y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import できるかどうかが オプション機能の有効 / 無効を表現している
y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Analytics モジュール 05 仕組みを紐解く import できる場合と できない場合が存在する テストしづらい import による複雑化 デバッグしづらい コンパイルされない
y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Analytics モジュール 05 仕組みを紐解く 不在の可能性がある Optional な AnalyticsImpls モジュール テストしづらい import による複雑化 デバッグしづらい コンパイルされない
p a c k a g e = P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 05 仕組みを紐解く テストしづらい import による複雑化 デバッグしづらい コンパイルされない 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 FirebaseAnalytics を利⽤するため dependencies に記述
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く AnalyticsProtocols モジュール テストしづらい import による複雑化 デバッグしづらい コンパイルされない
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く オプション機能の実装が含まれる AnalyticsImpls モジュール テストしづらい import による複雑化 デバッグしづらい コンパイルされない
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く AnalyticsImpl 構造体は AnalyticsProtocol に準拠する テストしづらい import による複雑化 デバッグしづらい コンパイルされない
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く FirebaseAnalytics を依存に追加する テストしづらい import による複雑化 デバッグしづらい コンパイルされない
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く import による複雑化 AnalyticsImpls だけが FirebaseAnalytics に依存するようになった テストしづらい デバッグしづらい コンパイルされない
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( ... ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s”, . p r o d u c t ( n a m e : “F i r e b a s e A n a l y t i c s”, p a c k a g e : “f i r e b a s e - i o s - s d k”) ] ) , . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, d e p e n d e n c i e s : [ ] ) ] ) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く Analytics モジュールは どう定義するか import による複雑化 テストしづらい デバッグしづらい コンパイルされない
p a c k a g e = P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く resultBuilder を活⽤ import による複雑化 テストしづらい デバッグしづらい コンパイルされない dependencies で if ⽂を利⽤できるように
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く 条件分岐を利⽤しながら ⼦要素の組み合わせを宣⾔的に記述できる import による複雑化 テストしづらい デバッグしづらい コンパイルされない resultBuilder を活⽤ s t r u c t S a m p l e V i e w : V i e w { v a r b o d y : s o m e : V i e w { T e x t ( “1” ) i f f l a g { T e x t ( “2” ) } } } 1 2 3 4 5 6 7 8
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く analyticsEnabled が true の時だけ AnalyticsImpls モジュールに依存する import による複雑化 テストしづらい デバッグしづらい コンパイルされない
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 05 仕組みを紐解く analyticsEnabled を操作することで Analytics モジュールの依存関係を変更できるようになった import による複雑化 テストしづらい デバッグしづらい コンパイルされない
p a c k a g e = P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 モジュール化戦略のポイント 「Package.swift でモジュール構成を⾃由に組み替える」
p a c k a g e = P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s P r o t o c o l s” ] ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 05 仕組みを紐解く オプション機能が無効なとき import による複雑化 テストしづらい デバッグしづらい コンパイルされない
y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Analytics モジュール 05 仕組みを紐解く import による複雑化 テストしづらい デバッグしづらい コンパイルされない オプション機能が無効なとき
l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } オプション機能の参照コード 05 仕組みを紐解く import による複雑化 テストしづらい デバッグしづらい コンパイルされない オプション機能が無効なとき
p a c k a g e = P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
= P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : [ “A n a l y t i c s I m p l s ”, “A n a l y t i c s P r o t o c o l s” ] ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 05 仕組みを紐解く オプション機能が有効なとき import による複雑化 テストしづらい デバッグしづらい コンパイルされない
m p o r t A n a l y t i c s P r o t o c o l s # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) i m p o r t A n a l y t i c s I m p l s # e n d i f p u b l i c c l a s s A n a l y t i c s F a c t o r y { s t a t i c f u n c c r e a t e ( ) -> A n a l y t i c s P r o t o c o l ? { # i f c a n I m p o r t ( A n a l y t i c s I m p l s ) r e t u r n A n a l y t i c s I m p l ( ) # e l s e r e t u r n n i l # e n d i f } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 オプション機能が有効なとき
m p o r t A n a l y t i c s 2 3 i f l e t a n a l y t i c s = A n a l y t i c s F a c t o r y . c r e a t e ( ) { 4 a n a l y t i c s . s e n d E v e n t ( ... ) 5 } オプション機能が有効なとき
i m p o r t A n a l y t i c s P r o t o c o l s 2 i m p o r t F i r e b a s e A n a l y t i c s 3 4 s t r u c t A n a l y t i c s I m p l : A n a l y t i c s P r o t o c o l { 5 f u n c s e n d E v e n t ( ... ) { … } 6 }
l y t i c s P r o t o c o l s 2 i m p o r t F i r e b a s e A n a l y t i c s 3 4 s t r u c t A n a l y t i c s I m p l : A n a l y t i c s P r o t o c o l { 5 f u n c s e n d E v e n t ( ... ) { … } 6 } AnalyticsImpls モジュール 05 仕組みを紐解く デバッグしづらい テストしづらい 静的解析されない import による複雑化 コンパイルされない Active Compilation Conditions が無くなり AnalyticsImpl がコンパイルされるようになった 常に import できる
Active Compilation Conditions が無くなり AnalyticsImpl がコンパイルされるようになった 1 i m p o r t A n a l y t i c s P r o t o c o l s 2 i m p o r t F i r e b a s e A n a l y t i c s 3 4 s t r u c t A n a l y t i c s I m p l : A n a l y t i c s P r o t o c o l { 5 f u n c s e n d E v e n t ( ... ) { … } 6 } 常に import できる
t p a c k a g e = P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
t p a c k a g e = P a c k a g e ( d e p e n d e n c i e s : [ . p a c k a g e ( u r l : “ h t t p s : / /… / f i r e b a s e - i o s - s d k . g i t ”, … ) ] , t a r g e t : [ . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, d e p e n d e n c i e s : . b u i l d { i f C o n f i g u r a t i o n . a n a l y t i c s E n a b l e d { “A n a l y t i c s I m p l s ” } “A n a l y t i c s P r o t o c o l s” } ) , . t a r g e t ( n a m e : “A n a l y t i c s I m p l s ”, … . t a r g e t ( n a m e : “A n a l y t i c s P r o t o c o l s”, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
s t r u c t C o n f i g u r a t i o n { 2 s t a t i c l e t a n a l y t i c s E n a b l e d = t r u e 3 } 4 5 l e t p a c k a g e = P a c k a g e ( ... )
f i g u r a t i o n { 2 s t a t i c l e t a n a l y t i c s E n a b l e d = t r u e 3 } 4 5 l e t p a c k a g e = P a c k a g e ( ... ) 05 仕組みを紐解く Package.swift スクリプトで Bool 値を変更する デバッグしづらい テストしづらい 静的解析されない import による複雑化 コンパイルされない
f i g u r a t i o n { 2 s t a t i c l e t a n a l y t i c s E n a b l e d = t r u e 3 } 4 5 l e t p a c k a g e = P a c k a g e ( ... ) 05 仕組みを紐解く Package.swift デバッグしづらい テストしづらい 静的解析されない import による複雑化 コンパイルされない スクリプトで Configuration 構造体を⽣成し 1~3 ⾏⽬を置換している
f i g u r a t i o n { 2 s t a t i c l e t a n a l y t i c s E n a b l e d = t r u e 3 } 4 5 l e t p a c k a g e = P a c k a g e ( ... ) 05 仕組みを紐解く Package.swift ⼿動で Bool 値を変更するだけで ⾊々な組み合わせを検証できるようになった デバッグしづらい テストしづらい 静的解析されない import による複雑化 コンパイルされない
f i g u r a t i o n { 2 s t a t i c l e t a n a l y t i c s E n a b l e d = t r u e 3 } 4 5 l e t p a c k a g e = P a c k a g e ( ... ) 05 仕組みを紐解く Package.swift 有効化してデバッグを開始するまでの⼿順が Bool 値を変更するだけになった デバッグしづらい テストしづらい 静的解析されない import による複雑化 コンパイルされない
s t r u c t C o n f i g u r a t i o n { 2 s t a t i c l e t a n a l y t i c s E n a b l e d = t r u e 3 } 4 5 l e t p a c k a g e = P a c k a g e ( ... )