Slide 1

Slide 1 text

"OESPJEͰ࢖͑Δ,PUMJOϨγϐ ,BNFEPO

Slide 2

Slide 2 text

ϓϩϑΟʔϧ  • Χϝυϯ • Kotlin޷͖Ͱ͢ • AndroidͷΞϓϦ։ൃ΍ͬͯ·͢ • ϘʔυήʔϜ͕޷͖Ͱ͢ Akiba.BoardGameओ࠵

Slide 3

Slide 3 text

,PUMJO͕"OESPJEެࣜݴޠԽ㊗ 

Slide 4

Slide 4 text

 Έͳ͞Μ
 KotlinͰշదAndroidΞϓϦ։ൃͯ͠·͔͢ʁ

Slide 5

Slide 5 text

,PUMJO  w+FUCSBJOT੡ϦϦʔε w+7.ݴޠɺ,PUMJO/BUJWF w#FUUFS+BWB+BWBޓ׵ੑ w੩తܕ෇͚ wΦϒδΣΫτࢦ޲ w/VMM҆શ ΑΓ/VMMѻ͍΍͘͢ͳΔʣ

Slide 6

Slide 6 text

ର৅ऀ  w,PUMJOΛҰ౓͸৮ͬͨ͜ͱ͕͋Δਓ w,PUMJOͷػೳ͸ͳΜͱͳ͘Θ͔Δ͕ɺ
 "OESPJEͰͲ͏׆͔͢೰ΜͰ͍Δਓ w,PUMJOΛ࣮ફతͳίʔυΛ஌Γ͍ͨํ KotlinͷྗΛ։์͍ͤͨ͞

Slide 7

Slide 7 text

"OESPJEͰ,PUMJOͷྗΛղ͖์ͭϨγϐ  ,PUMJOͷྗΛղ͖์ͭΛΩʔϫʔυΛ٧ΊࠐΈ·ͨ͠
 ݴޠ࢓༷ͷࡉ͍ͱ͜Ζ·Ͱࠓճ͸ѻ͍·ͤΜ w1SPQFSUJFTBOE'JFMET w%4- w%*

Slide 8

Slide 8 text

"OESPJEͰ,PUMJOͷྗΛղ͖์ͭϨγϐ  Properties and Fields

Slide 9

Slide 9 text

,PUMJOͷ1SPQFSUJFTBOE'JFMET  wLFZXPSEQSPQFSUZ/BNF<1SPQFSUZ5ZQF>< QSPQFSUZ@JOJUJBMJ[FS>
 <HFUUFS><TFUUFS> wLFZXPSEWBM SFBEPOMZ WBS NVUBCMF  w1SPQFSUZ5ZQF<ʜ>
 ͳ͠ /PU/VMM ɺ /VMMBCMF ɺ 1MBUGPSN5ZQF  wWBMIPHF4USJOHl5FTUz wWBSGPP4USJOH OVMM

Slide 10

Slide 10 text

1SPQFSUJFTBOE'JFMETͷબͼํʹ͍ͭͯ  WBSΑΓWBMɺ ΑΓ /PU/VMM ɺΑΓ ͷ΄͏͕ΑΓ҆શ wWBMͰࣄ଍ΓΔͷͰ͋Ε͹ɺWBMΛ࢖༻͠Α͏͢Δ
 ্ॻ͖͠ͳ͍Α͏ʹؾΛ͚ͭΔͰ͸ͳ͘ɺ
 ্ॻ͖Ͱ͖ͳ͍Α͏ʹ͢Δ wΫϥε੹຿తʹ͸WBM͕ͩɺ"OESPJEͷ࢓্༷WBS΍ ʹͤ͟ Δ௥͑ͳ͍͕࣌ଟʑ͋Δ w͋Δఔ౓ճආ͢ΔςΫχοΫ͕ଘࡏ͢Δ

Slide 11

Slide 11 text

1SPQFSUJFTBOE'JFMETͷࢦ਑Λ࡞ͬͯΈͨ 

Slide 12

Slide 12 text

ܕͷબͼํ 

Slide 13

Slide 13 text

ॳظԽ࣌ʹΠϯελϯεԽͰ͖Δ  ActivityͷϥΠϑαΠΫϧͳͲʹґଘ͠ͳ͍৔߹ class SampleActivity : AppCompatActivity() {
 
 val adapter = ItemAdapter()
 
 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(R.layout.activity_sample)
 val listView = (findViewById(R.id.listView) as ListView)
 listView.adapter = adapter
 }
 }

