๊ฐœ๋ฐœ ์ผ์ง€ ๐Ÿ’ป/Nutri Capture

Nutri Capture ๋ฐฑ์—”๋“œ - ์ด์ง„ ํƒ์ƒ‰ ์ ์šฉ

interfacer_han 2024. 12. 17. 10:31

#1 ์‚ฝ์ž… ํ•จ์ˆ˜ ๋ฆฌํŒฉํ† ๋ง

#1-1 ๋ฆฌํŒฉํ† ๋งํ•  ํ•จ์ˆ˜

// in NutrientViewModel.kt

private fun findIndexToInsert(list: SnapshotStateList<DayMealView>, newItem: DayMealView): Int {
    for(i: Int in list.indices) {
        if(newItem < list[i]) {
            return i
        }
    }
    // ์‚ฝ์ž…ํ•  ์œ„์น˜๊ฐ€ ์—†๋‹ค๋ฉด ๋งจ ๋(list.size)์— ์‚ฝ์ž…
    return list.size
}

NutrientViewModel์—๋Š” ์ •๋ ฌ๋œ ๋ฐฐ์—ด์— ์ƒˆ ์›์†Œ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ํ•จ์ˆ˜ findIndexToInsert()๊ฐ€ ์žˆ๋‹ค. ๊ธฐ์กด findIndexToInsert()๋Š” ์œ„ ์ฝ”๋“œ์—์„œ ๋ณด๋“ฏ ์„ ํƒ ์ •๋ ฌ์˜ ์›๋ฆฌ๋กœ ์งฐ๋‹ค.
 

#1-2 ์ด์ง„ ํƒ์ƒ‰

 

์ด์ง„ ํƒ์ƒ‰ (Binary search)

#1 ์•Œ๊ณ ๋ฆฌ์ฆ˜ #1-1 #1-2 ์ด๋ ‡๊ฒŒ ํ•ด์„œ x์˜ ์ธ๋ฑ์Šค i๋ฅผ ์ฐพ์œผ๋ฉด ์ข‹๊ฒ ์ง€๋งŒ, ์ด x๊ฐ€ ๋ฐฐ์—ด values ์–ด๋””์—๋„ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด ๊ฒฝ์šฐ์—” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ• ๊นŒ? #1-3 ์—… ์•ค ๋‹ค์šด ๊ฒŒ์ž„์€ ์šฐ๋ฆฌ๋‚˜

kenel.tistory.com

findIndexToInsert()๋Š” ์ •๋ ฌ๋œ ๋ฐฐ์—ด์—์„œ์˜ ์‚ฝ์ž…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ฆ‰, ์ด์ง„ ํƒ์ƒ‰์˜ ์›๋ฆฌ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
 

#1-3 ๋ฆฌํŒฉํ† ๋ง๋œ ํ•จ์ˆ˜

// in NutrientViewModel.kt

private fun findIndexToInsert(list: SnapshotStateList<DayMealView>, newItem: DayMealView): Int {
    var min = 0
    var max = list.size - 1

    while (min <= max) {
        val mid = (min + max) / 2

        // up
        if (list[mid] < newItem) {
            min = mid + 1

        // down
        } else if (list[mid] > newItem) {
            max = mid - 1

        // equal
        } else { // list[mid] == newItem
            return mid + 1
        }
    }

    return max + 1
}

์ด์ง„ ํƒ์ƒ‰์ด์ง€๋งŒ ๋‚ด๊ฐ€ ์ฐพ๋Š” ์›์†Œ์˜ index๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ๋Œ€์‹ , ๋‚ด๊ฐ€ ์‚ฝ์ž…ํ•˜๊ณ ์ž ํ•˜๋Š” ์›์†Œ๋ฅผ ์–ด๋Š ์ธ๋ฑ์Šค์— ๋„ฃ์–ด์•ผ ํ•  ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
 

#2 ํ…Œ์ŠคํŠธ

#2-1 Unit Testing

 

[Android] Unit Testing - ๊ธฐ์ดˆ

