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

Androidアプリの 安全なリファクタリングを行うパターン集

Androidアプリの 安全なリファクタリングを行うパターン集

DroidKaigi 2021 Day1
2021/10/19

HiroYUKI Seto

October 19, 2021
Tweet

More Decks by HiroYUKI Seto

Other Decks in Programming

Transcript

  1. גࣜձࣾϊϋφɹ੉ށ༏೭
    "OESPJEΞϓϦͷ
    ҆શͳϦϑΝΫλϦϯάΛߦ͏ύλʔϯू

    View full-size slide

  2. )JSP:6,*4FUP
    גࣜձࣾϊϋφ
    .PCJMF5FDI-FBE
    "OESPJE&OHJOFFS
    !TFUP@IJ
    !IJSPZVLJTFUP

    View full-size slide

  3. w ίʔυϕʔεͷ࡮৽ํ๏ൺֱ
    w ϑϧεΫϥονͱϦϑΝΫλϦϯά
    w ϦϑΝΫλϦϯάͰى͜Γ͕ͪͳ໰୊ͱରࡦ
    w ҆શͳϦϑΝΫλϦϯάͱ͸
    w .7$ΞϓϦͷ҆શͳϦϑΝΫλϦϯά
    ΞδΣϯμ

    View full-size slide

  4. w ඞͣϦϑΝΫλϦϯάͰίʔυΛ௚ͤʂͱ͸ࢥ͍ͬͯͳ͍
    w ϝϦοτσϝϦοτΛߟ͑Δ΂͖
    w ؀ڥɾ৔໘ʹΑͬͯҟͳΔ
    w εΫϥονͱϦϑΝΫλϦϯάͷ૊Έ߹Θͤ΋˕
    w ࠓճ͸ϦϑΝΫλϦϯάͷࣦഊΛݮΒ͢ϙΠϯτͷ঺հ
    w ઈରʹࣦഊ͠ͳ͘ͳΔํ๏͸ͳ͍
    ͸͡Ίʹ

    View full-size slide

  5. w ςετΛॻ͜͏
    w ഁյతมߋͨ͠Βͦͷ෦෼Λݕূ͠Α͏
    ൃදͷཁ໿

    View full-size slide

  6. ίʔυϕʔεͷ࡮৽ํ๏ൺֱ

    View full-size slide

  7. w طଘίʔυΛࣺ͔ͯͯΒཧ૝ܕʹॻ͖௚͢
    w ˓͕͠ΒΈ͕ͳ͘։ൃ଎౓΋ग़΍͍͢
    w ˚৽نόάΛ࢓ࠐΉՄೳੑ
    w ˚ݱߦ࢓༷͕೺ѲͰ͖͍ͯͳ͍ͱ೉͍͠
    w ࢓༷Λ֬ೝ͢Δ͕࣌ؒඞཁ
    w ҙਤ͠ͳ͍σάϨͷՄೳੑ
    ϑϧεΫϥον

    View full-size slide

  8. w طଘίʔυΛॻ͖׵͑ͯཧ૝ܕʹ͍࣋ͬͯ͘
    w ˓࢓༷Λ೺Ѳ͍ͯ͠ͳͯ͘΋Ͱ͖Δ
    w ϦϑΝΫλͯ͠ίʔυ͔Β࢓༷ΛಡΈղ͘
    w ˚৽نόάطଘόάʹۤ͠ΉՄೳੑ
    w ˚طଘ࣮૷ʹҾͬுΒΕͯ։ൃ଎౓͕ग़ͳ͍Մೳੑ
    ϦϑΝΫλϦϯά

    View full-size slide

  9. ൺֱද

    ϑϧεΫϥον ϦϑΝΫλϦϯά
    ޻਺ɾ։ൃ଎౓
    ޻਺গ
    ։ൃ଎౓˓
    ޻਺ଟ
    ։ൃ଎౓˚
    ࢓༷ҡ࣋
    ˚

    ҙਤ͠ͳ͍σάϨΛ͢ΔՄೳੑ
    ˓
    όά ΤϯόάͷՄೳੑ
    Τϯόά

    طଘόάΛܧଓͷՄೳੑ
    ͦͷଞ ݱঢ়࢓༷Λ೺Ѳ͍ͯ͠ͳ͍ͱ೉ ࣮૷͠ͳ͕Β࢓༷೺Ѳ͔Մ

    View full-size slide

  10. ϦϑΝΫλϦϯάͰ
    ى͜Γ͕ͪͳ໰୊ͱରࡦ

    View full-size slide

  11. w ֎෦ಈ࡞࢓༷Ϣʔβʔʹݟ͑Δಈ࡞
    w ඇഁյతมߋ
    w ಺෦ಈ࡞ʹ΋Өڹ͕ͳ͍ϝιου΍Ϋϥεͷ੔ཧ
    w ഁյతมߋ
    w ಺෦ಈ࡞͸มΘ͕ͬͨ֎෦ಈ࡞࢓༷͸มΘ͍ͬͯͳ͍৔߹
    w ྫɿΞϧΰϦζϜมߋɺ+TPO1BSTFSมߋ
    w ಺෦ಈ࡞΋֎෦ಈ࡞࢓༷΋มΘΔ৔߹
    w ྫɿ࢓༷มߋɺϥΠϑαΠΫϧมߋɺϝϞϦϦʔΫमਖ਼
    ඇഁյతมߋഁյతมߋ

    View full-size slide

  12. w ͱʹ͔͘طଘಈ࡞͕յΕΔ
    w ͪΐͬͱม͚͑ͨͩͳͷʹյΕͨ
    w յΕͳ͍͸ͣͷमਖ਼ͰյΕͨ
    w ૝ఆ֎ͷ෦෼͕ಈ͔ͳ͘ͳͬͨ
    ى͜Γ͕ͪͳ໰୊

    View full-size slide

  13. w ૝ఆ͍ͯ͠ͳ͍ഁյతมߋ
    w ϦϑϨΫγϣϯɺੜ੒ίʔυͷࢀর
    w ϥΠϒϥϦͷΞοϓσʔτ
    w $IBOHFMPHʹͳ͍मਖ਼
    w ଞΞϓϦ΍'SBNFXPSLͱͷ࿈ܞ
    w ݕূ͕೉͍͠໰୊
    w ϥΠϑαΠΫϧɺඇಉظॲཧ
    w ෳ߹తͳཁҼ
    ૝ఆ֎ͷݪҼ

    ରࡦ͸೉͍͠

    View full-size slide

  14. w ݕূΛखް͘΍Ε͹໰୊͸ग़ʹ͘͘ͳΔ
    w 㱻ݕূϦιʔε͕ඞཁʹͳΔ
    w ഁյతมߋʹΑͬͯಈ࡞͕յΕ͍ͯΔ
    w ඇഁյతมߋͰ͸ಈ࡞͸มΘΒͳ͍
    w ݕূΛബͯ͘͠΋໰୊͸ग़ʹ͍͘͸ͣ
    w ഁյతมߋΛݕূ͢Ε͹໰୊͕ݟ͔ͭΓ΍͍͢͸ͣ
    w ಺෦ಈ࡞͕ҙਤͨ͠௨Γ
    w ֎෦ಈ࡞࢓༷͕ҙਤͨ͠௨Γ
    ݪҼ෼ੳͱରࡦ

    View full-size slide

  15. w ഁյతมߋඇഁյతมߋΛ໌֬ʹ͢Δ
    w मਖ਼ޙͷಈ࡞ΛݕূͰ͖Δঢ়ଶʹ͢Δ
    w ՄೳͳݶΓࣗಈςετͰݕূ͢Δ
    w ഁյతมߋΛͨ͠఺Λݕূ͢Δ
    w ಺෦ಈ࡞͕ҙਤͨ͠΋ͷͰ͋Δ͜ͱ
    w ಺෦ಈ࡞Λม͑ͯ΋֎෦ಈ࡞࢓༷͕ಉҰͰ͋Δ͜ͱ
    w ֎෦ಈ࡞࢓༷͕ҙਤͨ͠΋ͷͰ͋Δ͜ͱ
    ҆શͳϦϑΝΫλϦϯά

    View full-size slide

  16. w ҆શͳϦϑΝΫλϦϯάͷͨΊʹܭըΛཱͯΔ
    w ணखલʹΰʔϧ·ͰͷεςοϓΛ෼ׂ͢Δ
    w ΰʔϧ΁ͷํ޲ੑ͕ͳ͍ঢ়ଶͰ͸໎૸͕ͪ͠
    w ഁյతมߋඇഁյతมߋΛࠞͥͳ͍
    w εςοϓͷഁյతมߋΛগͳ͘͢Δ
    w ݕূΛ؆୯ʹ͢ΔͨΊ
    εςοϓ෼ׂ

    View full-size slide

  17. w ✅ͦͷεςοϓʹΑͬͯݕূ͕Ͱ͖ΔΑ͏ʹͳΔ͔
    w ✅ഁյతมߋ͔
    w ✅Ͳ͕͜ഁյతมߋ͔
    w ✅ഁյతมߋʹݕূํ๏͕͋Δ͔
    εςοϓ෼ׂνΣοΫϙΠϯτ

    View full-size slide

  18. w 㲈ςετ͕ॻ͚ΔΑ͏ʹͳΔ͔
    w ϦϑΝΫλϦϯά͢ΔͳΒ͹໨ࢦ͢΂͖ΰʔϧ
    w ࣗಈςετͰಈ࡞อূͰ͖Ε͹खಈͷݕূίετ͕ݮΔ
    w मਖ਼ͨ͠ίʔυ͕ҙਤͨ͠ಈ࡞Λ͍ͯ͠Δ͔ͷݕূ
    w ඇഁյతมߋͳΒ͹ಈ࡞ʹมߋ͸ͳ͍͸ͣ
    w ݕূΛ௥Ճͤͣ໨ઌͷ։ൃ଎౓ΛٻΊΔ͜ͱ΋Մ
    ✅ݕূ͕Ͱ͖ΔΑ͏ʹͳΔ͔

    View full-size slide

  19. w ಈ࡞͕มΘͬͨ఺͕͋Δ͔
    w ಺෦ಈ࡞͸มΘ͕ͬͨ֎෦ಈ࡞࢓༷͸มΘ͍ͬͯͳ͍৔߹
    w ಺෦ಈ࡞΋֎෦ಈ࡞࢓༷΋มΘΔ৔߹
    ✅ഁյతมߋ͔

    View full-size slide

  20. w ಺෦࣮૷
    w εΫϥον։ൃ
    w ΞϧΰϦζϜมߋ
    w ґଘϥΠϒϥϦมߋ
    w +BWBˠ,PUMJOͷOVMMBCJMJUZ
    w ֎෦ಈ࡞࢓༷
    w "OESPJEͷϥΠϑαΠΫϧมߋ
    w ΞϓϦͷ࢓༷
    ✅Ͳ͕͜ഁյతมߋ͔

    View full-size slide

  21. w ಺෦ಈ࡞͸มΘ͕ͬͨ֎෦ಈ࡞࢓༷͸มΘ͍ͬͯͳ͍৔߹
    w มߋલͱมߋޙͷಈ࡞͕ಉҰͰ͋Δ͜ͱͷݕূ
    w ಺෦ಈ࡞΋֎෦ಈ࡞࢓༷΋มΘΔ৔߹
    w ҙਤ௨Γಈ͘͜ͱͷݕূ
    w ݕূํ๏
    w ࣗಈςετ 6OJU5FTUɺ6*5FTUɺ7JTVBM3FHSFTTJPO5FTU

    w खಈςετͰͷݕূɺ2"Ͱͷݕূ
    w શͯͷมߋΛݕূ͢Δͷ͸ෆՄ
    ✅ഁյతมߋʹݕূํ๏͕͋Δ͔

    View full-size slide

  22. w ૝ఆ͍ͯ͠ͳ͍ഁյతมߋ
    w ϦϑϨΫγϣϯɺੜ੒ίʔυͷࢀর
    w ϥΠϒϥϦͷΞοϓσʔτ
    w $IBOHFMPHʹͳ͍मਖ਼
    w ଞΞϓϦ΍'SBNFXPSLͱͷ࿈ܞ
    w ݕূ͕೉͍͠໰୊
    w ϥΠϑαΠΫϧ
    w ෳ߹తͳཁҼ
    ૝ఆ֎ͷݪҼ

    ରࡦ͸೉͍͠

    View full-size slide

  23. w ϦΞʔΩςΫνϟͷࡍ

    "OESPJEͰ͸σʔλ૚͔Βணख͢Δͱྑ͍
    εςοϓ෼ׂUJQT

    ݹ͍%BUB૚
    ৽͍͠6*૚
    ݺͼग़͠
    ෆ҆ఆͳ݁Ռ
    ѻ͍ʹ͍͘ܕ
    ෆ҆ఆͳ݁Ռ
    Λߟྀ࣮ͨ͠૷

    View full-size slide

  24. w ϦΞʔΩςΫνϟͷࡍ

    "OESPJEͰ͸σʔλ૚͔Βணख͢Δͱྑ͍
    εςοϓ෼ׂUJQT

    ৽͍͠%BUB૚
    ݹ͍6*૚
    ݺͼग़͠
    ҆ఆͨ݁͠Ռ
    6*૚࡮৽ͷࡍ
    ҆ఆ࣮ͨ͠૷

    View full-size slide

  25. .7$ΞϓϦͷϦϑΝΫλϦϯά

    View full-size slide

  26. w IUUQTHJUIVCDPNIJSPZVLJTFUPESPJELBJHJTBNQMF
    w NBJO͕ݩͷίʔυ
    w ϦϑΝΫλϦϯάͨ͠΋ͷͰ13
    w ϘλϯΛԡ͢ͱ௨৴ͯ͠

    3FTQPOTF$PEFΛදࣔ
    αϯϓϧϦϙδτϦ

    View full-size slide

  27. αϯϓϧίʔυ

    ελʔτ ΰʔϧ
    ΞʔΩςΫνϟ .7$
    .77.

    3FDPNNFOEFE"QQ"SDI
    7JFXૢ࡞ "DUJWJUZͰૢ࡞
    %BUB#JOEJOH
    ""$7JFX.PEFM-JWF%BUB
    ௨৴ॲཧ "DUJWJUZʹ΂ͨॻ͖ 3FNPUF%BUBTPVSDF
    ඇಉظॲཧ "TZOD5BTL %FQSFDBUFE
    $PSPVUJOF

    View full-size slide

  28. w IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLHVJEFSFDPNNFOEFEBQQBSDI
    3FDPNNFOEFE"QQ"SDIJUFDUVSF

    View full-size slide

  29. αϯϓϧίʔυ

    'SBHNFOU
    "TZOD5BTL
    8FCTFSWJDF
    'SBHNFOU
    7JFX.PEFM
    3FQPTJUPSZ
    3FNPUF%BUB4PVSDF
    8FCTFSWJDF
    -JWF%BUB
    ελʔτ ΰʔϧ

    View full-size slide

  30. αϯϓϧίʔυ ελʔτ

    'SBHNFOU

    View full-size slide

  31. 3FNPUF%BUBTPVSDFͷ࡞੒
    3FQPTJUPSZͷ࡞੒
    7JFX.PEFMͷಋೖ
    -JWF%BUBͷಋೖ
    .77.Խ
    $PSPVUJOFԽ
    εςοϓ෼ׂ

    View full-size slide

  32. 4UFQ3FNPUF%BUB4PVSDFͷ࡞੒

    'SBHNFOU
    "TZOD5BTL
    8FCTFSWJDF
    3FNPUF%BUB4PVSDF
    8FCTFSWJDF
    #FGPSF "GUFS
    'SBHNFOU
    "TZOD5BTL

    View full-size slide

  33. 4UFQ3FNPUF%BUB4PVSDFͷ࡞੒

    View full-size slide

  34. w ඇഁյతมߋ
    w ॲཧͷΫϥε੾Γग़͠ͷΈ
    w 0L)UUQ$MJFOUΛΫϥεม਺ʹ͕ͨ͠ɺ4UFQͷ࣮૷ͳΒඇഁյత
    w 3FNPUF%BUB4PVSDFͷΠϯελϯεΛ࢖͍ճ͢ͱഁյత
    4UFQ3FNPUF%BUB4PVSDFͷ࡞੒

    View full-size slide

  35. w ௨৴෦෼ͷ࣮૷͕ෛ࠴ͳ͜ͱ΋ଟʑ
    w ϦϑΝΫλ͢Δʹ͸
    w ςετΛॻ͍ͯϦΫΤετ΍ϨεϙϯεͷQBSTF݁ՌΛอূ͢Δ
    w ෛ࠴ΫϥεΛॻ͖׵͍͑ͯ͘
    w NPDLLͷTMPUΛ࢖ͬͯ௨৴पΓͷෛ࠴ղফͷϦϑΝΫλϦϯάΛ͢Δ
    w IUUQTRJJUBDPNIJSPZVLJTFUPJUFNTFFCGFG
    ༨ஊ௨৴෦෼΋ॻ͖׵͍͑ͨ

    View full-size slide

  36. ϒϥοΫϘοΫεͷ௚͠ํ

    ϒϥοΫϘοΫε
    ݺͼग़͠
    ݁Ռ
    8SBQQFSΫϥε
    ݺͼग़͠ ݺͼग़͠
    ݁Ռ
    ݁Ռ
    ςετͰอূ
    ςετ
    ݺͼग़͠
    ݁Ռ
    ྑ͍࣮૷
    ݺͼग़͠
    ݁Ռ
    "OESPJEςετશॻ1/FUXPSL6UJMTͷྫ

    View full-size slide

  37. 4UFQ3FQPTJUPSZͷ࡞੒

    3FQPTJUPSZ
    8FCTFSWJDF
    #FGPSF "GUFS
    'SBHNFOU
    "TZOD5BTL
    3FNPUF%BUB4PVSDF
    3FNPUF%BUB4PVSDF
    8FCTFSWJDF
    'SBHNFOU
    "TZOD5BTL

    View full-size slide

  38. 4UFQ3FQPTJUPSZͷ࡞੒

    View full-size slide

  39. w ඇഁյతมߋ
    w Ϋϥε੾Γग़͠ͷΈ
    w ݕূͷ௥Ճ
    w 6OJU5FTU͕ॻ͚ΔΑ͏ʹͳΔ
    4UFQ3FQPTJUPSZͷ࡞੒

    View full-size slide

  40. 4UFQ7JFX.PEFMͷಋೖ

    3FQPTJUPSZ
    8FCTFSWJDF
    #FGPSF "GUFS
    'SBHNFOU
    "TZOD5BTL
    3FNPUF%BUB4PVSDF
    3FQPTJUPSZ
    8FCTFSWJDF
    'SBHNFOU
    "TZOD5BTL
    3FNPUF%BUB4PVSDF
    7JFX.PEFM

    View full-size slide

  41. 4UFQ7JFX.PEFMͷಋೖ

    'SBHNFOU

    View full-size slide

  42. 4UFQ7JFX.PEFMͷಋೖ

    w ֎෦ಈ࡞࢓༷͸ಉҰͳഁյతมߋ
    w ճ໨ͷ࣮ߦ࣌ʹ3FQPTJUPSZ͕࢖͍ճ͞ΕΔ
    w ഁյతมߋͷݕূ
    w ճ໨ͷ࣮ߦ΋֎෦ಈ࡞࢓༷͕ಉҰͰ͋Δ͜ͱ
    w 6*5FTUɺखಈςετͳͲ
    w ʮճ໨ͷ࣮ߦͰ΋ҙਤͨ͠ಈ࡞ʯͷ6*5FTU͸ෆໟͳͷͰखಈ͕Α͍

    View full-size slide

  43. w ϦϑΝΫλϦϯάͷ్தͰઃܭͱͯ͠ඍົʹͳΔ͜ͱ΋
    w ʮݕূ͢ΔͨΊʯʮ࠷ऴతʹ៉ྷʹͳΔʯͱׂΓ੾Δ
    w தؒঢ়ଶͷ··Ͱ์ஔ͸ઈରʹආ͚Δ
    w ࠷ॳʹνʔϜϝϯόʔʹमਖ਼ํ਑Λڞ༗͢Δ
    ϙΠϯτதؒঢ়ଶΛݏ͕Βͳ͍

    View full-size slide

  44. 4UFQ-JWF%BUBͷಋೖ

    'SBHNFOU
    7JFX.PEFM
    3FQPTJUPSZ
    3FNPUF%BUB4PVSDF
    8FCTFSWJDF
    -JWF%BUB
    #FGPSF "GUFS
    3FQPTJUPSZ
    8FCTFSWJDF
    'SBHNFOU
    "TZOD5BTL
    3FNPUF%BUB4PVSDF
    7JFX.PEFM
    "TZOD5BTL

    View full-size slide

  45. 4UFQ-JWF%BUBͷಋೖ

    'SBHNFOU
    "TZOD5BTL 7JFX.PEFM

    View full-size slide

  46. w ֎෦ಈ࡞࢓༷΋มΘΔഁյతมߋ
    w PO4UBSUͱPO4UPQͷ͔ؒ͠6*͕൓ө͞Εͳ͍
    w ݕূͷ௥Ճ
    w 6OJUςετ
    w -JWF%BUBʹ஋͕ೖ͍ͬͯΔ͜ͱͷ֬ೝ
    w ഁյతมߋͷݕূ
    w खಈ֬ೝ
    w ࣗಈςετ͕೉͍͠ϥΠϑαΠΫϧؔ࿈
    4UFQ-JWF%BUBͷಋೖ

    View full-size slide

  47. w ֎෦࢓༷͸ಉҰͳഁյతมߋ
    w 7JFXͱͷ΍ΓͱΓ͕%BUB#JOEJOHܦ༝ʹ
    w ഁյతมߋͷݕূ
    w 6*5FTUJOH
    w .77.ԽલޙͰಉ͡6*ςετ͕ಈ࡞͢Δ͜ͱ
    w खಈςετ
    w 6*5FTUͰΧόʔ͖͠Εͳ͍෦෼
    4UFQ.77.Խ

    View full-size slide

  48. 4UFQ$PSPVUJOFԽ

    #FGPSF "GUFS
    'SBHNFOU
    7JFX.PEFM
    3FQPTJUPSZ
    3FNPUF%BUB4PVSDF
    8FCTFSWJDF
    -JWF%BUB
    'SBHNFOU
    7JFX.PEFM
    3FQPTJUPSZ
    3FNPUF%BUB4PVSDF
    8FCTFSWJDF
    -JWF%BUB
    "TZOD5BTL

    View full-size slide

  49. 4UFQ$PSPVUJOFԽ

    7JFX.PEFM

    View full-size slide

  50. w ֎෦࢓༷΋มΘΔഁյతมߋ
    w "TZOD5BTLˠ$PSPVUJOFͰඇಉظॲཧ͕ࠜຊ͔ΒมΘΔ
    w 7JFX.PEFMPO$MFBS 'SBHNFOUPO%FTUSPZ
    Ͱඇಉظॲཧऴྃ
    w "TZOD5BTL࣌୅ͷϝϞϦϦʔΫमਖ਼
    w ഁյతมߋͷݕূ
    w "TZOD5BTLΛ$PSPVUJOFʹஔ͖׵͑ͯ6OJU5FTU͕௨Δ͜ͱ
    w खಈςετϥΠϑαΠΫϧ PO%FTUSPZ

    4UFQ$PSPVUJOFԽ

    View full-size slide

  51. αϯϓϧίʔυ

    'SBHNFOU
    "TZOD5BTL
    8FCTFSWJDF
    'SBHNFOU
    7JFX.PEFM
    3FQPTJUPSZ
    3FNPUF%BUB4PVSDF
    8FCTFSWJDF
    -JWF%BUB
    #FGPSF "GUFS

    View full-size slide

  52. w 'SBNFXPSL΍ϥΠϒϥϦͷಈ࡞Λ஌Δ
    w ഁյతมߋΛݟམͱ͢Մೳੑ͕ݮΔ
    w "OESPJEͰ͸ಛʹϥΠϑαΠΫϧΛҙࣝ͢Δ
    w ಺෦࣮૷ΛಡΉͷ͕Φεεϝ
    ϙΠϯτಈ࡞Λ஌Δ

    View full-size slide

  53. w ΤϥʔΛચ͍ग़ͯ͠ॲཧํ๏ΛܾΊΔ
    w ϦΞʔΩςΫνϟͷࡍ͸ॲཧ͢Δ૚ΛܾΊΔ
    w IUUQTTQFBLFSEFDLDPNLHNZTIJOBOESPJEBQQFSSPSIBOEMJOH
    ϙΠϯτΤϥʔॲཧ

    View full-size slide

  54. w ܭըΛཱͯͯϦϑΝΫλϦϯάΛ͠Α͏
    w ςετΛॻ͜͏
    w ഁյతมߋͨ͠Βͦͷ෦෼Λݕূ͠Α͏
    ൃදͷཁ໿

    View full-size slide