Slide 14

Slide 14 text

ܕͷબͼํ 

Slide 15

Slide 15 text

"DUJWJUZ࢓༷ͷ͍ͤͰॳظԽͰ͖ͳ͍  ίϯύΠϧ͸௨Δ͕ɺNPEʹͳΔ setContentViewҎ߱Ͱͳ͍ͱfindViewById͸औಘͰ͖ͳ͍ class SampleActivity : AppCompatActivity() {
 
 val adapter = ItemAdapter()
 
 val listView = (findViewById(R.id.listView) as ListView)
 
 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(R.layout.activity_sample)
 listView.adapter = adapter
 }
 }

Slide 16

Slide 16 text

"DUJWJUZϥΠϑαΠΫϧͷ͍ͤͰॳظԽͰ͖ͳ͍  listViewΛࢀর͞ΕΔ·ͰॲཧΛ஗Ԇ͢Δ setContentViewҎ߱Ͱࢀর͞Ε͍ͯΔͨΊ໰୊ͳ͠ class SampleActivity : AppCompatActivity() {
 
 val adapter = ItemAdapter()
 
 val listView by lazy {
 (findViewById(R.id.listView) as ListView)
 }
 
 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(R.layout.activity_sample)
 listView.adapter = adapter
 }
 }

Slide 17

Slide 17 text

ܕͷબͼํ 

Slide 18

Slide 18 text

֎෦͔Βґଘؔ܎Λղܾ͢Δඞཁ͋Γ  class SampleActivity : AppCompatActivity() {
 val binding by lazy {
 DataBindingUtil.setContentView(this, R.layout.activity_sample)
 }
 }
 class SampleFragment : Fragment() {
 lateinit var binding: FragmentSampleBinding 
 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
 binding = DataBindingUtil.inflate (inflater, R.layout.fragment_sample, container, false)
 
 }
 }

Slide 19

Slide 19 text

֎෦͔Βґଘؔ܎Λղܾ͢Δඞཁ͋Γ  class SampleFragment : Fragment() {
 lateinit var binding: FragmentSampleBinding
 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
 binding = DataBindingUtil.inflate (inflater, R.layout.fragment_sample, container, false)
 
 }
 } inflaterͱcontainer͸onCreateViewͰ ࢀরͰ͖ΔΑ͏ʹͳΔͨΊɺby lazyͰॻ͘͜ͱ͕Ͱ͖ͳ͍

Slide 20

Slide 20 text

ܕͷબͼํ 

Slide 21

Slide 21 text

ϓϥοτϑΥʔϜܕͱઓ͏  +BWBͷϝιου͸ɺ ϓϥοτϑΥʔϜܕ ʹͳΔ wϓϥοτϑΥʔϜܕ͸ɺ/PU/VMMͰ΋/VMMBCMFͰ΋͋Δ w΋ͪΖΜ/PU/VMMͷͱ͖ʹ/VMM৔߹͸/1&ʹͳΔ

Slide 22

Slide 22 text

ϓϥοτϑΥʔϜܕͱઓ͏  val listView: View = findViewById(R.id.listView)
 val listView: View? = findViewById(R.id.listView)  ϓϥοτϑΥʔϜܕ ͷ৔߹͸໌ࣔతʹܕΛॻ͘ wϓϥοτϑΥʔϜܕ͸ɺܕਪ࿦͠ͳ͍΄͏͕٢ w/PU/VMMͩͱࢥ͏ͷͰ͋Ε͹ɺ/PU/VMMʹ͢Δ w/VMMͷॠؒʹ/1&ͰམͪΔͷͰૣظʹόάΛൃݟͰ͖Δ w,PUMJO͸/1&Ͱམͱ͞ͳ͍ٕज़Ͱ͸ͳ͘ɺ/VMMΛద੾ʹѻ͍΍͘͢ ͯ͘͠ΕΔɻҙਤ͠ͳ͍ͷͰ͋Ε͹མͱ͢΂͖ɻ

Slide 23

Slide 23 text

"OESPJEͰ,PUMJOͷྗΛղ͖์ͭϨγϐ  DSL (Domain Specific Language)

Slide 24

Slide 24 text