#1 ์ด์ „ ๊ธ€#1-1 Unit Testing ๊ฐœ์š” [Android] Unit Testing - ๊ฐœ์š”์™€ ํ™˜๊ฒฝ ์„ค์ •#1 ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ ํ…Œ์ŠคํŠธ#1-1 ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ ํ…Œ์ŠคํŠธ์˜ ์ข…๋ฅ˜๋จผ์ €, ์—ฌ๊ธฐ์— ์žˆ๋Š” ๊ตฌ๊ธ€ ๊ณต์‹ ๋ฌธ์„œ์—์„œ ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ

kenel.tistory.com

๋ฆฌํŒฉํ† ๋งํ•œ ํ•จ์ˆ˜ ๋กœ์ง์— ๋ฌธ์ œ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์ถ”ํ›„ ์‹ฌํ™”์‹œํ‚ฌ ๋•Œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ, ํ™•์‹คํ•˜๊ฒŒ ๋งค๋“ญ์ง“๊ธฐ ์œ„ํ•ด์„œ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค. ์ถ”ํ›„ ๋กœ์ง์„ ์‹ฌํ™”์‹œํ‚ฌ ๋•Œ๋„, ์ง€๊ธˆ ๋งŒ๋“ค์–ด๋‘” ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋  ๊ฒƒ์ด๋‹ค.
 

#2-2 ๊ฐ„์†Œํ™”ํ•œ findIndexToInsert()

// ๊ฐ„์†Œํ™” ์ „ ์ธ์ˆ˜: (list: SnapshotStateList<DayMealView>, newItem: DayMealView)
private fun findIndexToInsert(list: List<Long>, newItem: Long): Int {
    ...
}

ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•  findIndexToInsert()๋‹ค. DayMealView๋Š” ์ด 3๊ฐœ์˜ ๋น„๊ต ์กฐ๊ฑด์„ ๊ฐ€์ง€๊ณ  ๋น„๊ตํ•˜์ง€๋งŒ, ์—ฌ๊ธฐ์—์„œ๋Š” mealId๋งŒ์„ ๊ฐ€์ง€๊ณ  ๋น„๊ตํ•œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด, 3๊ฐœ์˜ ๋น„๊ต ์กฐ๊ฑด์€ ๋‹จ์ˆœํ•œ "<", ">", "==" ๋น„๊ต์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•˜๋‚˜๋ฅผ ๊ฒ€์ฆํ•˜๋ฉด ๋‚˜๋จธ์ง€๋Š” ๋”ฐ๋ผ์˜จ๋‹ค. ๋”ฐ๋ผ์„œ findIndexToInsert๊ฐ€ (mealId๊ณผ ๋‹ค๋ฅธ ๋น„๊ต ์กฐ๊ฑด์ด ์ „๋ถ€ ํฌํ•จ๋œ) DayMealView๊ฐ€ ์•„๋‹Œ, mealId๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค. DayMealView๋ฅผ ๊ทธ๋Œ€๋กœ ๋‘ฌ๋„ ๋˜์ง€๋งŒ ์‹œ๊ฐ„์ด ๋งŽ์ด ๊ฑธ๋ฆด ๊ฒƒ์ด๋‹ค. ์ง€๊ธˆ ๋‚ด๊ฒŒ ํ•„์š”ํ•œ ๊ฒƒ์€ ๋กœ์ง ๊ฒ€์ฆ์ด๋‹ค.
 

#2-3 ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค

// 1
DayMealView.mealId์˜ ๋ฐฐ์—ด: {} (๋นˆ ๋ฐฐ์—ด)
๋ฐฐ์—ด์— ๋„ฃ์„ ์ƒˆ mealId: 1
์‚ฝ์ž…๋œ mealId์˜ ์œ„์น˜(index): 0

// 2
DayMealView.mealId์˜ ๋ฐฐ์—ด: {1, 7, 13}
๋ฐฐ์—ด์— ๋„ฃ์„ ์ƒˆ mealId: 9
์‚ฝ์ž…๋œ mealId์˜ ์œ„์น˜(index): 2

// 3
DayMealView.mealId์˜ ๋ฐฐ์—ด: {2, 6, 7, 8, 10}
๋ฐฐ์—ด์— ๋„ฃ์„ ์ƒˆ mealId: 11
์‚ฝ์ž…๋œ mealId์˜ ์œ„์น˜(index): 5 

