Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MVVMって何? というか…MV○丸ごと、何?

 MVVMって何? というか…MV○丸ごと、何?

shibuya.swift #4 (http://shibuya-swift.connpass.com/event/31031/)
で発表したスライドです。

もっと詳しいMVVMの話はこちら:
健康的なMVVM 書いてますか? ~MVVMアンチパターン集~
(https://speakerdeck.com/takasek/jian-kang-de-namvvm-shu-itemasuka-mvvmantipatanji)

704056da9a4c4e075ad14479beaebab7?s=128

takasek

June 08, 2016
Tweet

Transcript

  1. .77.ͬͯԿʁ
 ͱ͍͏͔ʜ.7˓ؙ͝ͱɺ Կʁ TIJCVZBTXJGU CZ

  2. !UBLBTFL w GSFFMBODFJ04&OHJOFFS w 'J/$͞ΜͰ͓࢓ࣄ͍͍ͤͯͨͩͯ͞·͢ w ɹ!UBLBTFL w ɹUBLBTFL w

    ɹUBLBTFL
  3. !UBLBTFL w /PUJGXJGU
 IUUQTHJUIVCDPNUBLBTFL/PUJGXJGU
 /4/PUJpDBUJPOͷVTFS*OGPΛ
 4XJGUZʹѻ͏ϚΠΫϩϥΠϒϥϦ w "DUJPO$MPTVSBCMF
 IUUQTHJUIVCDPNUBLBTFL"DUJPO$MPTVSBCMF
 UBSHFUBDUJPOΛ౉͢ॲཧΛ


    4XJGUZͳΫϩʔδϟͰॻ͚Δ
 ϚΠΫϩϥΠϒϥϦ (JU)VCͰ
 044ϥΠϒϥϦ΋࡞ͬͯ·͢
  4. .7$
 .71
 .77.

  5. .7˓͸ԿΛղܾ͠Α͏ ͱ͍ͯ͠Δ͔

  6. Ϗϡʔͱ
 ϏδωεϩδοΫͷ෼཭

  7. .7$ ݹయత.7$ 
 .7$.PEFM 
 ֦ு.7$ 
 ͦͷଞΦϨΦϨ.7$ʜ

  8. ݹయత.7$ͱ͸ ϊϧ΢ΣʔͷτΡϦάϰΟɾϦφΧ΢͞ΜʹΑͬ ͯ೥ʹߟҊ͞Εͨ $POUSPMMFSͱ7JFX͸ରԠ $POUSPMMFSͷ੹຿͸ɺ
 ɾೖྗͷड͚औΓ
 ɾଞͷϞδϡʔϧͷૢ࡞

  9. .PEFM $POUSPMMFS 7JFX ݹయత.7$ ೖྗ Φϒβʔόಉظ 4FQBSBUFE 1SFTFOUBUJPO ❌

  10. ݹయత.7$ͷ؊ w ෳ਺ͷϏϡʔ͕ΦϒβʔόɾύλʔϯͰಉ࣌ʹߋ ৽͞ΕΔ͜ͱ
 ʢ'PXMFSࢯ͍Θ͘ʮΦϒβʔόಉظʯʣ w ίϯτϩʔϥ͕ϏϡʔΛઈର৮Βͳ͍͜ͱ
 ʢ'PXMFSࢯ͍Θ͘ʮ෼཭ϓϨθϯςʔγϣϯʯʣ

  11. .PEFM $POUSPMMFS 7JFX ͪͳΈʹ.7$.PEFM XFCΞϓϦ ϦΫΤετ DMJFOU TFSWFS 1998೥ɺJSP(JavaServer Page)ͷ


    ࢓༷υϥϑτͰఏএ͞ΕͨΒ͍͠ MVCΛWebαʔϏεʹద༻ ObserverύλʔϯΛ
 ࢖Θͳ͍ (࢖͑ͳ͍)
  12. .7$ͷ໰୊ ϓϨθϯςʔγϣϯϩδοΫͷ ஔ͖৔͕ͳ͍
 UFYU$PMPS͸.PEFMʹஔ͘ʁ7JFXʹஔ͘ʁ 
 
 7JFXͷঢ়ଶΛ؅ཧͰ͖ͳ͍
 UFYUpFME͕ೖྗࡁͷͱ͖͚ͩԡͤΔϘλϯΈ͍ͨͳ 
 


    6*͕ϦονʹͳΔʹै͍ɺॏେͳ໰୊ʹʜ
  13. .7$ͷ໰୊ 6*ʹ͓͚Δೖྗͱग़ྗ͸
 ຊ࣭తʹ͸ෆՄ෼ʜʂ

  14. 7JFX .PEFM $POUSPMMFS ֦ு.7$ ೖྗ Φϒβʔόಉظ 4FQBSBUFE 1SFTFOUBUJPO ɹɹɹͱ͸ 7JFX

    $POUSPMMFS
  15. .7$ͱݴͬͯ΋ ༷ʑ

  16. .PEFM J04Ͱ͋Γ͕ͪͳ.7$ ೖྗ 7JFX $POUSPMMFS 7JFX 7JFX EFMFHBUF UPVDI &WFOU

    4FFBMTP
 ͜Ε͕࠷ڧͷ.7$ J04 IUUQRJJUBDPNLPJUBSPJUFNTCBGEGB
  17. ͦ͜Ͱ
 .71 छྨ͋Δ
 ؂ࢹίϯτϩʔϥ1BTTJWF7JFX

  18. 5BMJHFOUͱ͍͏04Ͱ࢖ΘΕ͍ͯͨΒ͍͠ ෳࡶͩͬͨͷͰ೥ࠒɺ
 %PMQIJO4NBMM5BTLνʔϜʹΑͬͯ
 ੔ཧ͞ΕͨΒ͍͠ .71 ؂ࢹίϯτϩʔϥ ͷྺ࢙ ڞಉ։ൃʂ

  19. 7JFX .PEFM 1SFTFOUFS ೖྗ Φϒβʔόಉظ .71 ؂ࢹίϯτϩʔϥ CͰ͸ͳ͘
 Vͷ੹຿ ໾ׂ


    ɾೖྗΛModelʹ౉͢
 ɾPresentation Logic ͜͜͸ݹయతMVCͱಉ͡
 ςετͮ͠Β͍໰୊͸͋Δ

  20. .PEFM 1SFTFOUFS 7JFX .71 1BTTJWF7JFX ೖྗ JOUFSGBDF ModelͱViewΛ
 ׬શʹ੾Γ཭ͨ͠ ඞͣ


    interfaceΛ௨͢
  21. Ҿ༻"SDIJUFDUJOH"OESPJEʜ5IFDMFBOXBZ 
 IUUQGFSOBOEPDFKBTDPNBSDIJUFDUJOHBOESPJEUIFDMFBOXBZ ΞʔΩςΫνϟ =֤ϨΠϠͷґଘΛ೗Կʹ੔ཧ͢Δ͔

  22. .PEFM 1SFTFOUFS 7JFX .71 1BTTJWF7JFX ͸
 ͲͷΑ͏ʹґଘΛ੔ཧ͔ͨ͠ JOUFSGBDF ґଘੑͷٯస %*1%FQFOEFODZ*OWFSTJPO1SJODJQMF

    
 ʹΑͬͯґଘΛҰํ௨ߦʹ
  23. .77.

  24. ೥ʹ+PTI4NJUIࢯ͕
 .4%/ϚΨδϯͰهࣄʹͨ͜͠ͱͰ޿·ͬͨ 81' 8JOEPXT1SFTFOUBUJPO'PVOEBUJPO ͷػೳ͕
 લఏͱͳ͍ͬͯΔ
 
 ɾ7JFX͸9".-ͰςϯϓϨʔτͱͯ͠એݴͰ͖Δ
 ɾ֤ίϯτϩʔϧ͸%BUB$POUFYUͱ͍͏ϓϩύςΟΛ࣋ͪ
 ɹσʔλόΠϯσΟϯάΛඪ४αϙʔτ

    .77.ͷྺ࢙
  25. .PEFM 7JFX.PEFM 7JFX %BUB #JOEJOH $PNNBOET .77. ೖྗ ɹσʔλόΠϯσΟϯάͷ࣮ݱͷͨΊʹ͸ɺJ04ͷ৔߹ ɹɹ'31ϥΠϒϥϦ

    3Y4XJGU 3FBDUJWF$PDPB ΍ ɹɹσʔλόΠϯσΟϯάϥΠϒϥϦ 4XJGU#POE ͷ ɹɹαϙʔτ͕ඞཁ ɹ ˞'J/$Ͱ͸ݱࡏ4XJGU#POEΛར༻
  26. όΠϯσΟϯάʹΑͬͯґଘΛҰํ௨ߦʹ 7JFXɹɹ7JFX.PEFM 7JFX.PEFMɹɹ.PEFM 7JFX.PEFM 7JFX σʔλόΠϯσΟϯά .77.͸
 ͲͷΑ͏ʹґଘΛ੔ཧ͔ͨ͠

  27. .77.ʹΑͬͯ
 Կ͕खʹೖΔͷ͔ ɾ୯ํ޲ͷґଘؔ܎
 ɾ୯ํ޲ͷॲཧϑϩʔ
 ɾϏδωεϩδοΫͱ
 ɹϓϨθϯςʔγϣϯͷ෼཭
 ɾUFTUBCJMJUZ

  28. جຊɺ
 7JFXˠ7JFX.PEFM͸ίϚϯυΛୟ͚ͩ͘ 7JFX.PEFMˠ7JFX͸όΠϯυ͢Δ͚ͩ 7JFX.PEFM 7JFX %BUB #JOEJOH $PNNBOET ᶃίϚϯυ ᶄঢ়ଶมߋ

    ᶅঢ়ଶ൓ө †એݴతʹهड़
  29. class MyViewModel { weak var view: MyView? func doSomething(fuga: Fuga)

    { guard let view = view else { return } if view.isHoge { view.doSomething(fuga) } } } class MyView { func awakeFromNib() { viewModel.view = self } } ୯ํ޲ͷґଘؔ܎ ❌ ϨΠϠͷґଘؔ܎͕͓͔͍͠ɻ
 7.͕7JFXΛ஌ͬͯ͠·͍ͬͯΔ
  30. class MyViewModel { let fuga = Observable<Fuga?>(nil) func didReceiveFuga(fuga: Fuga)

    { self.fuga.value = fuga } } class MyView { func awakeFromNib() { viewModel.fuga.ignoreNil().observe { [weak self] in self?.doSomething($0) } } } ୯ํ޲ͷґଘؔ܎
  31. ୯ํ޲ͷॲཧϑϩʔ 7JFX.PEFM΁ͷίϚϯυ͕
 ɹॲཧͷ׬ྃ࣌ʹ࣮ߦ͢ΔΫϩʔδϟΛड͚ͨΓ class MyView { func awakeFromNib() { viewModel.alertMessage.observe

    { [weak self] in self?.showAlert($0) // ↓Ͳ͕ͬͪຊے!? } } func didTapButton() { viewModel.doSomething(completion: { [weak self] alertMessage in self?.showAlert(alertMessage) // ↑Ͳ͕ͬͪຊے!? }) } } ˠॲཧͷྲྀΕ͕ΧΦεʹʂ BMFSU.FTTBHF 0CTFSWBCMF4USJOH͕ มߋ͞ΕͨΒൃಈ ͳΜ͔΍ͬͨ݁Ռ BMFSU.FTTBHFΛ ड͚औΔ ❌
  32. class MyView { var viewType: ViewType func setup(viewType: ViewType) {

    self.viewType = viewType switch viewType { case .Title: viewModel.title.observe { ... } case .Image: viewModel.image.observe { ... } case .Detail: viewModel.detail.observe { ... } } } } ϏδωεϩδοΫͱϓϨθϯςʔγϣϯͷ෼཭ 7JFXଆʹঢ়ଶ΍৚݅෼ذ͕͋Δ ❌
  33. ʮ7JFX͸7JFX.PEFMͷӨʯΛ పఈͤ͞Δ class MyView { func awakeFromNib() { viewModel.title.observe {

    ... } viewModel.image.observe { ... } viewModel.detail.observe { ... } } } 7JFX͸Կ΋൑அΛߦΘͣɺ 7JFX.PEFMͷঢ়ଶΛ ໧ʑͱ6*ʹ൓өͤ͞Δ 7JFX.PEFM͸ɺ 7JFXΛ࠶ߏ੒Ͱ͖Δ͚ͩͷ ঢ়ଶ৘ใΛอ࣋͢Δ ϏδωεϩδοΫͱϓϨθϯςʔγϣϯͷ෼཭
  34. ͦ΋ͦ΋7JFX.PEFM͸.PEFMͷӨͳͷͰ͢ɻ
 ͦͯ͠·ͨ7JFX͸7JFX.PEFMͷӨͰ΋͋Γ·͢ɻ Ҿ༻.77.ͷ.PEFMʹ·ͭΘΔޡղUIFTFBPGGFSUJMJUZ IUUQVHBZBIBUFCMPKQFOUSZNPEFMNJTUBLF

  35. .77.ʹΑͬͯ
 Կ͕खʹೖΒͳ͍ͷ͔ ɾυϝΠϯ૚Πϯϑϥ૚ͷ෼཭
 ɾը໘ભҠͳͲɺෳ਺ը໘ͷڠௐ

  36. ;ͨͨͼҾ༻"SDIJUFDUJOH"OESPJEʜ5IFDMFBOXBZ 
 IUUQGFSOBOEPDFKBTDPNBSDIJUFDUJOHBOESPJEUIFDMFBOXBZ .77.͸ ΞʔΩςΫνϟશମΛΧόʔͰ͖Δ֓೦Ͱ͸ͳ͘ ද૚෦෼ͷ࣮૷ʹա͗ͳ͍

  37. ❌ 7JFX.PEFM͕
 ɹ ɹ௨৴ॲཧ
 ɹσʔλΩϟογϡ
 ɹ͞·͟·ͳۀ຿ͷϋϯυϦϯά 
 ɹʜΛߦ͍ͬͯΔ

  38. .PEFM૚Λ͔ͬ͠Γ࡞Ζ͏ .PEFM%"0 %BUB"DDFTT0CKFDU Ͱ͸ͳ͍ .PEFMۀ຿ϩδοΫ ඇ6*,JUͷผϓϥοτϑΥʔϜʹҠ২ͯ͠΋มΘΒͳ͍෦෼ Α͘7JFX$POUSPMMFSʹߦ͘Β͍ॻ͔ΕͯΔ΍ͭ ͋Ε͸΄ͱΜͲ.PEFMʹॻ͘΂͖΋ͷ

  39. ΑΓΑ͍.77.ͷͨΊʹ IUUQCJUMZ1&BC,