%4-  w͋ΔಛఆͷྖҬʢυϝΠϯʣͷ໰୊Λղܾ͢ΔͨΊʹ࡞ΒΕɺ ͦΕҎ֎ͷྖҬͷ໰୊Λղ͘͜ͱ͸૝ఆ͍ͯ͠ͳ͍ɻ wࠓճ͸7BMJEBUJPOΛྫʹ͢Δ wྫ͑͹ςΩετϘοΫεͳͲͰ6TFSͷOBNF͕ೖྗ͞Εͨͱ͖ ʹɺ༗ޮͳ΋ͷ͔ߟ͑Δ wจࣈ਺͸ɺdจࣈ·Ͱ༗ޮ

Slide 25

Slide 25 text

࠷ॳ͸ྑ͔͕ͬͨʜ  ػೳ௥Ճ͸͞Ε͍ͯ͘… • ৽ͨʹageΛ௥Ճ: 20ࡀҎ্ • name͕NGϫʔυΛؚ·ͳ͍ class User(val name: String) {
 
 fun vaildate(): Boolean {
 return name.length in 1..16 }
 
 }

Slide 26

Slide 26 text

ຊ౰ͷઓ͍͸͜Ε͔Βͩͥ  • ԿͰΤϥʔʹͳ͔ͬͨɺΤϥʔϝοηʔδ͍ͩͨ͠
 ɹɹɹɹɹɹɹɹɹʘ(^o^)ʗ class User(val name: String, val age: Int) {
 
 fun vaildate(): Boolean {
 return name.length in 1..16 &&
 name in listOf("hoge","foo") &&
 age >= 20
 }
 
 }

Slide 27

Slide 27 text

7BMJEBUJPOͷ%4-Λ࡞ͬͯɺϦϑΝΫλϦϯά  • Validation֤ཁૉͷ͋Δ΂͖࢟ɺͦ͏Ͱͳ͍࣌ͷϝοηʔδ • A ͸ B Ͱ͋Δɻͦ͏Ͱͳ͍࣌ɺ Error Message class User(val name: String, val age: Int) {
 
 fun vaildate(): Boolean {
 return name.length in 1..16 &&
 name in listOf("hoge","foo") &&
 age >= 20
 }
 
 }

Slide 28

Slide 28 text

%4-Ͱཁ݅  wυϝΠϯΛఆٛ͢Δදݱྗ wຊ࣭ʹूதͰ͖ΔΑ͏ʹγϯλοΫεΛΘ͔Γ΍͘͢ w*%&ͷػೳΛ͍͔͑ΔΑ͏ʹܕͳͲอ؅Ͱ͖Δ͔ wυϝΠϯͷݴ༿Ͱ͔͚Δ w"͸#Ͱ͋Δɻͦ͏Ͱͳ͍࣌ɺ&SSPS.FTTBHF

Slide 29

Slide 29 text

͍͖ͳΓ࠷ऴܕΛͲʔΜ  • User be {validation} not “error message” • Validation͕૿͑ͯ΋໰୊ͳ͠ • υϝΠϯͷจ๏ͷ··ͰɺಡΈ΍͍͢ class User(val name: String, val age: Int) {
 val validation = Validation { be { age >= 20 } not "成人のみです"
 be { name.length in 1..16 } not "1-16文字以下で"
 be { name !in listOf("hoge", "foo") } 
 not "NGワード以外で"
 }
 fun vaildate() = validation.validate(this)
 }

Slide 30

Slide 30 text

͞ΒʹಡΈ΍͘͢  • ΍Γա͗ײ͕͋Δ class User(val name: String, val age: Int) {
 val validation = Validation { of(age) be { it >= 20 } not "成人のみです"
 of(name) be { it.length in 1..16 } not "1-16文字以下で"
 of(name) be { it !in listOf("hoge", "foo") } 
 not "NGワード以外で"
 }
 fun vaildate() = validation.validate(this)
 }

Slide 31

Slide 31 text

%4-Λ࣮ݱ͢Δٕज़  wWBS͔ΒWBMʹ͢ΔͨΊʹ#VJMEFS wఆٛͬΆ͘͢ΔPQFSBUPSJOWPLF w୹͘͢ΔϨγʔόʔࢦఆMBNCEB w࠷ޙͷҾ਺ͷ৔߹͸ ΛলུՄೳ w୹͘͢Δ&YUFOTJPOT'VODUJPOTPS1SPQFSUJFT wӳޠͬΆ͍จ๏ʹJOpY