// 4
DayMealView.mealId์˜ ๋ฐฐ์—ด: {1, 2, 3, 4}
๋ฐฐ์—ด์— ๋„ฃ์„ ์ƒˆ mealId: 2
์‚ฝ์ž…๋œ mealId์˜ ์œ„์น˜(index): 2

ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•  ์˜ˆ์ œ๋‹ค. ์ด ๋ชจ๋“  ์˜ˆ์ œ๋“ค์„ ํ†ต๊ณผํ•ด์•ผ ๋ฆฌํŒฉํ† ๋ง์ด ์ž˜ ์™„๋ฃŒ๋œ ๊ฒƒ์ผํ…Œ๋‹ค.
 

#2-4 ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค

// package com.example.nutri_capture_new

import com.google.common.truth.Truth
import org.junit.Test


class FindIndexToInsertTest {
    private data class TestCase(
        val oldItems: List<Long>, val newItem: Long, val correctInsertedIndex: Int
    )

    private val testCases = listOf(
        TestCase(
            oldItems = emptyList(),
            newItem = 1,
            correctInsertedIndex = 0
        ),
        TestCase(
            oldItems = listOf(1, 7, 13),
            newItem = 9,
            correctInsertedIndex = 2
        ),
        TestCase(
            oldItems = listOf(2, 6, 7, 8, 10),
            newItem = 11,
            correctInsertedIndex = 5
        ),
        TestCase(
            oldItems = listOf(1, 2, 3, 4),
            newItem = 2,
            correctInsertedIndex = 2
        ),
    )

    @Test
    fun findIndexToInsert_givenTestcases_returnsCorrectIndex() {
        for (testCase in testCases) {
            val result = findIndexToInsert(testCase.oldItems, testCase.newItem)
            Truth.assertThat(result).isEqualTo(testCase.correctInsertedIndex)
        }
    }
}

private fun findIndexToInsert(list: List<Long>, newItem: Long): Int {
    var min = 0
    var max = list.size - 1

    while (min <= max) {
        val mid = (min + max) / 2

        // up
        if (list[mid] < newItem) {
            min = mid + 1

        // down
        } else if (list[mid] > newItem) {
            max = mid - 1

        // equal
        } else { // list[mid] == newItem
            return mid + 1
        }
    }

    return max + 1
}

์œ„์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด, Local unit test ์ž๋ฆฌ์— ๋„ฃ๋Š”๋‹ค. ์ฒ˜์Œ์—๋Š” NutrientViewModel ํด๋ž˜์Šค์˜ ๋ณต์‚ฌ๋ณธ์„ ํ†ต์งธ๋กœ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค๋ ค๊ณ  ํ–ˆ์œผ๋‚˜, ์•„์ง์€ ๋ทฐ๋ชจ๋ธ์—์„œ ํ…Œ์ŠคํŠธํ•  ๊ฒŒ ์—†๊ณ  ์ž‘์„ฑ ๋„์ค‘์— ๋ถˆํ•„์š”ํ•œ ๋…ธ๋ ฅ์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด ์ค‘๊ฐ„์— ๊ทธ๋งŒ๋’€๋‹ค.
 

#2-5 ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

๋ฌด์‚ฌํžˆ ํ†ต๊ณผํ–ˆ๋‹ค. ๋˜, ์•ฑ๋„ ์ž˜ ๋™์ž‘ํ•œ๋‹ค.
 

#3 ์š”์•ฝ

NutrientViewModel.findIndexToInsert()์˜ ๋กœ์ง์— ์ด์ง„ ํƒ์ƒ‰์„ ์ ์šฉํ–ˆ๋‹ค.
 

#4 ์™„์„ฑ๋œ ์•ฑ

#4-1 ์ด ๊ฒŒ์‹œ๊ธ€ ์‹œ์ ์˜ Commit

 

GitHub - Kanmanemone/nutri-capture-new

Contribute to Kanmanemone/nutri-capture-new development by creating an account on GitHub.

github.com

 

#4-2 ๋ณธ ํ”„๋กœ์ ํŠธ์˜ ๊ฐ€์žฅ ์ตœ์‹  Commit

 

GitHub - Kanmanemone/nutri-capture-new

Contribute to Kanmanemone/nutri-capture-new development by creating an account on GitHub.

github.com