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

読みやすいコードの書き方 第 3 回 / Code readability: Session 3 (ver. 2, Ja)

読みやすいコードの書き方 第 3 回 / Code readability: Session 3 (ver. 2, Ja)

第 3 回: コメント

---

セッションリスト

第 1 回: 導入と原則
- https://speakerdeck.com/munetoshi/code-readability-session-1-ver-2-ja

第 2 回: 命名
- https://speakerdeck.com/munetoshi/code-readability-session-2-ver-2-ja

第 3 回: コメント
- https://speakerdeck.com/munetoshi/code-readability-session-3-ver-2-ja

第 4 回: 状態
- https://speakerdeck.com/munetoshi/code-readability-session-4-ver-2-ja

第 5 回: 関数
- https://speakerdeck.com/munetoshi/code-readability-session-5-ver-2-ja

第 6 回: 依存関係 I
- https://speakerdeck.com/munetoshi/code-readability-session-6-ver-2-ja

第 7 回: 依存関係 II
- https://speakerdeck.com/munetoshi/code-readability-session-7-ver-2-ja

第 8 回: レビュー
- https://speakerdeck.com/munetoshi/code-readability-session-8-ver-2-ja

---

関連書籍 「読みやすいコードのガイドライン - 持続可能なソフトウェア開発のために」
- https://gihyo.jp/book/2022/978-4-297-13036-7

英語版のリスト: https://gist.github.com/munetoshi/65a1b563fb2c271f328c121a4ac63571#file-code-readability-links-md

以前のバージョン (英語): https://speakerdeck.com/munetoshi/code-readability

© 2019-2023 Munetoshi Ishikawa, supported by LINE corporation

Munetoshi Ishikawa

May 11, 2023
Tweet

More Decks by Munetoshi Ishikawa

Other Decks in Programming