Slide 32

Slide 32 text

ఆٛͬΆ͘͢ΔPQFSBUPSJOWPLF  class Validation(val validations: List Boolean, String>>) {
 
 companion object { 
 operator fun invoke(init: ValidationBuilder.() -> Unit): Validation { 
 val builder = ValidationBuilder()
 return builder.apply(init).build()
 }
 } Validation { be { age >= 20 } not “成人のみです” } operator invokeͰinvokeΛলུɺValidation()Ͱ࣮ߦͰ͖Δ ࠷ޙ͕ϥϜμͳͷͰ()লུՄೳ͠ɺ{}ʹͳΔ

Slide 33

Slide 33 text

ఆٛͬΆ͘͢ΔPQFSBUPSJOWPLF  class Validation(val validations: List Boolean, String>>) {
 
 companion object { 
 operator fun invoke(init: ValidationBuilder.() -> Unit): Validation { 
 val builder = ValidationBuilder()
 return builder.apply(init).build()
 }
 } Validation.invoke({…}) Validation.invoke{…} Validation{…} operator invokeͰinvokeΛলུɺValidation()Ͱ࣮ߦͰ͖Δ ࠷ޙ͕ϥϜμͳͷͰ()লུՄೳ͠ɺ{}ʹͳΔ

Slide 34

Slide 34 text

WBS͔ΒWBMʹ͢ΔͨΊʹ  BuilderΛ࡞੒͠ɺ • ఆ͕ٛऴΘΔ·Ͱ͸mutableʹͯ͠Buildޙ͸immutableʹ͢Δ • Builder಺ʹఆٛ༻ͷγϯλοΫεΛด͡ΊΔ class Validation(val validations: List Boolean, String>>) {
 fun validate(value: T) = validations.filter { !it.first.invoke(value) }.map { it.second }
 }
 class ValidationBuilder { var validations: MutableList Boolean, String>> = mutableListOf()
 
 fun build(): Validation {
 return Validation(validations)
 }
 }

Slide 35

Slide 35 text

ϨγʔόʔࢦఆMBNCEB  class ValidationBuilder {
 var validations: MutableList Boolean, String>> = mutableListOf() 
 ɹɹfun be(validate: T.() -> Boolean) = validate } Validation { be { age >= 20 } not “成人のみです” } TͷvalidateΛϥϜμͰ࡞੒͢Δɺ࠷ޙͷϥϜμ͸লུՄೳ T.() -> Boolean) = (T)->Boolean ͷҧ͍͸ʁ

Slide 36

Slide 36 text

5 #PPMFBO 5 #PPMFBOͷҧ͍͸ʁ  Validation { be { it.age >= 20 } not “成人のみです” //fun be(validate: (T) -> Boolean) = validate be { this.age >= 20 } not “成人のみです” //fun be(validate: T.() -> Boolean) = validate } Ϩγʔόʔࢦఆͷ৔߹this͕TʹͳΔ

Slide 37

Slide 37 text

୹͘͢Δ&YUFOTJPOT'VODUJPOTPS1SPQFSUJFT  class ValidationBuilder {
 var validations: MutableList Boolean, String>> = mutableListOf()
 fun be(validate: T.() -> Boolean) = validate infix fun (T.() -> Boolean).not(error: String) {
 validations.add(this to error)
 } } Validation { be { age >= 20 } not “成人のみです” } validateͯ͠ແޮͳ஋ͩͬͨ৔߹Τϥʔϝοηʔδฦ͢Α͏ʹ͢Δ (T.() -> Boolean)ʹ֦ுؔ਺Λ࣮૷͠Pairʹͯ͠add͢Δ

Slide 38

Slide 38 text

ӳޠͬΆ͍จ๏ʹJOpY  class ValidationBuilder {
 var validations: MutableList Boolean, String>> = mutableListOf()
 fun be(validate: T.() -> Boolean) = validate infix fun (T.() -> Boolean).not(error: String) {
 validations.add(this to error)
 } } Validation { be { age >= 20 } not “成人のみです” } infix༗Γແ͠Ͳ͏ͳΔ͔ݟͯΈ·͠ΐ͏

Slide 39

Slide 39 text

