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

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

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

第 4 回: 状態

---

セッションリスト

第 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. const val ಡΈ΍͍͢ίʔυͷॻ͖ํ ୈ 4 ճ
    var ঢ়ଶ

    View Slide

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

    View Slide

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

    View Slide

  4. ίʔυͷ࣮ߦͱঢ়ଶ
    ίʔυͷධՁɾ࣮ߦͰ ঢ়ଶ͸มΘΓಘΔ
    var i = 1
    println(i) // prints `"1"`
    i = i + 1
    println(i) // prints `"2"`
    ঢ়ଶ > ಋೖ

    View Slide

  5. ঢ়ଶͱίʔυͷಡΈ΍͢͞ͷؔ܎ 1/2
    ঢ়ଶ͕ଟ͗͢Δίʔυ͸ಡΈʹ͍͘
    ໰୊: ୯७ʹෆมʹ͢Ε͹ಡΈ΍͘͢ͳΔʁ
    ౴: NO!
    Մมͳঢ়ଶ΍෭࡞༻Λ࢖ͬͨ΄͏͕ಡΈ΍͘͢ͳΔ͜ͱ΋͋Δɻ
    ঢ়ଶ > ಋೖ

    View Slide

  6. ঢ়ଶͱίʔυͷಡΈ΍͢͞ͷؔ܎ 2/2
    ೋ෼໦ͷ෯༏ઌ୳ࡧͷ࣮૷Λൺֱ
    5
    6 8
    3 1
    9
    5 node
    value
    ঢ়ଶ > ಋೖ

    View Slide

  7. ঢ়ଶͱίʔυͷಡΈ΍͢͞ͷؔ܎ 2/2
    ೋ෼໦ͷ෯༏ઌ୳ࡧͷ࣮૷Λൺֱ
    class Node(val value: Int, val left: Node?, val right: Node?)
    Case 1: ՄมͳΩϡʔΛར༻
    Case 2: ࠶ؼݺͼग़͠Λར༻
    ঢ়ଶ > ಋೖ

    View Slide

  8. Case 1: ՄมͳΩϡʔΛར༻
    fun search(valueToFind: Int, root: Node): Node? {
    val queue = ArrayDeque()
    var node: Node? = root
    while (node != null && node.value != valueToFind) {
    node.left?.let { queue.add(it) }
    node.right?.let { queue.add(it) }
    node = queue.poll()
    }
    return node
    }
    ঢ়ଶ > ಋೖ

    View Slide

  9. Case 2: ࠶ؼݺͼग़͠Λར༻
    fun search(valueToFind: Int, root: Node): Node? =
    innerSearch(valueToFind, listOf(root))
    tailrec fun innerSearch(valueToFind: Int, queue: List): Node? {
    val node = queue.getOrNull(0)
    if (node == null || node.value == valueToFind) {
    return node
    }
    val nextQueue = queue.subList(1, queue.size) +
    (node.left?.let { listOf(it) } ?: emptyList()) +
    (node.right?.let { listOf(it) } ?: emptyList())
    return innerSearch(valueToFind, nextQueue)
    }
    ঢ়ଶ > ಋೖ

    View Slide

  10. ࠶ؼݺͼग़͠ͷྫͷ໰୊఺
    ΑΓෳࡶ
    - ࠶ؼ͢Δؔ਺ͱΠϯλʔϑΣΠεͷ෼཭͕ඞཁ
    - ʮ࣍ͷΩϡʔͷঢ়ଶʯͷԋࢉ͕ෳࡶ
    valueToFind ͕มΘΒͳ͍͜ͱ͕ະอূ
    - ࠶ؼݺͼग़͠Ͱ࣮Ҿ਺͕มΘΔ͔ෆ໌
    - ࣮Ҿ਺Λݻఆ͢Δʹ͸ϩʔΧϧؔ਺͕ඞཁ
    ঢ়ଶ > ಋೖ

    View Slide

  11. ঢ়ଶͱಡΈ΍͢͞ͷؔ܎Ͱ஫ҙ͢Δ΂͖఺
    ʮεςʔτϨεɾෆมɾࢀরಁաͳίʔυʯࣗମ͕໨తͰ͸ͳ͍
    - ಡΈ΍͢͞ɾؤ݈ੑΛ࣮ݱ͢Δखஈ
    - ࠶ؼݺͼग़͠΍৞ΈࠐΈ͸ίʔυΛվળ͢ΔͨΊʹ࢖͏
    ݟ͔͚ͷঢ়ଶ਺ΑΓ΋ϓϩάϥϜ࣮ߦঢ়ଶશମʹ஫໨͢Δ
    - ہॴతͳՄมੑ͸େ͖ͳ໰୊Ͱ͸ͳ͍
    - ہॴతͳෆมੑ͕શମͷঢ়ଶ਺Λ૿΍͢͜ͱ΋͋Δ
    ঢ়ଶ > ಋೖ

    View Slide

  12. ࠓճͷ಺༰
    ಡΈ΍͢͞ͷͨΊʹؾΛ͚ͭΔ΂͖఺
    - ม਺ؒͷؔ܎
    - ঢ়ଶભҠͷઃܭ
    ঢ়ଶ > ಋೖ

    View Slide

  13. ࠓճͷ಺༰
    ಡΈ΍͢͞ͷͨΊʹؾΛ͚ͭΔ΂͖఺
    - ม਺ؒͷؔ܎
    - ঢ়ଶભҠͷઃܭ
    ঢ়ଶ > ม਺ؒͷؔ܎

    View Slide

  14. ௚ަͷؔ܎: ఆٛ
    2 ͭͷม਺ͷ಺ͲͪΒ͔ͷ஋͕ܾ·ͬͨͱ͖ʹ
    ΋͏ 1 ͭͷ ม਺͕औΓ͏Δ஋ʹӨڹΛٴ΅͞ͳ͍
    ঢ়ଶ > ม਺ؒͷؔ܎

    View Slide

  15. ௚ަͷؔ܎: ྫ
    αʔϏε಺௨՟ʮcoinʯͷදࣔը໘Λ૝ఆ
    ABC
    123,456 coins
    100,000
    1,000
    1,000
    8
    10
    11
    /
    /
    /
    5
    5
    5
    ঢ়ଶ > ม਺ؒͷؔ܎

    View Slide

  16. ௚ަͷؔ܎: ྫ
    αʔϏε಺௨՟ʮcoinʯͷදࣔը໘Λ૝ఆ
    ௚ަ:
    coinCount ͱ coinHistoryVisibility
    coinCount ͷ஋͸ coinHistoryVisibility ʹؔ܎͠ͳ͍
    ඇ௚ަ: coinCount ͱ coinText
    coinCount ͱ coinText ͷऔΕΔ஋ͷ૊Έ߹Θ͕ͤݶΒΕΔ
    ঢ়ଶ > ม਺ؒͷؔ܎

    View Slide

  17. ௚ަੑʹ͓͚Δجຊํ਑
    ʮඇ௚ަʯͳؔ܎Λආ͚Δ
    ඇ௚ަͳؔ܎ͷ͋ΔΫϥεͷྫ
    class CoinState(val coinCount: Int, val coinText: String)
    ෆਖ਼ͳঢ়ଶͷݪҼʹͳΔ
    CoinState(coinCount = 10, coinText = "0 coin")
    ঢ়ଶ > ม਺ؒͷؔ܎

    View Slide

  18. ඇ௚ަͳؔ܎Λղܾ͢Δํ๏
    - ؔ਺΍ήολʔϓϩύςΟʹஔ͖׵͑Δ
    - ௚࿨ܕΛ࢖͏
    ঢ়ଶ > ม਺ؒͷؔ܎

    View Slide

  19. ඇ௚ަͳؔ܎Λղܾ͢Δํ๏
    - ؔ਺΍ήολʔϓϩύςΟʹஔ͖׵͑Δ
    - ௚࿨ܕΛ࢖͏
    ঢ়ଶ > ม਺ؒͷؔ܎

    View Slide

  20. ؔ਺΍ήολʔϓϩύςΟʹΑΔஔ͖׵͑ 1/2
    coinText ͸ coinCount ͔ΒٻΊΒΕΔ
    class CoinState(
    val coinCount: Int,
    val coinText: String
    )
    coinCount ͷΈΛࢦఆՄೳʹ͢Δ
    ঢ়ଶ > ม਺ؒͷؔ܎ > ؔ਺΍ήολʔϓϩύςΟʹΑΔஔ͖׵͑

    View Slide

  21. ؔ਺΍ήολʔϓϩύςΟʹΑΔஔ͖׵͑ 2/2
    coinText Λ coinCount ͔ΒٻΊΔ
    class CoinState(
    val coinCount: Int
    ) {
    fun coinText(formatter: Formatter): String =
    formatter.getQuantityString(coinCount, "coin")
    }
    ෆਖ਼ͳ CoinState ͷΠϯελϯε͸ଘࡏ͑͠ͳ͍
    ঢ়ଶ > ม਺ؒͷؔ܎ > ؔ਺΍ήολʔϓϩύςΟʹΑΔஔ͖׵͑

    View Slide

  22. ඇ௚ަͳؔ܎Λղܾ͢Δํ๏
    - ؔ਺΍ήολʔϓϩύςΟʹஔ͖׵͑Δ
    - ௚࿨ܕΛ࢖͏
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  23. ௚࿨ܕΛ࢖͏ 1/3
    ίΠϯͷදࣔͰΤϥʔ͕ى͖͏Δ͜ͱΛ૝ఆ
    ABC
    ...
    123,456 coins
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  24. ௚࿨ܕΛ࢖͏ 2/3
    resultText ͱ errorCode ͷͲͪΒ͔Ұํ͚͕ͩ non-null
    class QueryResponse(
    val resultText: String?,
    val errorCode: Int?
    )
    ҰํͷϓϩύςΟ͸΋͏Ұํ͔ΒٻΊΒΕͳ͍
    ഉଞతͳ஋Λ௚࿨ܕͰදݱ͢Δ
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  25. ௚࿨ܕ
    ෳ਺ͷܕͷ஋ͷத͔Βͪΐ͏Ͳ 1 ͭͷ஋ΛऔΔܕ
    ू߹࿦ͷ௚࿨ू߹ʹ૬౰
    QueryResponse ͷྫ:
    QueryResponse = Result | Error
    ࣮ݱखஈ: Tagged union, variant, sealed class, associated value ...
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  26. ௚࿨ܕΛ࢖͏ 3/3
    sealed class QueryResponse {
    class Result(val resultText: String): QueryResponse()
    class Error(val errorCode: Int): QueryResponse()
    }
    QueryResponse ͸ resultText ͔ errorCode Λഉଞతʹ࣋ͭ
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  27. ඇ௚ަͳؔ܎Λղܾ͢Δํ๏
    - ؔ਺΍ήολʔϓϩύςΟʹஔ͖׵͑Δ
    - ௚࿨ܕΛ࢖͏
    - খ͞ͳΫϥεͰ୅༻͢Δ
    - ಛघܥͱͯ͠ྻڍܕΛ࢖͏
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  28. ௚࿨ܕͷ୅༻ 1/2
    ௚࿨ܕ͕ͳ͍ݴޠ΋͋Δ (ྫ: Java ~14)
    ௚࿨ܕʹ͍ۙ໾ׂΛখ͞ͳΫϥεͰ࣮ݱ
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  29. ௚࿨ܕͷ୅༻ 2/2
    class QueryResponse {
    @Nullable private final String resultText;
    @Nullable private final Integer errorCode;
    private QueryResponse(...) { ... }
    @NonNull
    static QueryResponse asResult(@NonNull String ...) { ... }
    @NonNull
    static QueryResponse asError(int errorCode) { ... }
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  30. ඇ௚ަͳؔ܎Λղܾ͢Δํ๏
    - ؔ਺΍ήολʔϓϩύςΟʹஔ͖׵͑Δ
    - ௚࿨ܕΛ࢖͏
    - খ͞ͳΫϥεͰ୅༻͢Δ
    - ಛघܥͱͯ͠ྻڍܕΛ࢖͏
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  31. ಛघܥͱͯ͠ͷྻڍܕ
    ඇ௚ަͳؔ܎ͷഉআʹྻڍܕͰे෼ͳ͜ͱ΋
    // isResultViewShown && isErrorViewShown can't happen
    var isResultViewShown: Boolean
    var isErrorViewShown: Boolean
    ྻڍʹΑͬͯ (true, true) ͷ৔߹Λഉআ͢Δ
    enum class VisibleViewType { RESULT_VIEW, ERROR_VIEW, NOTHING }
    ঢ়ଶ > ม਺ؒͷؔ܎ > ௚࿨ܕΛ࢖͏

    View Slide

  32. ม਺ؒͷؔ܎: ·ͱΊ
    ௚ަɾඇ௚ަͷؔ܎
    - ஋ͷऔΕΔൣғ͕Өڹ͢Δ͔Ͳ͏͔
    - ʮෆਖ਼ͳঢ়ଶʯΛ࡞Βͳ͍ͨΊʹॏཁ
    ඇ௚ަͷؔ܎ͷഉআํ๏
    - ؔ਺ɾήολʔϓϩύςΟ
    - ௚࿨ܕɾྻڍܕɾখ͞ͳΫϥε
    ঢ়ଶ > ม਺ؒͷؔ܎ > ·ͱΊ

    View Slide

  33. ࠓճͷ಺༰
    ಡΈ΍͢͞ͷͨΊʹؾΛ͚ͭΔ΂͖఺
    - ม਺ؒͷؔ܎
    - ঢ়ଶભҠ
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ

    View Slide

  34. ঢ়ଶભҠͷछྨ
    - ෆม: ఆ਺ ౳
    - ႈ౳: Closable, Lazy ౳
    - ඇ८ճ (ࣗݾϧʔϓΛআ͘): ϦιʔεͷετϦʔϜ ౳
    - ८ճ: ࠶ར༻ՄೳΦϒδΣΫτ ౳
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ

    View Slide

  35. ঢ়ଶભҠͷछྨ
    - ෆม: ఆ਺ ౳
    - ႈ౳: Closable, Lazy ౳
    - ඇ८ճ (ࣗݾϧʔϓΛআ͘): ϦιʔεͷετϦʔϜ ౳
    - ८ճ: ࠶ར༻ՄೳΦϒδΣΫτ ౳
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ

    View Slide

  36. ෆมͳΦϒδΣΫτ
    ͢΂ͯͷϓϩύςΟ͕มԽ͠ͳ͍
    // Examples of "immutable"
    class Immutable(val value: Int)
    class AnotherImmutable(val immutable: Immutable)
    // Examples of "mutable"
    class Mutable(var value: Int)
    class AnotherMutable(var immutable: Immutable)
    class YetAnotherMutable(val mutable: Mutable)
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ෆม

    View Slide

  37. ෆมɾՄมͷ஫ҙ఺ 1/3
    Ұ෦ͷϓϩύςΟ͚ͩͰ΋ෆมʹͰ͖ͳ͍͔ݕ౼͢Δ
    class CheckBoxViewModel(
    val text: String,
    var isEnabled: Boolean
    )
    ஋ͷϥΠϑαΠΫϧ͝ͱʹΫϥεΛ෼͚Δ͜ͱ΋ߟྀ͢Δ
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ෆม

    View Slide

  38. ෆมɾՄมͷ஫ҙ఺ 2/3
    ෆมͱಡΈऔΓઐ༻ͷҧ͍ʹ஫ҙ͢Δ
    val mutableList: MutableList = mutableListOf()
    val list: List = mutableList
    println(list.size) // => "0"
    mutableList += itemModel
    println(list.size) // => "1"
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ෆม

    View Slide

  39. ෆมɾՄมͷ஫ҙ఺ 3/3
    ࢀরͱࢀরઌΦϒδΣΫτΛಉ࣌ʹՄมʹ͠ͳ͍ʢՄೳͳݶΓʣ
    var itemModelList: MutableList
    fun clearItemModelList() {
    // itemModelList.clear() or itemModelList = emptyMutableList()
    }
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ෆม

    View Slide

  40. ෆมɾՄมͷ஫ҙ఺ 3/3
    ࢀরͱࢀরઌΦϒδΣΫτΛಉ࣌ʹՄมʹ͠ͳ͍ʢՄೳͳݶΓʣ
    var itemModelList: MutableList
    val list = itemModelList
    fun clearItemModelList() {
    // itemModelList.clear() or itemModelList = emptyMutableList()
    }
    มߋͷӨڹൣғ͕Θ͔Γʹ͘͘ͳΔ
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ෆม

    View Slide

  41. ঢ়ଶભҠͷछྨ
    - ෆม: ఆ਺ ౳
    - ႈ౳: Closable, Lazy ౳
    - ඇ८ճ (ࣗݾϧʔϓΛআ͘): ϦιʔεͷετϦʔϜ ౳
    - ८ճ: ࠶ར༻ՄೳΦϒδΣΫτ ౳
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ႈ౳

    View Slide

  42. ႈ౳ੑ
    ʮ1 ճʯͱʮෳ਺ճʯͰ࣮ߦ݁Ռ͕౳͍͠
    val closable = Closable() // "Open" state
    closable.close() // "Closed" state
    closable.close() // Valid. Keep "Closed" state
    ෭࡞༻ΛӅṭͰ͖Δ͜ͱ͕͋Δ (ྫ: Kotlin ͷ Lazy)
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ႈ౳

    View Slide

  43. ႈ౳ͷঢ়ଶભҠਤ
    2 ͭͷঢ়ଶͱ 1 ճͷભҠύε
    Open Closed
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ႈ౳

    View Slide

  44. ႈ౳ͷར఺
    ෆਖ਼ͳঢ়ଶભҠͷഉআ
    // We may forget to check `isClosed`
    if (!nonIdempotentClosable.isClosed()) {
    nonIdempotentClosable.close()
    }
    // We can simply call `close` for an idempotent instance
    idempotentClosable.close()
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ႈ౳

    View Slide

  45. ࣗݾϧʔϓͷԠ༻
    ႈ౳Ҏ֎ʹରͯ͠΋ࣗݾϧʔϓ͸༗ޮ
    ঢ়ଶભҠͷऴ୺Ͱࣗݾϧʔϓ͢Δ
    Zero Two
    One
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ႈ౳

    View Slide

  46. ࣗݾϧʔϓͷԠ༻
    ႈ౳Ҏ֎ʹରͯ͠΋ࣗݾϧʔϓ͸༗ޮ
    ঢ়ଶભҠͷऴ୺Ͱࣗݾϧʔϓ͢Δ
    None Multiple
    Single
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ႈ౳

    View Slide

  47. ঢ়ଶભҠͷछྨ
    - ෆม: ఆ਺ ౳
    - ႈ౳: Closable, Lazy ౳
    - ඇ८ճ (ࣗݾϧʔϓΛআ͘): ϦιʔεͷετϦʔϜ ౳
    - ८ճ: ࠶ར༻ՄೳΦϒδΣΫτ ౳
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  48. ඇ८ճͱ८ճ 1/2
    ඇ८ճ: Ҏલͷঢ়ଶʹ໭Δ ܦ࿏͕ͳ͍
    ८ճ: Ҏલͷঢ়ଶʹ໭Δ ܦ࿏͕͋Δ
    State1 State2
    State3
    State1 State2
    State3
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  49. ඇ८ճͱ८ճ 2/2
    (ࣗݾϧʔϓΛআ͍ͯ) ඇ८ճ͕๬·͍͠
    ΦϒδΣΫτΛ࢖͍ࣺͯΔ
    - ঢ়ଶΛϦηοτ͢Δ͝ͱʹ৽ͨͳΠϯελϯεΛ࡞Δ
    - ύϑΥʔϚϯεͰෆརͳ͜ͱ΋
    // This class instance works only a given `videoPath`.
    class VideoPlayer(videoPath: String) {
    enum class State { LOADING, PLAYING, FINISHED, ERROR }
    ...
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  50. ඇ८ճͷྫɹ1/2
    DurationLogger Ϋϥεͷ࣮૷
    Measuring Finished
    finishMeasurement
    finishMeasurement
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  51. ඇ८ճͷྫɹ2/2
    class DurationLogger(...) {
    private var state: State = State.Measuring(...)
    fun finishMeasureMent() {
    val measuringState = state as? State.Measuring ?: return
    ...
    state = State.Finished
    }
    private sealed class State {
    class Measuring(val startedTimeInNanos: Long) : State()
    object Finished : State()
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  52. ८ճͷྫɹ1/2
    startMeasurement ʹΑΓ࠶ར༻Մೳ
    Measuring Stopped
    finishMeasurement
    finishMeasurement
    startMeasurement
    startMeasurement
    initial state
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  53. ८ճͷྫɹ2/2
    class DurationLogger(...) {
    private var state: State = State.Stopped
    fun startMeasurement() {
    if (state == State.Stopped) {
    state = State.Measuring(...)
    }
    }
    fun finishMeasurement() {
    val measuringState = state as? State.Measuring ?: return
    ...
    state = State.Stopped
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  54. ८ճͷ໰୊఺
    ࢖͍ํΛؒҧ͍΍͍͢
    private val logger = DurationLogger(...)
    fun runSomeHeavyTask() {
    logger.startMeasurement()
    ...
    runAnotherHeavyTask() // Bug: `logger` is touched internally
    logger.finishMeasurement()
    }
    private fun runAnotherHeavyTask() { /* Use `logger` here, too */ }
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  55. ඇ८ճͷঢ়ଶભҠͱݱ࣮
    Ϟσϧͷ୯७ԽͷͨΊʹ८ճ͕ඞཁʹͳΔ
    - ແཧͳ८ճͷ࡟আ͸ίʔυΛΑΓෳࡶʹ͢Δ͔΋
    - DurationLogger ͷྫ: Measuring <-> Paused
    ८ճͷൣғΛখ͘͢͞Δ
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  56. ८ճͷہॴԽ
    ८ճΛ 1 ͭͷঢ়ଶʹด͡ࠐΊΔ = େ͖ͳ८ճΛ࡞Βͳ͍
    Measuring
    Finished
    Paused
    finish
    pause
    resume
    Measuring/Paused
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ८ճɾඇ८ճ

    View Slide

  57. ঢ়ଶભҠͷछྨ
    - ෆม: ఆ਺ ౳
    - ႈ౳: Closable, Lazy ౳
    - ඇ८ճ (ࣗݾϧʔϓΛআ͘): ϦιʔεͷετϦʔϜ ౳
    - ८ճ: ࠶ར༻ՄೳΦϒδΣΫτ ౳
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ·ͱΊ

    View Slide

  58. ঢ়ଶભҠͷઃܭ: ·ͱΊ
    - ෆม΍ႈ౳Λར༻͢Δ
    - ঢ়ଶભҠͷ८ճΛ࡟আɾہॴԽ͢Δ
    ঢ়ଶ > ঢ়ଶભҠͷઃܭ > ·ͱΊ

    View Slide

  59. ·ͱΊ
    ಡΈ΍͢͞ɾؤ݈ੑͷͨΊʹঢ়ଶΛ୯७Խ͢Δ
    - ୯७Խͦͷ΋ͷΛ໨తʹ͠ͳ͍
    ඇ௚ަͳؔ܎Λഉআ͢Δ
    - ؔ਺ʹΑΔஔ͖׵͑ɾ௚࿨ܕ΍ྻڍͷར༻
    ঢ়ଶભҠͷઃܭʹؾΛ഑Δ
    - ෆมɾႈ౳ɾ८ճ
    ঢ়ଶ > ·ͱΊ

    View Slide