Transcript

  1. /** ಡΈ΍͍͢ίʔυͷॻ͖ํ ୈ 3 ճ */
    // ίϝϯτ

    View Slide

  2. લճͷ͓͞Β͍: ໋໊
    ໊લ͸ਖ਼͔֬ͭઆ໌తʹ
    - ໊લͷࣔ͢಺༰: ʮ͍ͭɾͩΕʯΑΓʮԿʯ
    - จ๏: ॏཁͳ୯ޠͷҐஔ
    - ୯ޠ: ҙຯ͕ڱ͍ɾলུ͠ͳ͍ɾߠఆత

    View Slide

  3. ߨٛͷߏ੒
    - ಋೖͱݪଇ
    - ࣗવݴޠ: ໋໊, ίϝϯτ
    - ܕͷߏ଄: ঢ়ଶ, ؔ਺
    - ܕؒͷߏ଄: ґଘؔ܎I, ґଘؔ܎II
    - ϨϏϡʔ
    ίϝϯτ > ಋೖ

    View Slide

  4. ίϝϯτ
    ίʔυதʹॻ͔ΕΔ஫ऍɾઆ໌
    - ௨ৗɺίϯύΠϥ΍ΠϯλϓϦλ͔Β͸ແࢹ͞ΕΔ
    /**
    * Explanation of `fooFunction`...
    */
    fun fooFunction(parameter: Parameter /* note of the parameter */) {
    barFunction() // Explanation of why `barFunction` is called
    /* A comment with
    multiple lines. */
    ίϝϯτ > ಋೖ

    View Slide

  5. ίϝϯτͷ༗༻ੑ
    - ίʔυΛཧղ͠΍͘͢͢Δ
    - ϛεΛ๷͙
    - ϦϑΝΫλϦϯά͠΍͘͢͢Δ
    े෼ʹಡΈ΍͍͢ͳΒ͹ίϝϯτ͸ෆཁ
    (ίʔσΟϯάن໿ʹΑΔ)
    ίϝϯτ > ಋೖ

    View Slide

  6. ίϝϯτͷ༗༻ੑ
    - ίʔυΛཧղ͠΍͘͢͢Δ
    - ϛεΛ๷͙
    - ϦϑΝΫλϦϯά͠΍͘͢͢Δ
    े෼ʹಡΈ΍͍͢ͳΒ͹ίϝϯτ͸ෆཁ
    (ίʔσΟϯάن໿ʹΑΔ)
    ίϝϯτ > ಋೖ

    View Slide

  7. ίϝϯτʹΑΔϦϑΝΫλϦϯά: ྫ
    /**
    * Adds a new pair of keyword and the definition to this dictionary,
    * can be referenced by [getDefinition(String)].
    *
    * If the keyword is already registered, this registration fails.
    * Then, this returns a boolean representing whether the registration
    * succeeded.
    */
    fun add(newData: Pair): Boolean
    ಈ࡞ͷ୯७͞ͷׂʹ௕͍ίϝϯτ͕ඞཁ
    ίϝϯτ > ಋೖ

    View Slide

  8. ίϝϯτʹΑΔϦϑΝΫλϦϯά: ܭը
    ͳͥίϝϯτ͕௕͘ͳͬͨͷ͔Λߟ͑Δ
    վળҊ
    - ؔ਺໊ͷมߋ
    - ύϥϝʔλͷ෼ׂ
    - Τϥʔέʔεͷ୯७Խ
    - ෆཁͳ໭Γ஋ͷ࡟আ
    ίϝϯτ > ಋೖ

    View Slide

  9. ίϝϯτʹΑΔϦϑΝΫλϦϯά: ݁Ռ
    /**
    * Adds or overwrites a definition of a given [keyword].
    * The registered definition is obtained by [getDefinition(String)].
    */
    fun registerDefinition(keyword: String, definitionText: String)
    ಈ࡞ͷ୯७͞ʹݟ߹ͬͨίϝϯτΛॻ͘
    ίϝϯτ > ಋೖ

    View Slide

  10. ୅දతͳίϝϯτͷछྨ
    - υΩϡϝϯςʔγϣϯ: Ϋϥεɾؔ਺౳ʹॻ͘ܗࣜతͳίϝϯτ
    /**
    * A list of pairs of a string keyword and the explanation text.
    *
    * ... (details of usage, limitations, etc.)...
    */
    class Dictionary {
    ...
    }
    ίϝϯτ > ಋೖ

    View Slide

  11. ୅දతͳίϝϯτͷछྨ
    - υΩϡϝϯςʔγϣϯ: Ϋϥεɾؔ਺౳ʹॻ͘ܗࣜతͳίϝϯτ
    - ඇܗࣜతͳίϝϯτ: ίʔυதͷ༷ʑͳ৔ॴʹॻ͔ΕΔίϝϯτ
    // Call `toList` here to create a copied list explicitly.
    val listSnapshot = list.toList()
    ίϝϯτ > ಋೖ

    View Slide

  12. ୅දతͳίϝϯτͷछྨ
    - υΩϡϝϯςʔγϣϯ: Ϋϥεɾؔ਺౳ʹॻ͘ܗࣜతͳίϝϯτ
    - ඇܗࣜతͳίϝϯτ: ίʔυதͷ༷ʑͳ৔ॴʹॻ͔ΕΔίϝϯτ
    - To do ίϝϯτ:
    // TODO:
    ,
    // FIXME:
    ίϝϯτ > ಋೖ

    View Slide

  13. ୅දతͳίϝϯτͷछྨ
    - υΩϡϝϯςʔγϣϯ: Ϋϥεɾؔ਺౳ʹॻ͘ܗࣜతͳίϝϯτ
    - ඇܗࣜతͳίϝϯτ: ίʔυதͷ༷ʑͳ৔ॴʹॻ͔ΕΔίϝϯτ
    - To do ίϝϯτ:
    // TODO:
    ,
    // FIXME:
    - IDEɾίϯύΠϥɾίʔυੜ੒༻ͷίϝϯτ:
    // $COVERAGE-IGNORE$
    ίϝϯτ > ಋೖ

    View Slide

  14. ୅දతͳίϝϯτͷछྨ
    - υΩϡϝϯςʔγϣϯ: Ϋϥεɾؔ਺౳ʹॻ͘ܗࣜతͳίϝϯτ
    - ඇܗࣜతͳίϝϯτ: ίʔυதͷ༷ʑͳ৔ॴʹॻ͔ΕΔίϝϯτ
    - To do ίϝϯτ:
    // TODO:
    ,
    // FIXME:
    - IDEɾίϯύΠϥɾίʔυੜ੒༻ͷίϝϯτ:
    // $COVERAGE-IGNORE$
    ίϝϯτ > ಋೖ

    View Slide

  15. υΩϡϝϯςʔγϣϯͱඇܗࣜతͳίϝϯτͷ໾ׂ
    υΩϡϝϯςʔγϣϯ
    - ίʔυΛ ಡ·ͳͯ͘΋ ཧղͰ͖ΔΑ͏ʹ͢Δ
    - ʮԿͰ͋Δ͔ɾԿΛ͢Δ͔ʯΛઆ໌͢Δ
    ඇܗࣜతͳίϝϯτ
    - ίʔυΛ ಡΉ࣌ʹ ཧղΛॿ͚Δ
    - ֓ཁɾཧ༝ɾഎܠɾམͱ݀͠Λઆ໌͢Δ
    ίϝϯτ > ಋೖ

    View Slide

  16. ࠓճͷ಺༰
    - υΩϡϝϯςʔγϣϯ
    - ඇܗࣜతͳίϝϯτ
    ίϝϯτ > ಋೖ

    View Slide

  17. ࠓճͷ಺༰
    - υΩϡϝϯςʔγϣϯ
    - ඇܗࣜతͳίϝϯτ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ

    View Slide

  18. υΩϡϝϯςʔγϣϯͷର৅
    - Ϋϥε, ΠϯλʔϑΣΠε, ྻڍܕ, ߏ଄ମ, ϓϩτίϧ, τϨΠτ...
    - ม਺, ϓϩύςΟ, ϑΟʔϧυ, ύϥϝʔλ, ఆ਺...
    - ؔ਺, ϝιου, खଓ͖, αϒϧʔνϯ...
    - είʔϓ, ύοέʔδ, Ϟδϡʔϧ, ໊લۭؒ...
    ίϝϯτ > υΩϡϝϯςʔγϣϯ

    View Slide

  19. υΩϡϝϯςʔγϣϯͷϑΥʔϚοτ
    ίϝϯτͷ։࢝෦෼
    - `/**`: Kotlin, Java, Swift and Objective-C
    - `///`: Swift and Objective-C
    - `/*!`: Objective-C
    ֤ υΩϡϝϯςʔγϣϯδΣωϨʔλͷϑΥʔϚοτ Λࢀর
    ྫ: KDoc, Javadoc, Swift Markup, HeaderDoc, Doxygen
    ίϝϯτ > υΩϡϝϯςʔγϣϯ

    View Slide

  20. υΩϡϝϯςʔγϣϯʹॻ͘಺༰
    ·ͣ͸Ξϯνύλʔϯ͔Β
    ίϝϯτ > υΩϡϝϯςʔγϣϯ

    View Slide

  21. Ξϯνύλʔϯ: ࣗಈੜ੒͞ΕͨίϝϯτΛ์ஔ
    /**
    * @param keyword
    * @return
    */
    fun getDescription(keyword: String): String
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > Ξϯνύλʔϯ

    View Slide

  22. Ξϯνύλʔϯ: ఆ໊ٛͱಉ͡
    /**
    * Gets the description for a keyword.
    */
    fun getDescription(keyword: String): String
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > Ξϯνύλʔϯ

    View Slide

  23. Ξϯνύλʔϯ: ίʔυΛ຋༁͚ͨͩ͠
    /**
    * Calls [doA] if `conditionA` is satisfied.
    * Otherwise, calls [doB] and if ...
    */
    fun getDescription(keyword: String): String {
    if (conditionA) {
    doA()
    } else {
    doB()
    if (...) {...}
    }
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > Ξϯνύλʔϯ

    View Slide

  24. Ξϯνύλʔϯ: ϓϥΠϕʔτϝϯόΛ࢖ͬͯઆ໌
    /**
    * Returns a string stored in a private map [dictionary].
    */
    fun getDescription(keyword: String): String
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > Ξϯνύλʔϯ

    View Slide

  25. Ξϯνύλʔϯ: ཁ໿͕ͳ͍
    /**
    * Throws an exception if the given `keyword` is empty.
    */
    fun getDescription(keyword: String): String
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > Ξϯνύλʔϯ

    View Slide

  26. Ξϯνύλʔϯ: ݺͼग़͠ଆʹݴٴ
    /**
    * ...
    * This is called by class [UserProfilePresenter].
    */
    fun getDescription(keyword: String): String
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > Ξϯνύλʔϯ

    View Slide

  27. Ξϯνύλʔϯ͔Βͷڭ܇
    υΩϡϝϯςʔγϣϯ͸ඞཁͳͱ͖ʹ͚ͩॻ͘
    - Ϋϥε໊ɾؔ਺໊ɾม਺໊Ͱे෼ʹઆ໌Ͱ͖Δ৔߹͸লུ
    ʮͦΕ͕ԿͰ͋Δ͔ɾԿΛ͢Δ͔ʯΛཁ໿Ͱઆ໌͢Δ
    - ݺͼग़͠ଆʹݴٴͤͣʹઆ໌
    - ࣮૷ͷৄࡉʹ৮Εͣʹઆ໌
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > Ξϯνύλʔϯ

    View Slide

  28. υΩϡϝϯςʔγϣϯʹॻ͘಺༰
    ཁ໿ (ඞਢ)
    ʮԿͰ͋Δ͔ɾԿΛ͢Δ͔ʯΛઆ໌͢Δ 1 จɾ 1 ϑϨʔζ
    ৄࡉ (Φϓγϣφϧ)
    ࢖༻๏΍੍໿౳Λઆ໌͢Δ௥Ճͷจ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ֓ཁ

    View Slide

  29. υΩϡϝϯςʔγϣϯʹॻ͘಺༰
    ཁ໿ (ඞਢ)
    ʮԿͰ͋Δ͔ɾԿΛ͢Δ͔ʯΛઆ໌͢Δ 1 จɾ 1 ϑϨʔζ
    ৄࡉ (Φϓγϣφϧ)
    ࢖༻๏΍੍໿౳Λઆ໌͢Δ௥Ճͷจ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ཁ໿

    View Slide

  30. ཁ໿ͷॻ͖ํ
    ςΫχοΫ
    - ॏཁͳίʔυΛݟ͚ͭΔ
    - ίʔυͷڞ௨఺Λݟ͚ͭΔ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ཁ໿

    View Slide

  31. ཁ໿ͷॻ͖ํ: ॏཁͳίʔυ 1/2
    ίʔυͰ ࠷΋ॏཁͳ ߦɾϒϩοΫɾཁૉΛݟ͚ͭΔ
    if (!user.isValid) return
    val rawProfileImage = getProfileImage(user.id, ...)
    val roundProfileImage = applyRoundFilter(rawProfileImage, ...)
    profileView.setImage(roundProfileImage)
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ཁ໿

    View Slide

  32. ཁ໿ͷॻ͖ํ: ॏཁͳίʔυ 2/2
    ࠷΋ॏཁͳ఺Λॻ͖ɺ ิ଍͢Δ
    /**
    * Shows a roundly cut profile image of a given [user].
    * ...
    */
    ...
    profileView.setImage(roundProfileImage)
    ཁ໿͸໋໊ͷώϯτʹ΋ͳΔ
    !
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ཁ໿

    View Slide

  33. ཁ໿ͷॻ͖ํ: ίʔυͷڞ௨఺
    ίʔυͷڞ௨఺Λ୳͠ɺ ந৅Խ͢Δ
    /**
    * Updates message layout with a newly received message data.
    */
    fun ...(receivedMessageData: MessageData) {
    messageView.text = receivedMessageData.contentText
    senderNameView.text = receivedMessageData.senderName
    timestampView.text = receivedMessageData.sentTimeText
    }
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ཁ໿

    View Slide

  34. ཁ໿ͷϑΥʔϚοτ
    ඪ४ϥΠϒϥϦɾAPI ͷॻ͖ํʹ४ͣΔ ྫ: Kotlin, Java, Swift, Objective-C
    - Ϋϥε, ม਺: ໊ࢺ۟
    ྫ: "A generic ordered collection of elements."4
    - ؔ਺: ࡾਓশ୯਺ͷ ಈࢺ Ͱ࢝·ΔϑϨʔζ
    ྫ: "Adds a new element at the end of the array."5
    5 https://developer.apple.com/documentation/swift/array/3126937-append
    4 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/#list
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ཁ໿

    View Slide

  35. ೔ຊޠͷཁ໿ͷϑΥʔϚοτ
    جຊ͸ӳޠͱಉ͡
    - Ϋϥε, ม਺: ओޠΛলུͨ͠ ໊ࢺ ͰऴΘΔจɾମݴࢭΊ
    ྫ: ʮ...ʹม׵͢ΔΞμϓλͰ͢ɻʯɾʮ...ͷঢ়ଶɻʯ
    - ؔ਺: ओޠΛলུͨ͠ ಈࢺ ͰऴΘΔจ
    ྫ: ʮ...Λදࣔ͠·͢ɻʯɾʮ...Λฦ͢ɻʯ
    ܟମɾৗମ ΛϓϩμΫτ಺Ͱ౷Ұ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ཁ໿

    View Slide

  36. υΩϡϝϯςʔγϣϯʹॻ͘಺༰
    ཁ໿ (ඞਢ)
    ʮԿͰ͋Δ͔ɾԿΛ͢Δ͔ʯΛઆ໌͢Δ 1 จɾ 1 ϑϨʔζ
    ৄࡉ (Φϓγϣφϧ)
    ࢖༻๏΍੍໿౳Λઆ໌͢Δ௥Ճͷจ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  37. υΩϡϝϯςʔγϣϯͷʮৄࡉʯͷ಺༰
    - ࢓༷ͱ࢖͍ํ
    - ؔ਺ͷ໭Γ஋
    - ੍໿ͱΤϥʔ
    - ྫ
    - ...
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  38. υΩϡϝϯςʔγϣϯͷʮৄࡉʯͷ಺༰
    - ࢓༷ͱ࢖͍ํ
    - ؔ਺ͷ໭Γ஋
    - ੍໿ͱΤϥʔ
    - ྫ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  39. ࢓༷ͱ࢖͍ํ
    యܕతͳ࢖͍ํ ͱ ظ଴͢Δಈ࡞ ʹ͍ͭͯॻ͘
    /**
    * ...
    * To update view components such as message text and sender name,
    * give [MessageData] model object to [bindView].
    */
    class MessageViewPresenter(messageView: View)
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  40. υΩϡϝϯςʔγϣϯͷʮৄࡉʯͷ಺༰
    - ࢓༷ͱ࢖͍ํ
    - ؔ਺ͷ໭Γ஋
    - ੍໿ͱΤϥʔ
    - ྫ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  41. ؔ਺ͷ໭Γ஋ 1/2
    ໰୊: ҎԼͷؔ਺ͷ໭Γ஋͸ԿΛҙຯ͢Δ?
    fun setSelectedState(isSelected: Boolean): Boolean
    ղ౴ྫ:
    isToggled // ঢ়ଶ͕มԽͨ͠Β true
    wasSelected // ݺͼग़͠લͷঢ়ଶ
    isSuccessfullyUpdated // ਖ਼ৗʹऴྃ͢Ε͹ true
    isSelected // Ҿ਺ `isSelected` Λύεεϧʔ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  42. ؔ਺ͷ໭Γ஋ 2/2
    ؔ਺໊Ͱ͸આ໌͕ෆे෼ͳ৔߹ɺίϝϯτͰิ଍͢Δ
    - ؔ਺͕ ঢ়ଶΛมߋ͢Δ ৔߹
    - ໭Γ஋ʹ ੍໿͕͋Δ ৔߹
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  43. ؔ਺ͷ໭Γ஋ 2/2
    ؔ਺໊Ͱ͸આ໌͕ෆे෼ͳ৔߹ɺίϝϯτͰิ଍͢Δ
    - ؔ਺͕ ঢ়ଶΛมߋ͢Δ ৔߹
    - ໭Γ஋ʹ ੍໿͕͋Δ ৔߹
    /**
    * ...
    * ... returns true if it was selected before this function call.
    */
    fun setSelectedState(isSelected: Boolean): Boolean
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  44. ؔ਺ͷ໭Γ஋ 2/2
    ؔ਺໊Ͱ͸આ໌͕ෆे෼ͳ৔߹ɺίϝϯτͰิ଍͢Δ
    - ؔ਺͕ ঢ়ଶΛมߋ͢Δ ৔߹
    - ໭Γ஋ʹ ੍໿͕͋Δ ৔߹
    /**
    * ...
    * The profile ID is non-negative value.
    */
    fun getProfileId(): Int
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  45. υΩϡϝϯςʔγϣϯͷʮৄࡉʯͷ಺༰
    - ࢓༷ͱ࢖͍ํ
    - ؔ਺ͷ໭Γ஋
    - ੍໿ͱΤϥʔ
    - ྫ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  46. ੍໿ͱΤϥʔ
    ࣄલ৚݅ ΍ ҧ൓࣌ͷಈ࡞ ʹ͍ͭͯίϝϯτ͢Δ
    - ؔ਺ݺͼग़࣌͠ͷ Ϩγʔόͷ৚݅
    - ࣮Ҿ਺ͷ੍໿
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  47. ੍໿ͱΤϥʔ
    ࣄલ৚݅ ΍ ҧ൓࣌ͷಈ࡞ ʹ͍ͭͯίϝϯτ͢Δ
    - ؔ਺ݺͼग़࣌͠ͷ Ϩγʔόͷ৚݅
    - ࣮Ҿ਺ͷ੍໿
    /**
    * ... [prepare] must be called before calling [play] or [seek],
    * or this throws [ResourceNotReadyException].
    */
    class VideoPlayer(videoPath: String)
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  48. ੍໿ͱΤϥʔ
    ࣄલ৚݅ ΍ ҧ൓࣌ͷಈ࡞ ʹ͍ͭͯίϝϯτ͢Δ
    - ؔ਺ݺͼग़࣌͠ͷ Ϩγʔόͷ৚݅
    - ࣮Ҿ਺ͷ੍໿
    /**
    * ...
    * Returns `null` if the given `position` is out of the array range.
    */
    fun valueAt(position: Int): T?
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  49. ੍໿ͷྫ
    - ࣮Ҿ਺΍Ϩγʔόͷঢ়ଶ
    - ΠϯελϯεͷϥΠϑαΠΫϧ
    - ݺͼग़࣌͠ͷεϨου
    - ࠶ೖՄೳੑ
    - ܭࢉ࣌ؒɾϝϞϦ࢖༻ྔ
    - ֎෦؀ڥͷঢ়ଶʢωοτϫʔΫɾ෺ཧετϨʔδ౳ʣ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  50. υΩϡϝϯςʔγϣϯͷʮৄࡉʯͷ಺༰
    - ࢓༷ͱ࢖͍ํ
    - ؔ਺ͷ໭Γ஋
    - ੍໿ͱΤϥʔ
    - ྫ
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide


  51. ྫΛ࢖ͬͯ࢓༷ͷཧղΛॿ͚Δ
    - ࢖͍ํͷྫ
    - ࣮Ҿ਺ͱ໭Γ஋ͷྫ
    /**
    * ... For example, this returns `listOf("a", "bc", "", "d")`
    * for argument `"a, bc ,,d"`
    */
    fun splitByComma(string: String): List {...
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ৄࡉ

    View Slide

  52. υΩϡϝϯςʔγϣϯ: ·ͱΊ
    ର৅: Ϋϥεɾؔ਺ɾม਺ɾείʔϓ
    ಺༰: ཁ໿ (ඞਢ)ɾ ৄࡉ(೚ҙ)
    ஫ҙ఺:
    - ໊લͰ͸આ໌͕ෆे෼ͳͱ͖ʹॻ͘
    - ݺͼग़͠ଆ΍࣮૷ͷৄࡉʹݴٴ͠ͳ͍
    ίϝϯτ > υΩϡϝϯςʔγϣϯ > ·ͱΊ

    View Slide

  53. ࠓճͷ಺༰
    - υΩϡϝϯςʔγϣϯ
    - ඇܗࣜతͳίϝϯτ
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  54. ඇܗࣜతͳίϝϯτ: Kotlin ʹ͓͚Δྫ
    // Function explanation, which won't appear on KDoc
    fun function(param /* Parameter explanation */: Param) {
    // Code block summary
    someMethod(value) // Reason of a statement
    newId = param.id + 123 /* Reason of constant value */ + ...
    ...
    - ಡΉਓͷॿ͚ʹͳΔ͜ͱͳΒԿͰ΋ॻ͘
    - ཁ໿͸ඞਢͰ͸ͳ͍
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  55. ඇܗࣜతͳίϝϯτΛඞཁͱ͢Δίʔυ
    - େ͖ͳίʔυ
    - ෳࡶɾඇ௚ײతͳίʔυ
    - ϫʔΫΞϥ΢ϯυΛؚΉίʔυ
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  56. ඇܗࣜతͳίϝϯτΛඞཁͱ͢Δίʔυ
    - େ͖ͳίʔυ
    - ෳࡶɾඇ௚ײతͳίʔυ
    - ϫʔΫΞϥ΢ϯυΛؚΉίʔυ
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  57. େ͖ͳίʔυʹର͢Δίϝϯτ
    ίϝϯτͰ ίʔυͷ·ͱ·Γ Λ࡞Γɺ֓ཁΛઆ໌͢Δ
    ...
    val messageKey = ...
    val messageData = messageCache[messageKey]
    ...
    if (messageData == null || ...) { // <- When this satisfies?
    ... // <- Hard to overview code in a nest
    }
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  58. େ͖ͳίʔυʹର͢Δίϝϯτ
    ίϝϯτͰ ίʔυͷ·ͱ·Γ Λ࡞Γɺ֓ཁΛઆ໌͢Δ
    // Get message data cache if it's available
    val messageKey = ...
    val messageData = messageCache[messageKey]
    ...
    // Load message data from DB if there's no cached data.
    if (messageData == null || ...) {
    ...
    }
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  59. ඇܗࣜతͳίϝϯτΛඞཁͱ͢Δίʔυ
    - େ͖ͳίʔυ
    - ෳࡶɾඇ௚ײతͳίʔυ
    - ϫʔΫΞϥ΢ϯυΛؚΉίʔυ
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  60. ෳࡶɾඇ௚ײతͳίʔυʹର͢Δίϝϯτ
    ཧղ͕೉͍͠ίʔυͷ֓ཁ΍ཧ༝Λઆ໌͢Δ
    //
    //
    wordReplacementData.reverse()
    .forEach { (startIndex, endIndex, newText) ->
    stringBuilder.replace(startIndex, endIndex, newText)
    }
    ໰୊: ͳͥ reverse() Λݺͼग़͢ඞཁ͕͋Δʁ
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  61. ෳࡶɾඇ௚ײతͳίʔυʹର͢Δίϝϯτ
    ཧղ͕೉͍͠ίʔυͷ֓ཁ΍ཧ༝Λઆ໌͢Δ
    // Replace texts in the reverse order because `replace()`
    // affects the following indices.
    wordReplacementData.reverse()
    .forEach { (startIndex, endIndex, newText) ->
    stringBuilder.replace(startIndex, endIndex, newText)
    }
    ؒҧͬͨʮϦϑΝΫλϦϯάʯʹΑΔ reverse() ͷ࡟আΛ๷͙
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  62. ඇܗࣜతͳίϝϯτΛඞཁͱ͢Δίʔυ
    - େ͖ͳίʔυ
    - ෳࡶɾඇ௚ײతͳίʔυ
    - ϫʔΫΞϥ΢ϯυΛؚΉίʔυ
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  63. ϫʔΫΞϥ΢ϯυΛؚΉίʔυʹର͢Δίϝϯτ
    ϫʔΫΞϥ΢ϯυͰԿΛ͢Δ͔ɾͳͥඞཁͳͷ͔Λઆ໌͢Δ
    // We restore the previous state here
    // because libraryFunction() may break the receiver state
    ৄࡉΛ஌ΔͨΊͷϦϯΫΛ௥Ճ͢Δ
    // To avoid Device-X specific tinting bug (see, ISSUE-123456)
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  64. ඇܗࣜతͳίϝϯτ: ·ͱΊ
    جຊ͸υΩϡϝϯςʔγϣϯͱಉ͡
    - ͨͩ͠ɺཁ໿͸ඞਢͰ͸ͳ͍
    େ͖ͳɾෳࡶͳɾඇ௚ײతͳίʔυʹରͯ͠આ໌Λ͢Δ
    - ίʔυͷ·ͱ·Γɾ֓ཁɾཧ༝ɾϦϯΫ
    ίϝϯτ > ඇܗࣜతͳίϝϯτ

    View Slide

  65. ·ͱΊ
    - ίϝϯτ͸ඞཁͳͱ͖ɺඞཁͳ͚ͩॻ͘
    - ίϝϯτΛॻ͘લޙͰϦϑΝΫλϦϯάΛߦ͏
    - υΩϡϝϯςʔγϣϯ: ཁ໿ (ඞਢ) ɾ ৄࡉ (Φϓγϣφϧ)
    - ඇܗࣜతͳίϝϯτ: େ͖ͳɾෳࡶͳɾඇ௚ײతͳίʔυͷઆ໌
    ίϝϯτ > ·ͱΊ

    View Slide