ӳޠͬΆ͍จ๏ʹJOpY  Validation { be { it.age >= 20 }.not(“成人のみです”) //fun (T.() -> Boolean).not(error: String) 
 be { this.age >= 20 } not “成人のみです” //infix fun (T.() -> Boolean).not(error: String) } infixΛ࢖͏͜ͱͰ.() Λͳ͘͠ɺεϖʔε۠੾Γʹ ӳޠͬΆ͘Ͱ͖Δ

Slide 40

Slide 40 text

%4-Λ࣮ݱ͢Δٕज़  wWBS͔ΒWBMʹ͢ΔͨΊʹ#VJMEFS wఆٛͬΆ͘͢ΔPQFSBUPSJOWPLF w୹͘͢ΔϨγʔόʔࢦఆMBNCEB w࠷ޙͷҾ਺ͷ৔߹͸ ΛলུՄೳ w୹͘͢Δ&YUFOTJPOT'VODUJPOTPS1SPQFSUJFT wӳޠͬΆ͍จ๏ʹJOpY ͳΜͰ΋͍͍͔ΒɺDSLͷαϯϓϧΛ࡞ͬͯΈΑ͏ Kotlinྗ͕ඈ༂తʹΞοϓ͠·͢ʂ

Slide 41

Slide 41 text

"OESPJEͰ,PUMJOͷྗΛղ͖์ͭϨγϐ  DI Container (Dependency Injection Container)

Slide 42

Slide 42 text

೔ຊޠ8JLJQFEJBͩͱʜ  lґଘੑͷ஫ೖʢ͍ͦΜ͍ͤͷͪΎ͏ʹΎ͏ɺӳ %FQFOEFODZJOKFDUJPOʣͱ͸ɺίϯϙʔωϯτؒͷ ґଘؔ܎ΛϓϩάϥϜͷιʔείʔυ͔Βഉআ͠ɺ֎෦ ͷઃఆϑΝΠϧͳͲͰ஫ೖͰ͖ΔΑ͏ʹ͢Διϑτ΢Σ ΞύλʔϯͰ͋Δɻz 8JLJQFEJBґଘੑͷ஫ೖ

Slide 43

Slide 43 text

೔ຊޠ8JLJQFEJBͩͱʜ  lґଘੑͷ஫ೖʢ͍ͦΜ͍ͤͷͪΎ͏ʹΎ͏ɺӳ %FQFOEFODZJOKFDUJPOʣͱ͸ɺίϯϙʔωϯτؒͷ ґଘؔ܎ΛϓϩάϥϜͷιʔείʔυ͔Βഉআ͠ɺ֎෦ ͷઃఆϑΝΠϧͳͲͰ஫ೖͰ͖ΔΑ͏ʹ͢Διϑτ΢Σ ΞύλʔϯͰ͋Δɻz 8JLJQFEJBґଘੑͷ஫ೖ ґଘੑͷ஫ೖʁ

Slide 44

Slide 44 text

ӳޠ൛8JLJQFEJBͩͱʜ  l*OTPGUXBSFFOHJOFFSJOH EFQFOEFODZ JOKFDUJPOJTBUFDIOJRVFXIFSFCZPOFPCKFDU TVQQMJFTUIFEFQFOEFODJFTPGBOPUIFSPCKFDU "EFQFOEFODZJTBOPCKFDUUIBUDBOCFVTFE B TFSWJDF z 8JLJQFEJB%FQFOEFODZJOKFDUJPO

Slide 45

Slide 45 text

ӳޠ൛8JLJQFEJBͩͱʜ  l*OTPGUXBSFFOHJOFFSJOH EFQFOEFODZ JOKFDUJPOJTBUFDIOJRVFXIFSFCZPOFPCKFDU TVQQMJFTUIFEFQFOEFODJFTPGBOPUIFSPCKFDU "EFQFOEFODZJTBOPCKFDUUIBUDBOCFVTFE B TFSWJDF z 8JLJQFEJB%FQFOEFODZJOKFDUJPO dependency͸ΦϒδΣΫτ ΦϒδΣΫτͷ஫ೖ

Slide 46

Slide 46 text

Πϝʔδ͠Α͏  DIͬΆ͍ͷ͸Ͳͬͪʁ ۩ࡐɺຯΛௐ੔ɺม͑΍͍͢ͷ͸

Slide 47

Slide 47 text

Πϝʔδ͠Α͏  DIͬΆ͍ͷ͸Ͳͬͪʁ ۩ࡐɺຯΛௐ੔ɺม͑΍͍͢ͷ͸

Slide 48

Slide 48 text

ιʔείʔυͩͱ  class FriedRice val friedRice = FriedRice() class BowlOFRice(val rice: Rice, val topping: Topping) interface Topping interface Rice class JapaneseRice : Rice class BeefTopping : Topping //オブジェクトを入れる val beefBowl = BowlOFRice(JapaneseRice(), BeefTopping()) ※ઃܭ࣍ୈͰνϟʔϋϯ΋DIԽͰ͖·͢

Slide 49

Slide 49 text

%*ͷࢫຯɿมߋʹڧ͍  ஫ೖ͞ΕΔ΋ͷ͸ΦϒδΣΫτ͕ͩ
 ΠϯλʔϑΣʔεʢ࢓༷ʣʹґଘͨ͠΄͏͕ΑΓॊೈ wڇက͡Όͳͯ͘ɺ;Γ͔͚ကͰ΋໰୊ͳ͠ wܧঝͰͳ͘ɺ࢓༷ʹґଘ͍ͯ͠ΔͨΊՄೳ wςετ ຯݟ ͷͱ͖ʹϥΠεΛϞοΫʹ͢Δ͜ͱͰɺ
 ຯݟՄೳ

Slide 50

Slide 50 text

%*  DI Container (Dependency Injection Container)

Slide 51

Slide 51 text

%*ͱ%*$POUBJOFS  %*$POUBJOFS͸
 %*Λ࣮ݱ͢ΔͨΊͷศརπʔϧͰ͔͠ͳ͍ wઌఔͷઆ໌Ͱ%BHHFSͳͲͰ͖ͯ·͔ͨ͠ʁ class BowlOFRice(val rice: Rice, val topping: Topping) //オブジェクトを入れる val beefBowl = BowlOFRice(JapaneseRice(), BeefTopping())

Slide 52

Slide 52 text

%*$POUBJOFSͷࢫຯ  ࠷େͷϞνϕʔγϣϯɿΊΜͲ͏͍͘͞ w͍͍ͪͪΦϒδΣΫτ࡞੒͢Δͷ͕໘౗ w౎౓OFX͢Δඞཁ͕ͳ͘࢖͍·Θ͍ͨ͠ w஫ೖ͢ΔΦϒδΣΫτΛมߋ͢Δ࣌ʹɺ
 ͢΂ͯม͑Δͷ໘౗ ґଘؔ܎Λهड़ͨ͠Β উखʹੜ੒ɺ஫ೖͯ͘͠ΕͨΒ͍͍ͷʹ

Slide 53

Slide 53 text

%*$POUBJOFSͷࢫຯ  ࠷େͷϞνϕʔγϣϯɿΊΜͲ͏͍͘͞ w͍͍ͪͪΦϒδΣΫτ࡞੒͢Δͷ͕໘౗ w౎౓OFX͢Δඞཁ͕ͳ͘࢖͍·Θ͍ͨ͠ w஫ೖ͢ΔΦϒδΣΫτΛมߋ͢Δ࣌ʹɺ
 ͢΂ͯม͑Δͷ໘౗ ґଘؔ܎Λهड़ͨ͠Β উखʹੜ੒ɺ஫ೖͯ͘͠ΕͨΒ͍͍ͷʹ DI Container͞Μ͓ئ͍͠·͢

Slide 54

Slide 54 text

Πϝʔδ͠Α͏  ڇက DIίϯςφ ΅͘Β͸ڇကΛఆٛ

Slide 55

Slide 55 text

%*  DI Container? Service Locator?

Slide 56

Slide 56 text

4FSWJDF-PDBUPS  class FriedRice val friedRice = FriedRice() class BowlOFRice(val di: DIContainer){ @Inject lateinit var rice: Rice @Inject lateinit var topping: Topping init{ di.inject() } } //オブジェクトを入れる val beefBowl = BowlOFRice(di) ※ઃܭ࣍ୈͰνϟʔϋϯ΋DIԽͰ͖·͢

Slide 57

Slide 57 text

4FSWJDF-PDBUPS  ґଘؔ܎ͷهड़͕ΊΜͲ͘ͳͬͯ4FSWJDF-PDBUPSʹ
 ͯ͠͠·͏ w͋ΕʁͦͷΦϒδΣΫτͬͯ
 %*$POUBJOFSͬͯؔ܎͋Γ·͚ͨͬ͠ʁ wςετ͢Δͱ͖ʹ%*$POUBJOFS͕ͳ͍ͱςετͰ͖ͳ͍ w୯७ʹ%*$POUBJOFS෼ͷґଘؔ܎͕૿͑ͯ͠·ͬͨ w͜Ε͔Β঺հ͢Δ%*$POUBJOFS͸
 4FSWJDF-PDBUPSͱͯ͠ѻ͍΍͍͢ͷͰ஫ҙ͕ඞཁ

Slide 58

Slide 58 text

%*  Android DI: Dagger2?

Slide 59

Slide 59 text

%*ͷ֓೦ͷΘΓʹෳࡶ  wίϯϙʔωϯτɺαϒίϯϙʔωϯτɺϞδϡʔϧɺείʔ ϓΛద੾ʹఆٛ͢Δͷେม w%*ͷྖҬ͔Β"OESPJEྖҬʹ౿ΈࠐΜͰ͖͍ͯΔ w"DUJWJUZ 'SBHNFOU͕ੜ੒͞ΕͨޙɺͰ͔ࠩ͠͠ࠐΊͳ͍΋ ͷఆ͕ٛ໘౗ wLBQUͱ%BHHFSͱͷ૬ੑ͕ѱ͍ wLWTTDIFNBͳͲͰ࡞ΒΕΔΫϥεΛ1SPWJEFSͰ͖ͳ͍ɻʢ)PMEFS ࡞Ε͹Մೳʣ

Slide 60

Slide 60 text

,PUMJOͳΒҧ͏ํ๏͕͋Δ͔΋  %FMFHBUJPOɺ%FMFHBUFE1SPQFSUJFTΛ࢖͑͹΋ͬ ͱ͏·͘Ͱ͖Δ͔΋ class Delegate {
 operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
 return "$thisRef, thank you for delegating '${property.name}' to me!"
 }
 
 operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
 println("$value has been assigned to '${property.name} in $thisRef.'")
 }
 } 
 class Example {
 var hoge: String by Delegate()
 }

Slide 61

Slide 61 text

%*  Kotlin + Android DI: Kodein

Slide 62

Slide 62 text

,PEFJO  w,PUMJO੡ wLBQUΛ࢖Θͳ͍ͷͰɺϏϧυ஗͘ͳΒͳ͍ w,PUMJOͷػೳΛ͏·͘࢖ͬͯΔ w%FMFHBUJPOΛ࢖ͬͯɺ͏·͘஫ೖ͍ͯ͠Δ w௚ײతͳจ๏ SalomonBrys/KodeinͷREADME.mdΑΓ

Slide 63

Slide 63 text

,PEFJO͕Ͱ͖Δ͜ͱ  w -B[JMZJOTUBOUJBUFZPVSEFQFOEFODJFTXIFOOFFEFE w 4UPQDBSJOHBCPVUEFQFOEFODZJOJUJBMJ[BUJPOPSEFS w &BTJMZCJOEDMBTTFTPSJOUFSGBDFTUPUIFJSJOTUBODFPS QSPWJEFS w &BTJMZEFCVHZPVSEFQFOEFODZCJOEJOHTBOE SFDVSTJPOT SalomonBrys/KodeinͷREADME.mdΑΓ

Slide 64

Slide 64 text

,PEFJO͕Ͱ͖Δ͜ͱ  w -B[JMZJOTUBOUJBUFZPVSEFQFOEFODJFTXIFOOFFEFE w 4UPQDBSJOHBCPVUEFQFOEFODZJOJUJBMJ[BUJPOPSEFS w &BTJMZCJOEDMBTTFTPSJOUFSGBDFTUPUIFJSJOTUBODFPS QSPWJEFS w &BTJMZEFCVHZPVSEFQFOEFODZCJOEJOHTBOE SFDVSTJPOT SalomonBrys/KodeinͷREADME.mdΑΓ •ඞཁͳ࣌ʹΠϯελϯεԽ •providerʹ
 ΫϥεɺΠϯλʔϑΣʔεɺΠϯελϯεΛઃఆͰ͖ΔΑ

Slide 65

Slide 65 text

.PEVMFఆٛ  Kodein.Module { bind<型>(Qualifier) with singleton { … } bind<型>(Qualifier) with provider { … } bind<型>(Qualifier) with instance ( … ) } • Dagger2ͷModuleͱಉ͡ • KotlinͷػೳΛϑϧʹ࢖͍ͬͯͯจ๏ͰಡΈ΍͍͢ • infixɺϥϜμলུɺϨγʔόʔࢦఆϥϜμ

Slide 66

Slide 66 text

.PEVMFྫ  object NetworkModule { val module = Kodein.Module { bind() with singleton { OkHttpClient.Builder().build() } bind() with singleton { GsonConverterFactory.create() } bind() with singleton { Retrofit.Builder() .baseUrl(BuildConfig.GITHUB_ENDOPOINT) .addConverterFactory(instance()) .client(instance()).build() } } }

Slide 67

Slide 67 text

.PEVMFྫ  object NetworkModule { val module = Kodein.Module { bind() with singleton { OkHttpClient.Builder().build() } bind() with singleton { GsonConverterFactory.create() } bind() with singleton { Retrofit.Builder() .baseUrl(BuildConfig.GITHUB_ENDOPOINT) .addConverterFactory(instance()) .client(instance()).build() } } }

Slide 68

Slide 68 text

,PEFJOͷఆٛ  • Dagger2ͷComponentͱಉ͡ • ࢖༻͢ΔϞδϡʔϧΛఆٛ͢Δ class App : Application(), KodeinAware { override val kodein: Kodein = Kodein { bind() with instance(this@App) import(NetworkModule.module) import(PresentationModule.module) } }

Slide 69

Slide 69 text

*OKFDU  class MVPActivity : AppCompatActivity(), GithubView { val binding by lazy { DataBindingUtil.setContentView<…>(this, R.layout…) } val injector: KodeinInjector = KodeinInjector() val presenter: GithubPresenter by injector.instance() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) injector.inject(Kodein { extend(kodein) bind() with instance(this@MVPActivity) }) binding.searchBtn.setOnClickListener { presenter.search(binding.userEdit.text.toString()) } } }

Slide 70

Slide 70 text

%*  Dagger2 ͱ Kodein ൺֱ

Slide 71

Slide 71 text

%BHHFSͱ,PEFJO  ,PEFJO %BHHFS ґଘؔ܎Λ LBQUͰੜ੒ ෆཁ ඞཁ BQUͰੜ੒͞Εͨ΋ͷ JOKFDU ̋ ˚ )PMEFSΛ࡞ΔͳͲ޻෉͕ඞཁ ґଘؔ܎ͷ Τϥʔ ࣮ߦ࣌ ίϯύΠϧ࣌ είʔϓ ̋ ̋ /BNFE 2VBMJpFS ̋ ̋

Slide 72

Slide 72 text

ґଘؔ܎͕͓͔͍࣌͠ͷΤϥʔ  w%BHHFSͷ৔߹͸ɺίϯύΠϧ࣌ʹΤϥʔ wBQUͰੜ੒͢ΔͷͰɺґଘؔ܎͕͓͔͍͠৔߹ʹ͸ίϯύΠϧͰ͖ ·ͤΜ w,PEFJOͷ৔߹͸ɺ࣮ߦ࣌ʹΤϥʔ w.BQΈ͍ͨͳ΋ͷʹɺΦϒδΣΫτΛಥͬࠐΜͰऔΓग़ͯ͠Δ͚ͩ ͳͷͰɺJOKFDU͢Δͱ͖ʹͭͬ͜·Ε͍ͯΔͷ͔Ͳ͏͔͸ɺ࣮ߦ͞ ΕΔ·ͰΘ͔Βͳ͍ͨΊͰ͢

Slide 73

Slide 73 text

%*·ͱΊ  w%*πʔϧΛ%BHHFSҎ֎ͷબ୒΋͋Δ͔΋ w%FMFHBUJPOΛ࢖ͬͯ%*Λ࣮ݱͰ͖ͦ͏ w,PUMJO͕"OESPJE։ൃݴޠͱͯ͠ೖͬͨ͜ͱͰఆ൪ϥΠϒϥ Ϧͷมಈ͕͋Δ͔΋͠Εͳ͍ʜ

Slide 74

Slide 74 text

 KotlinͰշదAndroid։ൃΛʂ

Slide 75

Slide 75 text

No content