oh-my-oop 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MCP_STRUCTURE.md +301 -0
- package/README.md +167 -0
- package/SCOPE.md +27 -0
- package/dist/application/discovery.d.ts +133 -0
- package/dist/application/discovery.js +62 -0
- package/dist/application/discovery.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +80 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.js +32 -0
- package/dist/config.js.map +1 -0
- package/dist/domain/collaborators.d.ts +2 -0
- package/dist/domain/collaborators.js +26 -0
- package/dist/domain/collaborators.js.map +1 -0
- package/dist/domain/ids.d.ts +4 -0
- package/dist/domain/ids.js +23 -0
- package/dist/domain/ids.js.map +1 -0
- package/dist/domain/model.d.ts +71 -0
- package/dist/domain/model.js +2 -0
- package/dist/domain/model.js.map +1 -0
- package/dist/domain/schemas.d.ts +213 -0
- package/dist/domain/schemas.js +79 -0
- package/dist/domain/schemas.js.map +1 -0
- package/dist/domain/stereotypes.d.ts +7 -0
- package/dist/domain/stereotypes.js +65 -0
- package/dist/domain/stereotypes.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/io/classStore.d.ts +9 -0
- package/dist/io/classStore.js +39 -0
- package/dist/io/classStore.js.map +1 -0
- package/dist/io/collaborationStore.d.ts +7 -0
- package/dist/io/collaborationStore.js +32 -0
- package/dist/io/collaborationStore.js.map +1 -0
- package/dist/io/design.d.ts +3 -0
- package/dist/io/design.js +22 -0
- package/dist/io/design.js.map +1 -0
- package/dist/io/designIndex.d.ts +6 -0
- package/dist/io/designIndex.js +49 -0
- package/dist/io/designIndex.js.map +1 -0
- package/dist/io/frontmatter.d.ts +8 -0
- package/dist/io/frontmatter.js +31 -0
- package/dist/io/frontmatter.js.map +1 -0
- package/dist/io/history.d.ts +10 -0
- package/dist/io/history.js +38 -0
- package/dist/io/history.js.map +1 -0
- package/dist/io/useCaseStore.d.ts +8 -0
- package/dist/io/useCaseStore.js +36 -0
- package/dist/io/useCaseStore.js.map +1 -0
- package/dist/io/workspace.d.ts +14 -0
- package/dist/io/workspace.js +82 -0
- package/dist/io/workspace.js.map +1 -0
- package/dist/oop/commands.d.ts +446 -0
- package/dist/oop/commands.js +319 -0
- package/dist/oop/commands.js.map +1 -0
- package/dist/oop/conformance.d.ts +16 -0
- package/dist/oop/conformance.js +30 -0
- package/dist/oop/conformance.js.map +1 -0
- package/dist/prompts/discovery.d.ts +2 -0
- package/dist/prompts/discovery.js +41 -0
- package/dist/prompts/discovery.js.map +1 -0
- package/dist/prompts/imagineWithoutController.d.ts +2 -0
- package/dist/prompts/imagineWithoutController.js +75 -0
- package/dist/prompts/imagineWithoutController.js.map +1 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/index.js +17 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/phasePressureTest.d.ts +2 -0
- package/dist/prompts/phasePressureTest.js +69 -0
- package/dist/prompts/phasePressureTest.js.map +1 -0
- package/dist/prompts/rddIntro.d.ts +2 -0
- package/dist/prompts/rddIntro.js +53 -0
- package/dist/prompts/rddIntro.js.map +1 -0
- package/dist/prompts/review.d.ts +2 -0
- package/dist/prompts/review.js +45 -0
- package/dist/prompts/review.js.map +1 -0
- package/dist/prompts/stateMachineIntrospect.d.ts +2 -0
- package/dist/prompts/stateMachineIntrospect.js +80 -0
- package/dist/prompts/stateMachineIntrospect.js.map +1 -0
- package/dist/prompts/tellDontAskRephrase.d.ts +2 -0
- package/dist/prompts/tellDontAskRephrase.js +66 -0
- package/dist/prompts/tellDontAskRephrase.js.map +1 -0
- package/dist/render/diff.d.ts +21 -0
- package/dist/render/diff.js +84 -0
- package/dist/render/diff.js.map +1 -0
- package/dist/render/mermaid.d.ts +24 -0
- package/dist/render/mermaid.js +53 -0
- package/dist/render/mermaid.js.map +1 -0
- package/dist/render/sideBySide.d.ts +14 -0
- package/dist/render/sideBySide.js +91 -0
- package/dist/render/sideBySide.js.map +1 -0
- package/dist/resources/index.d.ts +2 -0
- package/dist/resources/index.js +349 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +22 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/alternatives.d.ts +2 -0
- package/dist/tools/alternatives.js +9 -0
- package/dist/tools/alternatives.js.map +1 -0
- package/dist/tools/classes.d.ts +2 -0
- package/dist/tools/classes.js +13 -0
- package/dist/tools/classes.js.map +1 -0
- package/dist/tools/collaborations.d.ts +2 -0
- package/dist/tools/collaborations.js +8 -0
- package/dist/tools/collaborations.js.map +1 -0
- package/dist/tools/compare.d.ts +2 -0
- package/dist/tools/compare.js +9 -0
- package/dist/tools/compare.js.map +1 -0
- package/dist/tools/conformance.d.ts +3 -0
- package/dist/tools/conformance.js +11 -0
- package/dist/tools/conformance.js.map +1 -0
- package/dist/tools/diagram.d.ts +2 -0
- package/dist/tools/diagram.js +9 -0
- package/dist/tools/diagram.js.map +1 -0
- package/dist/tools/discovery.d.ts +2 -0
- package/dist/tools/discovery.js +23 -0
- package/dist/tools/discovery.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +27 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/init.d.ts +2 -0
- package/dist/tools/init.js +9 -0
- package/dist/tools/init.js.map +1 -0
- package/dist/tools/oop.d.ts +9 -0
- package/dist/tools/oop.js +26 -0
- package/dist/tools/oop.js.map +1 -0
- package/dist/tools/responsibilities.d.ts +2 -0
- package/dist/tools/responsibilities.js +13 -0
- package/dist/tools/responsibilities.js.map +1 -0
- package/dist/tools/state.d.ts +2 -0
- package/dist/tools/state.js +8 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tools/useCases.d.ts +2 -0
- package/dist/tools/useCases.js +18 -0
- package/dist/tools/useCases.js.map +1 -0
- package/dist/tools/validate.d.ts +2 -0
- package/dist/tools/validate.js +9 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/tradeoff/engine.d.ts +61 -0
- package/dist/tradeoff/engine.js +171 -0
- package/dist/tradeoff/engine.js.map +1 -0
- package/dist/tradeoff/heuristics/classSplit.d.ts +3 -0
- package/dist/tradeoff/heuristics/classSplit.js +94 -0
- package/dist/tradeoff/heuristics/classSplit.js.map +1 -0
- package/dist/tradeoff/heuristics/collaborationShape.d.ts +2 -0
- package/dist/tradeoff/heuristics/collaborationShape.js +82 -0
- package/dist/tradeoff/heuristics/collaborationShape.js.map +1 -0
- package/dist/tradeoff/heuristics/collectionShape.d.ts +2 -0
- package/dist/tradeoff/heuristics/collectionShape.js +113 -0
- package/dist/tradeoff/heuristics/collectionShape.js.map +1 -0
- package/dist/tradeoff/heuristics/dualSubjectComparison.d.ts +2 -0
- package/dist/tradeoff/heuristics/dualSubjectComparison.js +114 -0
- package/dist/tradeoff/heuristics/dualSubjectComparison.js.map +1 -0
- package/dist/tradeoff/heuristics/errorHandling.d.ts +2 -0
- package/dist/tradeoff/heuristics/errorHandling.js +110 -0
- package/dist/tradeoff/heuristics/errorHandling.js.map +1 -0
- package/dist/tradeoff/heuristics/responsibilitySplit.d.ts +23 -0
- package/dist/tradeoff/heuristics/responsibilitySplit.js +183 -0
- package/dist/tradeoff/heuristics/responsibilitySplit.js.map +1 -0
- package/dist/tradeoff/heuristics/stereotypeChoice.d.ts +2 -0
- package/dist/tradeoff/heuristics/stereotypeChoice.js +23 -0
- package/dist/tradeoff/heuristics/stereotypeChoice.js.map +1 -0
- package/dist/tradeoff/heuristics/strategyOrPolicy.d.ts +2 -0
- package/dist/tradeoff/heuristics/strategyOrPolicy.js +110 -0
- package/dist/tradeoff/heuristics/strategyOrPolicy.js.map +1 -0
- package/dist/tradeoff/heuristics/valueObjectShape.d.ts +2 -0
- package/dist/tradeoff/heuristics/valueObjectShape.js +111 -0
- package/dist/tradeoff/heuristics/valueObjectShape.js.map +1 -0
- package/dist/tradeoff/templates.d.ts +2 -0
- package/dist/tradeoff/templates.js +33 -0
- package/dist/tradeoff/templates.js.map +1 -0
- package/dist/util/log.d.ts +1 -0
- package/dist/util/log.js +7 -0
- package/dist/util/log.js.map +1 -0
- package/dist/util/mcp.d.ts +4 -0
- package/dist/util/mcp.js +18 -0
- package/dist/util/mcp.js.map +1 -0
- package/dist/validate/cohesion.d.ts +3 -0
- package/dist/validate/cohesion.js +88 -0
- package/dist/validate/cohesion.js.map +1 -0
- package/dist/validate/collectionWrapper.d.ts +3 -0
- package/dist/validate/collectionWrapper.js +131 -0
- package/dist/validate/collectionWrapper.js.map +1 -0
- package/dist/validate/coupling.d.ts +3 -0
- package/dist/validate/coupling.js +47 -0
- package/dist/validate/coupling.js.map +1 -0
- package/dist/validate/cycle.d.ts +3 -0
- package/dist/validate/cycle.js +101 -0
- package/dist/validate/cycle.js.map +1 -0
- package/dist/validate/dataDuplication.d.ts +3 -0
- package/dist/validate/dataDuplication.js +150 -0
- package/dist/validate/dataDuplication.js.map +1 -0
- package/dist/validate/dependencyDirection.d.ts +3 -0
- package/dist/validate/dependencyDirection.js +106 -0
- package/dist/validate/dependencyDirection.js.map +1 -0
- package/dist/validate/dualUseKnowing.d.ts +3 -0
- package/dist/validate/dualUseKnowing.js +137 -0
- package/dist/validate/dualUseKnowing.js.map +1 -0
- package/dist/validate/emptyObjectFill.d.ts +3 -0
- package/dist/validate/emptyObjectFill.js +119 -0
- package/dist/validate/emptyObjectFill.js.map +1 -0
- package/dist/validate/findings.d.ts +22 -0
- package/dist/validate/findings.js +12 -0
- package/dist/validate/findings.js.map +1 -0
- package/dist/validate/functionDecompositionExcess.d.ts +3 -0
- package/dist/validate/functionDecompositionExcess.js +120 -0
- package/dist/validate/functionDecompositionExcess.js.map +1 -0
- package/dist/validate/functionNotObject.d.ts +3 -0
- package/dist/validate/functionNotObject.js +80 -0
- package/dist/validate/functionNotObject.js.map +1 -0
- package/dist/validate/godObject.d.ts +6 -0
- package/dist/validate/godObject.js +76 -0
- package/dist/validate/godObject.js.map +1 -0
- package/dist/validate/presentationInDomain.d.ts +3 -0
- package/dist/validate/presentationInDomain.js +57 -0
- package/dist/validate/presentationInDomain.js.map +1 -0
- package/dist/validate/primitiveWrapper.d.ts +3 -0
- package/dist/validate/primitiveWrapper.js +106 -0
- package/dist/validate/primitiveWrapper.js.map +1 -0
- package/dist/validate/rules.d.ts +24 -0
- package/dist/validate/rules.js +269 -0
- package/dist/validate/rules.js.map +1 -0
- package/dist/validate/singletonStatefulHolder.d.ts +3 -0
- package/dist/validate/singletonStatefulHolder.js +128 -0
- package/dist/validate/singletonStatefulHolder.js.map +1 -0
- package/dist/validate/strategyAsymmetry.d.ts +3 -0
- package/dist/validate/strategyAsymmetry.js +131 -0
- package/dist/validate/strategyAsymmetry.js.map +1 -0
- package/dist/validate/testability.d.ts +5 -0
- package/dist/validate/testability.js +157 -0
- package/dist/validate/testability.js.map +1 -0
- package/dist/validate/vagueName.d.ts +3 -0
- package/dist/validate/vagueName.js +136 -0
- package/dist/validate/vagueName.js.map +1 -0
- package/dist/validate/validationLocation.d.ts +3 -0
- package/dist/validate/validationLocation.js +120 -0
- package/dist/validate/validationLocation.js.map +1 -0
- package/lessons/STYLE_GUIDE.md +304 -0
- package/lessons/woowacourse-kotlin-blackjack/2chang5/33-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +293 -0
- package/lessons/woowacourse-kotlin-blackjack/Choisehyeon/52-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +106 -0
- package/lessons/woowacourse-kotlin-blackjack/Choisehyeon/9-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +282 -0
- package/lessons/woowacourse-kotlin-blackjack/DYGames/14-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +182 -0
- package/lessons/woowacourse-kotlin-blackjack/DYGames/37-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +122 -0
- package/lessons/woowacourse-kotlin-blackjack/EmilyCh0/12-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +117 -0
- package/lessons/woowacourse-kotlin-blackjack/EmilyCh0/38-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +291 -0
- package/lessons/woowacourse-kotlin-blackjack/HANDOVER.md +1475 -0
- package/lessons/woowacourse-kotlin-blackjack/HamBeomJoon/119-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +251 -0
- package/lessons/woowacourse-kotlin-blackjack/HamBeomJoon/137-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +459 -0
- package/lessons/woowacourse-kotlin-blackjack/Hevton/100-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +282 -0
- package/lessons/woowacourse-kotlin-blackjack/Hevton/82-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +303 -0
- package/lessons/woowacourse-kotlin-blackjack/Hogu59/71-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +134 -0
- package/lessons/woowacourse-kotlin-blackjack/Hogu59/96-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +323 -0
- package/lessons/woowacourse-kotlin-blackjack/JoYehyun99/66-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +210 -0
- package/lessons/woowacourse-kotlin-blackjack/Junyoung-WON/101-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +191 -0
- package/lessons/woowacourse-kotlin-blackjack/Junyoung-WON/80-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
- package/lessons/woowacourse-kotlin-blackjack/Leeyerin0210/108-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +516 -0
- package/lessons/woowacourse-kotlin-blackjack/Leeyerin0210/133-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +541 -0
- package/lessons/woowacourse-kotlin-blackjack/RightHennessy/22-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +278 -0
- package/lessons/woowacourse-kotlin-blackjack/RightHennessy/48-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
- package/lessons/woowacourse-kotlin-blackjack/SeongHoonC/16-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +228 -0
- package/lessons/woowacourse-kotlin-blackjack/SeongHoonC/54-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +227 -0
- package/lessons/woowacourse-kotlin-blackjack/Yunseok-Nam/76-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
- package/lessons/woowacourse-kotlin-blackjack/Yunseok-Nam/86-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +203 -0
- package/lessons/woowacourse-kotlin-blackjack/aprilgom/105-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +162 -0
- package/lessons/woowacourse-kotlin-blackjack/aprilgom/64-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
- package/lessons/woowacourse-kotlin-blackjack/boogi-woogi/18-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
- package/lessons/woowacourse-kotlin-blackjack/boogi-woogi/36-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +769 -0
- package/lessons/woowacourse-kotlin-blackjack/briandr97/19-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +226 -0
- package/lessons/woowacourse-kotlin-blackjack/briandr97/59-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +193 -0
- package/lessons/woowacourse-kotlin-blackjack/chaehyuns/70-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +175 -0
- package/lessons/woowacourse-kotlin-blackjack/chaehyuns/98-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +206 -0
- package/lessons/woowacourse-kotlin-blackjack/chanho0908/123-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +277 -0
- package/lessons/woowacourse-kotlin-blackjack/chanho0908/150-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +219 -0
- package/lessons/woowacourse-kotlin-blackjack/chws0508/26-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +259 -0
- package/lessons/woowacourse-kotlin-blackjack/chws0508/43-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +189 -0
- package/lessons/woowacourse-kotlin-blackjack/cucumber99/109-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +351 -0
- package/lessons/woowacourse-kotlin-blackjack/cucumber99/149-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +147 -0
- package/lessons/woowacourse-kotlin-blackjack/devfeijoa/121-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +168 -0
- package/lessons/woowacourse-kotlin-blackjack/devfeijoa/153-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +116 -0
- package/lessons/woowacourse-kotlin-blackjack/doabletuple/126-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +680 -0
- package/lessons/woowacourse-kotlin-blackjack/doabletuple/142-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +739 -0
- package/lessons/woowacourse-kotlin-blackjack/donghyun81/116-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +297 -0
- package/lessons/woowacourse-kotlin-blackjack/donghyun81/147-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +244 -0
- package/lessons/woowacourse-kotlin-blackjack/dpcks0509/78-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +232 -0
- package/lessons/woowacourse-kotlin-blackjack/dpcks0509/88-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +137 -0
- package/lessons/woowacourse-kotlin-blackjack/etama123/112-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +269 -0
- package/lessons/woowacourse-kotlin-blackjack/etama123/148-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +240 -0
- package/lessons/woowacourse-kotlin-blackjack/gaeun5744/102-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +146 -0
- package/lessons/woowacourse-kotlin-blackjack/gaeun5744/69-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +224 -0
- package/lessons/woowacourse-kotlin-blackjack/gahyunkim/118-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +397 -0
- package/lessons/woowacourse-kotlin-blackjack/gahyunkim/141-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +215 -0
- package/lessons/woowacourse-kotlin-blackjack/giovannijunseokim/106-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +395 -0
- package/lessons/woowacourse-kotlin-blackjack/giovannijunseokim/134-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +219 -0
- package/lessons/woowacourse-kotlin-blackjack/haeum808/62-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +230 -0
- package/lessons/woowacourse-kotlin-blackjack/haeum808/89-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +169 -0
- package/lessons/woowacourse-kotlin-blackjack/hwannow/110-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +221 -0
- package/lessons/woowacourse-kotlin-blackjack/hwannow/132-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +573 -0
- package/lessons/woowacourse-kotlin-blackjack/hxeyexn/103-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
- package/lessons/woowacourse-kotlin-blackjack/hxeyexn/81-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +301 -0
- package/lessons/woowacourse-kotlin-blackjack/hyemdooly/21-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +613 -0
- package/lessons/woowacourse-kotlin-blackjack/hyemdooly/35-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +691 -0
- package/lessons/woowacourse-kotlin-blackjack/hyunji1203/13-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +206 -0
- package/lessons/woowacourse-kotlin-blackjack/ii2001/79-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +153 -0
- package/lessons/woowacourse-kotlin-blackjack/ii2001/85-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +318 -0
- package/lessons/woowacourse-kotlin-blackjack/ijh1298/128-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +250 -0
- package/lessons/woowacourse-kotlin-blackjack/ijh1298/135-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +269 -0
- package/lessons/woowacourse-kotlin-blackjack/inseonyun/28-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +346 -0
- package/lessons/woowacourse-kotlin-blackjack/inseonyun/49-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +360 -0
- package/lessons/woowacourse-kotlin-blackjack/ippnsj/30-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +152 -0
- package/lessons/woowacourse-kotlin-blackjack/ippnsj/42-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +213 -0
- package/lessons/woowacourse-kotlin-blackjack/jaeyeongjo/73-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +247 -0
- package/lessons/woowacourse-kotlin-blackjack/jaeyeongjo/87-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +900 -0
- package/lessons/woowacourse-kotlin-blackjack/jerry8282/125-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +248 -0
- package/lessons/woowacourse-kotlin-blackjack/jerry8282/151-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +243 -0
- package/lessons/woowacourse-kotlin-blackjack/jinuemong/63-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +281 -0
- package/lessons/woowacourse-kotlin-blackjack/jinuemong/92-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +283 -0
- package/lessons/woowacourse-kotlin-blackjack/jiyuneel/113-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +348 -0
- package/lessons/woowacourse-kotlin-blackjack/jiyuneel/140-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +265 -0
- package/lessons/woowacourse-kotlin-blackjack/junjange/61-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +270 -0
- package/lessons/woowacourse-kotlin-blackjack/junjange/93-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +465 -0
- package/lessons/woowacourse-kotlin-blackjack/junseo511/107-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +296 -0
- package/lessons/woowacourse-kotlin-blackjack/junseo511/145-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +316 -0
- package/lessons/woowacourse-kotlin-blackjack/ki960213/11-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +175 -0
- package/lessons/woowacourse-kotlin-blackjack/kimhm0728/72-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +458 -0
- package/lessons/woowacourse-kotlin-blackjack/kimhm0728/97-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +225 -0
- package/lessons/woowacourse-kotlin-blackjack/kkosang/68-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +221 -0
- package/lessons/woowacourse-kotlin-blackjack/kkosang/94-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +158 -0
- package/lessons/woowacourse-kotlin-blackjack/kmkim2689/65-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +252 -0
- package/lessons/woowacourse-kotlin-blackjack/kmkim2689/90-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +460 -0
- package/lessons/woowacourse-kotlin-blackjack/krrong/32-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +216 -0
- package/lessons/woowacourse-kotlin-blackjack/krrong/46-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +285 -0
- package/lessons/woowacourse-kotlin-blackjack/m6z1/122-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +177 -0
- package/lessons/woowacourse-kotlin-blackjack/m6z1/144-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +155 -0
- package/lessons/woowacourse-kotlin-blackjack/medAndro/130-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +683 -0
- package/lessons/woowacourse-kotlin-blackjack/medAndro/143-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +678 -0
- package/lessons/woowacourse-kotlin-blackjack/moondev03/114-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +262 -0
- package/lessons/woowacourse-kotlin-blackjack/moondev03/131-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +498 -0
- package/lessons/woowacourse-kotlin-blackjack/murjune/77-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +287 -0
- package/lessons/woowacourse-kotlin-blackjack/murjune/91-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +280 -0
- package/lessons/woowacourse-kotlin-blackjack/no1msh/31-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +250 -0
- package/lessons/woowacourse-kotlin-blackjack/otter66/24-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +302 -0
- package/lessons/woowacourse-kotlin-blackjack/otter66/58-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +391 -0
- package/lessons/woowacourse-kotlin-blackjack/oungsi2000/111-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
- package/lessons/woowacourse-kotlin-blackjack/oungsi2000/136-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +540 -0
- package/lessons/woowacourse-kotlin-blackjack/parkjiminnnn/117-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +819 -0
- package/lessons/woowacourse-kotlin-blackjack/parkjiminnnn/139-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +683 -0
- package/lessons/woowacourse-kotlin-blackjack/pingu244/20-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +258 -0
- package/lessons/woowacourse-kotlin-blackjack/pingu244/41-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +171 -0
- package/lessons/woowacourse-kotlin-blackjack/re4rk/34-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +289 -0
- package/lessons/woowacourse-kotlin-blackjack/re4rk/8-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +297 -0
- package/lessons/woowacourse-kotlin-blackjack/rhkrwngud445/17-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
- package/lessons/woowacourse-kotlin-blackjack/rhkrwngud445/50-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +145 -0
- package/lessons/woowacourse-kotlin-blackjack/rhthrhrl0/23-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
- package/lessons/woowacourse-kotlin-blackjack/rhthrhrl0/39-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +238 -0
- package/lessons/woowacourse-kotlin-blackjack/rosemin928/129-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +726 -0
- package/lessons/woowacourse-kotlin-blackjack/rosemin928/138-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +845 -0
- package/lessons/woowacourse-kotlin-blackjack/s6m1n/67-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +220 -0
- package/lessons/woowacourse-kotlin-blackjack/s6m1n/99-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +229 -0
- package/lessons/woowacourse-kotlin-blackjack/s9hn/10-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +284 -0
- package/lessons/woowacourse-kotlin-blackjack/sh1mj1/75-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +224 -0
- package/lessons/woowacourse-kotlin-blackjack/songpink/74-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +238 -0
- package/lessons/woowacourse-kotlin-blackjack/songpink/95-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +216 -0
- package/lessons/woowacourse-kotlin-blackjack/sujin9/15-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +132 -0
- package/lessons/woowacourse-kotlin-blackjack/sujin9/47-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +265 -0
- package/lessons/woowacourse-kotlin-blackjack/tmdgh1592/29-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +305 -0
- package/lessons/woowacourse-kotlin-blackjack/tmdgh1592/51-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +278 -0
- package/lessons/woowacourse-kotlin-blackjack/tobae-time/115-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +305 -0
- package/lessons/woowacourse-kotlin-blackjack/tobae-time/154-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +298 -0
- package/lessons/woowacourse-kotlin-blackjack/whk06061/25-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +235 -0
- package/lessons/woowacourse-kotlin-blackjack/whk06061/53-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +130 -0
- package/lessons/woowacourse-kotlin-blackjack/wondroid-world/124-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +486 -0
- package/lessons/woowacourse-kotlin-blackjack/wondroid-world/152-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +482 -0
- package/lessons/woowacourse-kotlin-blackjack/yrsel/120-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +194 -0
- package/lessons/woowacourse-kotlin-blackjack/yrsel/146-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +444 -0
- package/lessons/woowacourse-kotlin-lotto/2chang5/27-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
- package/lessons/woowacourse-kotlin-lotto/2chang5/52-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +187 -0
- package/lessons/woowacourse-kotlin-lotto/Choisehyeon/14-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +206 -0
- package/lessons/woowacourse-kotlin-lotto/Choisehyeon/47-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +119 -0
- package/lessons/woowacourse-kotlin-lotto/DYGames/2-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +83 -0
- package/lessons/woowacourse-kotlin-lotto/DYGames/34-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +88 -0
- package/lessons/woowacourse-kotlin-lotto/EmilyCh0/12-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
- package/lessons/woowacourse-kotlin-lotto/EmilyCh0/40-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +135 -0
- package/lessons/woowacourse-kotlin-lotto/HANDOVER.md +217 -0
- package/lessons/woowacourse-kotlin-lotto/HamBeomJoon/121-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
- package/lessons/woowacourse-kotlin-lotto/HamBeomJoon/139-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +75 -0
- package/lessons/woowacourse-kotlin-lotto/Hevton/76-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
- package/lessons/woowacourse-kotlin-lotto/Hevton/92-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +122 -0
- package/lessons/woowacourse-kotlin-lotto/Hogu59/100-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +110 -0
- package/lessons/woowacourse-kotlin-lotto/Hogu59/68-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +84 -0
- package/lessons/woowacourse-kotlin-lotto/JoYehyun99/60-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +176 -0
- package/lessons/woowacourse-kotlin-lotto/JoYehyun99/96-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +71 -0
- package/lessons/woowacourse-kotlin-lotto/Junyoung-WON/61-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
- package/lessons/woowacourse-kotlin-lotto/Junyoung-WON/93-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +16 -0
- package/lessons/woowacourse-kotlin-lotto/Leeyerin0210/109-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +57 -0
- package/lessons/woowacourse-kotlin-lotto/Leeyerin0210/135-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +115 -0
- package/lessons/woowacourse-kotlin-lotto/PROGRESS.md +160 -0
- package/lessons/woowacourse-kotlin-lotto/README.md +77 -0
- package/lessons/woowacourse-kotlin-lotto/RightHennessy/32-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
- package/lessons/woowacourse-kotlin-lotto/RightHennessy/5-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
- package/lessons/woowacourse-kotlin-lotto/SUMMARY.md +369 -0
- package/lessons/woowacourse-kotlin-lotto/SeongHoonC/25-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
- package/lessons/woowacourse-kotlin-lotto/SeongHoonC/37-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +27 -0
- package/lessons/woowacourse-kotlin-lotto/Yunseok-Nam/72-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +137 -0
- package/lessons/woowacourse-kotlin-lotto/Yunseok-Nam/86-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +17 -0
- package/lessons/woowacourse-kotlin-lotto/aprilgom/102-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +62 -0
- package/lessons/woowacourse-kotlin-lotto/aprilgom/64-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +146 -0
- package/lessons/woowacourse-kotlin-lotto/boogi-woogi/11-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
- package/lessons/woowacourse-kotlin-lotto/boogi-woogi/29-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
- package/lessons/woowacourse-kotlin-lotto/briandr97/26-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
- package/lessons/woowacourse-kotlin-lotto/briandr97/51-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +123 -0
- package/lessons/woowacourse-kotlin-lotto/chaehyuns/71-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +115 -0
- package/lessons/woowacourse-kotlin-lotto/chaehyuns/97-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
- package/lessons/woowacourse-kotlin-lotto/chanho0908/124-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +51 -0
- package/lessons/woowacourse-kotlin-lotto/chanho0908/129-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
- package/lessons/woowacourse-kotlin-lotto/chws0508/24-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +117 -0
- package/lessons/woowacourse-kotlin-lotto/chws0508/50-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +167 -0
- package/lessons/woowacourse-kotlin-lotto/cucumber99/116-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
- package/lessons/woowacourse-kotlin-lotto/cucumber99/147-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +223 -0
- package/lessons/woowacourse-kotlin-lotto/devfeijoa/125-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +68 -0
- package/lessons/woowacourse-kotlin-lotto/devfeijoa/153-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
- package/lessons/woowacourse-kotlin-lotto/doabletuple/119-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +157 -0
- package/lessons/woowacourse-kotlin-lotto/doabletuple/138-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +77 -0
- package/lessons/woowacourse-kotlin-lotto/donghyun81/111-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +67 -0
- package/lessons/woowacourse-kotlin-lotto/donghyun81/152-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
- package/lessons/woowacourse-kotlin-lotto/dpcks0509/80-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +141 -0
- package/lessons/woowacourse-kotlin-lotto/dpcks0509/87-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +134 -0
- package/lessons/woowacourse-kotlin-lotto/etama123/112-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +170 -0
- package/lessons/woowacourse-kotlin-lotto/etama123/148-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +183 -0
- package/lessons/woowacourse-kotlin-lotto/gaeun5744/101-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
- package/lessons/woowacourse-kotlin-lotto/gaeun5744/78-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +158 -0
- package/lessons/woowacourse-kotlin-lotto/gahyunkim/107-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +83 -0
- package/lessons/woowacourse-kotlin-lotto/gahyunkim/136-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +51 -0
- package/lessons/woowacourse-kotlin-lotto/giovannijunseokim/106-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +171 -0
- package/lessons/woowacourse-kotlin-lotto/giovannijunseokim/137-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +111 -0
- package/lessons/woowacourse-kotlin-lotto/haeum808/67-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
- package/lessons/woowacourse-kotlin-lotto/haeum808/95-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
- package/lessons/woowacourse-kotlin-lotto/hwannow/113-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +235 -0
- package/lessons/woowacourse-kotlin-lotto/hwannow/132-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
- package/lessons/woowacourse-kotlin-lotto/hxeyexn/77-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +141 -0
- package/lessons/woowacourse-kotlin-lotto/hxeyexn/98-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +162 -0
- package/lessons/woowacourse-kotlin-lotto/hyemdooly/17-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +19 -0
- package/lessons/woowacourse-kotlin-lotto/hyemdooly/28-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +23 -0
- package/lessons/woowacourse-kotlin-lotto/hyunji1203/15-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +171 -0
- package/lessons/woowacourse-kotlin-lotto/hyunji1203/48-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +150 -0
- package/lessons/woowacourse-kotlin-lotto/ii2001/62-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
- package/lessons/woowacourse-kotlin-lotto/ii2001/88-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
- package/lessons/woowacourse-kotlin-lotto/ijh1298/122-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +179 -0
- package/lessons/woowacourse-kotlin-lotto/ijh1298/133-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +153 -0
- package/lessons/woowacourse-kotlin-lotto/inseonyun/3-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +222 -0
- package/lessons/woowacourse-kotlin-lotto/inseonyun/49-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +166 -0
- package/lessons/woowacourse-kotlin-lotto/ippnsj/16-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +154 -0
- package/lessons/woowacourse-kotlin-lotto/ippnsj/55-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
- package/lessons/woowacourse-kotlin-lotto/jaeyeongjo/59-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +68 -0
- package/lessons/woowacourse-kotlin-lotto/jaeyeongjo/83-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +53 -0
- package/lessons/woowacourse-kotlin-lotto/jerry8282/115-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
- package/lessons/woowacourse-kotlin-lotto/jerry8282/134-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
- package/lessons/woowacourse-kotlin-lotto/jinuemong/63-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +144 -0
- package/lessons/woowacourse-kotlin-lotto/jinuemong/89-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +148 -0
- package/lessons/woowacourse-kotlin-lotto/jiyuneel/128-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
- package/lessons/woowacourse-kotlin-lotto/jiyuneel/144-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
- package/lessons/woowacourse-kotlin-lotto/junjange/58-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +148 -0
- package/lessons/woowacourse-kotlin-lotto/junjange/81-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
- package/lessons/woowacourse-kotlin-lotto/junseo511/120-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +153 -0
- package/lessons/woowacourse-kotlin-lotto/junseo511/131-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +188 -0
- package/lessons/woowacourse-kotlin-lotto/ki960213/43-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +24 -0
- package/lessons/woowacourse-kotlin-lotto/ki960213/8-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +159 -0
- package/lessons/woowacourse-kotlin-lotto/kimhm0728/74-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +50 -0
- package/lessons/woowacourse-kotlin-lotto/kimhm0728/94-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +176 -0
- package/lessons/woowacourse-kotlin-lotto/kkosang/85-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
- package/lessons/woowacourse-kotlin-lotto/kmkim2689/70-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
- package/lessons/woowacourse-kotlin-lotto/kmkim2689/82-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +157 -0
- package/lessons/woowacourse-kotlin-lotto/krrong/19-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +161 -0
- package/lessons/woowacourse-kotlin-lotto/krrong/41-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +73 -0
- package/lessons/woowacourse-kotlin-lotto/m6z1/105-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +67 -0
- package/lessons/woowacourse-kotlin-lotto/m6z1/151-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
- package/lessons/woowacourse-kotlin-lotto/medAndro/127-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +186 -0
- package/lessons/woowacourse-kotlin-lotto/medAndro/130-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +132 -0
- package/lessons/woowacourse-kotlin-lotto/moondev03/110-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
- package/lessons/woowacourse-kotlin-lotto/moondev03/141-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
- package/lessons/woowacourse-kotlin-lotto/murjune/69-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
- package/lessons/woowacourse-kotlin-lotto/murjune/90-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +177 -0
- package/lessons/woowacourse-kotlin-lotto/no1msh/20-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +69 -0
- package/lessons/woowacourse-kotlin-lotto/no1msh/46-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
- package/lessons/woowacourse-kotlin-lotto/otter66/13-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
- package/lessons/woowacourse-kotlin-lotto/otter66/53-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +160 -0
- package/lessons/woowacourse-kotlin-lotto/oungsi2000/126-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +71 -0
- package/lessons/woowacourse-kotlin-lotto/oungsi2000/149-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +56 -0
- package/lessons/woowacourse-kotlin-lotto/parkjiminnnn/117-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
- package/lessons/woowacourse-kotlin-lotto/parkjiminnnn/146-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +173 -0
- package/lessons/woowacourse-kotlin-lotto/pingu244/33-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
- package/lessons/woowacourse-kotlin-lotto/pingu244/54-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +30 -0
- package/lessons/woowacourse-kotlin-lotto/pingu244/7-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +19 -0
- package/lessons/woowacourse-kotlin-lotto/re4rk/31-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
- package/lessons/woowacourse-kotlin-lotto/re4rk/4-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
- package/lessons/woowacourse-kotlin-lotto/rhkrwngud445/23-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
- package/lessons/woowacourse-kotlin-lotto/rhkrwngud445/38-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
- package/lessons/woowacourse-kotlin-lotto/rhthrhrl0/21-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +146 -0
- package/lessons/woowacourse-kotlin-lotto/rhthrhrl0/36-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +150 -0
- package/lessons/woowacourse-kotlin-lotto/rosemin928/123-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +179 -0
- package/lessons/woowacourse-kotlin-lotto/rosemin928/140-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +126 -0
- package/lessons/woowacourse-kotlin-lotto/s6m1n/103-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +119 -0
- package/lessons/woowacourse-kotlin-lotto/s6m1n/66-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +118 -0
- package/lessons/woowacourse-kotlin-lotto/s9hn/18-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +112 -0
- package/lessons/woowacourse-kotlin-lotto/sh1mj1/75-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
- package/lessons/woowacourse-kotlin-lotto/sh1mj1/91-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +140 -0
- package/lessons/woowacourse-kotlin-lotto/songpink/65-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +96 -0
- package/lessons/woowacourse-kotlin-lotto/songpink/99-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +64 -0
- package/lessons/woowacourse-kotlin-lotto/sujin9/10-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
- package/lessons/woowacourse-kotlin-lotto/sujin9/35-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
- package/lessons/woowacourse-kotlin-lotto/tmdgh1592/22-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +30 -0
- package/lessons/woowacourse-kotlin-lotto/tmdgh1592/30-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
- package/lessons/woowacourse-kotlin-lotto/tobae-time/114-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +158 -0
- package/lessons/woowacourse-kotlin-lotto/tobae-time/145-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +120 -0
- package/lessons/woowacourse-kotlin-lotto/whk06061/42-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
- package/lessons/woowacourse-kotlin-lotto/whk06061/9-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +89 -0
- package/lessons/woowacourse-kotlin-lotto/wondroid-world/118-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +100 -0
- package/lessons/woowacourse-kotlin-lotto/wondroid-world/150-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +142 -0
- package/lessons/woowacourse-kotlin-lotto/yrsel/108-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
- package/lessons/woowacourse-kotlin-lotto/yrsel/143-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +108 -0
- package/lessons/woowacourse-racingcar/2chang5/33-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
- package/lessons/woowacourse-racingcar/2chang5/75-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/CFalws/85-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
- package/lessons/woowacourse-racingcar/Choisehyeon/46-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
- package/lessons/woowacourse-racingcar/DYGames/49-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
- package/lessons/woowacourse-racingcar/EmilyCh0/40-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +64 -0
- package/lessons/woowacourse-racingcar/EmilyCh0/57-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/HamBeomJoon/137-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/HamBeomJoon/170-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
- package/lessons/woowacourse-racingcar/Hevton/106-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/Hevton/118-/353/246/254/355/214/251/355/204/260/353/247/201.md +51 -0
- package/lessons/woowacourse-racingcar/Hogu59/108-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
- package/lessons/woowacourse-racingcar/Hogu59/125-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
- package/lessons/woowacourse-racingcar/JoYehyun99/111-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/JoYehyun99/88-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +45 -0
- package/lessons/woowacourse-racingcar/Junyoung-WON/127-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
- package/lessons/woowacourse-racingcar/Junyoung-WON/90-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
- package/lessons/woowacourse-racingcar/Leeyerin0210/133-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
- package/lessons/woowacourse-racingcar/Leeyerin0210/159-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/PROGRESS.md +94 -0
- package/lessons/woowacourse-racingcar/README.md +69 -0
- package/lessons/woowacourse-racingcar/RightHennessy/51-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/RightHennessy/58-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/RunaNam/81-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +44 -0
- package/lessons/woowacourse-racingcar/SUMMARY.md +339 -0
- package/lessons/woowacourse-racingcar/SeongHoonC/37-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/SeongHoonC/66-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
- package/lessons/woowacourse-racingcar/Songusika/84-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
- package/lessons/woowacourse-racingcar/Yunseok-Nam/114-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
- package/lessons/woowacourse-racingcar/Yunseok-Nam/96-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/aprilgom/130-/353/246/254/355/214/251/355/204/260/353/247/201.md +52 -0
- package/lessons/woowacourse-racingcar/aprilgom/97-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
- package/lessons/woowacourse-racingcar/awesomeo184/23-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
- package/lessons/woowacourse-racingcar/boogi-woogi/35-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
- package/lessons/woowacourse-racingcar/boogi-woogi/59-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/briandr97/54-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/chaehyuns/131-/353/246/254/355/214/251/355/204/260/353/247/201.md +49 -0
- package/lessons/woowacourse-racingcar/chaehyuns/99-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
- package/lessons/woowacourse-racingcar/chanho0908/147-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/chanho0908/160-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
- package/lessons/woowacourse-racingcar/chws0508/45-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
- package/lessons/woowacourse-racingcar/chws0508/73-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +46 -0
- package/lessons/woowacourse-racingcar/cucumber99/132-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/cucumber99/177-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/devfeijoa/146-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/doabletuple/149-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/doabletuple/175-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/donghyun81/154-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
- package/lessons/woowacourse-racingcar/dpcks0509/103-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
- package/lessons/woowacourse-racingcar/dpcks0509/112-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
- package/lessons/woowacourse-racingcar/drunkenhw/82-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
- package/lessons/woowacourse-racingcar/etama123/145-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
- package/lessons/woowacourse-racingcar/gaeun5744/124-/353/246/254/355/214/251/355/204/260/353/247/201.md +53 -0
- package/lessons/woowacourse-racingcar/gaeun5744/93-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
- package/lessons/woowacourse-racingcar/gahyunkim/134-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/gahyunkim/164-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/giovannijunseokim/140-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/haeum808/101-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/haeum808/129-/353/246/254/355/214/251/355/204/260/353/247/201.md +46 -0
- package/lessons/woowacourse-racingcar/hwannow/141-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
- package/lessons/woowacourse-racingcar/hwannow/157-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +45 -0
- package/lessons/woowacourse-racingcar/hxeyexn/109-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
- package/lessons/woowacourse-racingcar/hxeyexn/128-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
- package/lessons/woowacourse-racingcar/hyemdooly/50-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
- package/lessons/woowacourse-racingcar/hyemdooly/68-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/hyunji1203/29-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/hyunji1203/60-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
- package/lessons/woowacourse-racingcar/ii2001/102-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +42 -0
- package/lessons/woowacourse-racingcar/ii2001/122-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
- package/lessons/woowacourse-racingcar/ijh1298/144-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/injoon2019/24-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
- package/lessons/woowacourse-racingcar/inseonyun/44-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
- package/lessons/woowacourse-racingcar/inseonyun/76-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/ippnsj/36-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/ippnsj/67-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/jaeyeongjo/110-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +39 -0
- package/lessons/woowacourse-racingcar/jaeyeongjo/89-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +46 -0
- package/lessons/woowacourse-racingcar/jinuemong/104-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
- package/lessons/woowacourse-racingcar/jinuemong/117-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +42 -0
- package/lessons/woowacourse-racingcar/jiyuneel/142-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
- package/lessons/woowacourse-racingcar/junjange/113-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +41 -0
- package/lessons/woowacourse-racingcar/junjange/87-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +39 -0
- package/lessons/woowacourse-racingcar/junseo511/148-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
- package/lessons/woowacourse-racingcar/junseo511/165-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
- package/lessons/woowacourse-racingcar/ki960213/32-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/ki960213/63-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
- package/lessons/woowacourse-racingcar/kimhm0728/100-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
- package/lessons/woowacourse-racingcar/kimhm0728/116-/353/246/254/355/214/251/355/204/260/353/247/201.md +54 -0
- package/lessons/woowacourse-racingcar/kkosang/105-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/kkosang/126-/353/246/254/355/214/251/355/204/260/353/247/201.md +53 -0
- package/lessons/woowacourse-racingcar/kmkim2689/123-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
- package/lessons/woowacourse-racingcar/kmkim2689/92-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/krrong/34-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +63 -0
- package/lessons/woowacourse-racingcar/m6z1/150-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/m6z1/156-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +40 -0
- package/lessons/woowacourse-racingcar/medAndro/153-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/moondev03/135-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
- package/lessons/woowacourse-racingcar/moondev03/161-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
- package/lessons/woowacourse-racingcar/murjune/121-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
- package/lessons/woowacourse-racingcar/murjune/95-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/no1msh/43-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/no1msh/69-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
- package/lessons/woowacourse-racingcar/otter66/48-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/otter66/77-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
- package/lessons/woowacourse-racingcar/oungsi2000/152-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
- package/lessons/woowacourse-racingcar/oungsi2000/187-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/parkjiminnnn/143-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
- package/lessons/woowacourse-racingcar/parkjiminnnn/158-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/pingu244/38-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
- package/lessons/woowacourse-racingcar/pingu244/62-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
- package/lessons/woowacourse-racingcar/re4rk/28-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
- package/lessons/woowacourse-racingcar/re4rk/55-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/rhkrwngud445/42-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/rhkrwngud445/74-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +47 -0
- package/lessons/woowacourse-racingcar/rhthrhrl0/31-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
- package/lessons/woowacourse-racingcar/rosemin928/138-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/rosemin928/171-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +38 -0
- package/lessons/woowacourse-racingcar/s6m1n/120-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
- package/lessons/woowacourse-racingcar/s6m1n/91-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
- package/lessons/woowacourse-racingcar/s9hn/53-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +44 -0
- package/lessons/woowacourse-racingcar/s9hn/78-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
- package/lessons/woowacourse-racingcar/sh1mj1/107-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/sh1mj1/115-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
- package/lessons/woowacourse-racingcar/songpink/119-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
- package/lessons/woowacourse-racingcar/songpink/98-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
- package/lessons/woowacourse-racingcar/sujin9/52-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
- package/lessons/woowacourse-racingcar/sujin9/61-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +47 -0
- package/lessons/woowacourse-racingcar/tmdgh1592/47-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
- package/lessons/woowacourse-racingcar/tmdgh1592/64-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/tobae-time/151-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
- package/lessons/woowacourse-racingcar/tobae-time/167-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
- package/lessons/woowacourse-racingcar/whk06061/41-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
- package/lessons/woowacourse-racingcar/wondroid-world/136-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
- package/lessons/woowacourse-racingcar/wondroid-world/166-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
- package/lessons/woowacourse-racingcar/yrsel/139-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
- package/lessons/woowacourse-racingcar/yujamint/83-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
- package/package.json +46 -0
- package/skills/oh-my-oop/SKILL.md +39 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# PR #71 — [로또 1단계] 채채
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@chaehyuns](https://github.com/chaehyuns)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/71
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @KwonDae (제이든)
|
|
7
|
+
- **라인 코멘트:** 22
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`fun interface NumberGenerator`** — 테스트 가능 구조.
|
|
12
|
+
- **`PurchaseAmount`의 한정자 상수 분리** — 도메인 객체 응집.
|
|
13
|
+
- **자가 의문 PR에 풍부히 명시** — *일급 컬렉션의 비용*, *class vs object*, *WinningNumber 분리* 등.
|
|
14
|
+
|
|
15
|
+
## 못한 점 (설계 관점)
|
|
16
|
+
|
|
17
|
+
### 1. `LottoNumberGenerator`의 랜덤 내장
|
|
18
|
+
|
|
19
|
+
```kotlin
|
|
20
|
+
class LottoNumberGenerator : NumberGenerator {
|
|
21
|
+
override fun generate(): LottoNumbers = LottoNumbers.lottoNumbersOf(*(LOTTO_NUMBER_RANGE).shuffled().take(LOTTO_SIZE).sorted().toIntArray())
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
리뷰어: "랜덤의 요소가 변경되면 비즈니스 로직도 변경되어야 할까요? 로또뿐 아니라 랜덤 요소가 변경되어도 *랜덤 요소를 외부로부터 주입받아* LottoNumberGenerator 로직을 재사용 가능하게끔 해볼까요?"
|
|
26
|
+
|
|
27
|
+
### 2. `LottoNumbers` — 일급 컬렉션 wrapper만, 행위 부재
|
|
28
|
+
|
|
29
|
+
```kotlin
|
|
30
|
+
data class LottoNumbers(val numbers: List<LottoNumber>) {
|
|
31
|
+
init { require(numbers.size == LOTTO_SIZE) {. }; require(numbers.distinctBy { it.number }.size == LOTTO_SIZE) }
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
리뷰어: "LottoNumbers 객체가 이미 원시값을 포장한 값을 갖고, *검증 외에는 하는 일이 없네요*. 이 객체에서 할 수 있는 일을 가져오거나 혹은 *Lotto 내에서 private 하게 관리*될 수 있도록 하는 건 어떨까요?" + "중복된 번호에 대한 검증이 필요하다면 *자료구조*를 사용해 보는 건 어떨까요? *2인승 자동차* 비유" — 검증만 + 자료구조도 List → Set 추천.
|
|
36
|
+
|
|
37
|
+
### 3. `vararg numbers: Int` 팩토리
|
|
38
|
+
|
|
39
|
+
```kotlin
|
|
40
|
+
fun lottoNumbersOf(vararg numbers: Int): LottoNumbers = LottoNumbers(numbers.map { LottoNumber(it) }.toList())
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
리뷰어: "numbers를 매번 `vararg`를 이용한 이유가 있을까요? `List<Int>` 형태로 받으면 toList() 같은 converter가 없어도 될 것 같아요." 학생: "test 코드를 작성하면서 가변인자로 넣기 위해 하다 보니 List<Int> 형태로 넣을 생각을 못했던 거 같습니다!"
|
|
44
|
+
|
|
45
|
+
### 4. Controller가 `SPLIT_DELIMITER` 처리
|
|
46
|
+
|
|
47
|
+
```kotlin
|
|
48
|
+
val winningNumbers = Lotto(LottoNumbers(inputView.readWinningNumbers().split(SPLIT_DELIMITER).map { LottoNumber(it.toInt()) }))
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
리뷰어: "`SPLIT_DELIMITER`에 대한 관심은 Controller에서 갖고 있어야 할까요?" + "inputView로부터 이미 split된 값을 받기는 어려울까요?" — View 책임.
|
|
52
|
+
|
|
53
|
+
### 5. `OutputView`가 `lottos.lottos` 깊게 접근
|
|
54
|
+
|
|
55
|
+
```kotlin
|
|
56
|
+
fun printLottoNumbers(lottos: Lottos) {
|
|
57
|
+
lottos.lottos.forEach { lotto: Lotto ->
|
|
58
|
+
val resultLotto = lotto.lottoNumbers.numbers.joinToString(.)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
리뷰어: "lottos 내부의 MutableList라는 수정 가능한 타입의 정보에 접근하고 있는데요. 단순 원시값 포장만 하기보다 *일급 컬렉션 활용*하여 원하는 데이터를 요청하고 View에서 할 일을 진행해 보도록 수정해 볼까요?" — *Tell, Don't Ask*.
|
|
64
|
+
|
|
65
|
+
### 6. `PurchaseAmount`의 상수 외부 주입 부재
|
|
66
|
+
|
|
67
|
+
리뷰어: "현재는 로또 가격이 1000으로 고정되어 있어서 문제가 없지만 로또 가격이 인상되었다면, `validateNumberRange`를 검증하는 *비즈니스 로직 내부 코드도 변경*되어야 하고 테스트 코드도 변경되어야 합니다."
|
|
68
|
+
|
|
69
|
+
### 7. `Pair<Lotto, LottoNumber>` 반환
|
|
70
|
+
|
|
71
|
+
```kotlin
|
|
72
|
+
private fun generateWinningNumbers(): Pair<Lotto, LottoNumber> {. }
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
리뷰어: "지금은 Pair이기에 코드를 작성한 개발자가 pair.first, pair.second가 어떤 값을 가져오는지 알 수 있을 겁니다. 하지만 다른 개발자가 유지보수를 해야 한다면, Pair 값을 가져다 쓸 때 *어떤 값인지 알려면 여기까지 들어와서 파악*을 해야겠죠?" — 영구 사용은 *data class*.
|
|
76
|
+
|
|
77
|
+
### 8. `class LottoNumberGenerator` vs `object`
|
|
78
|
+
|
|
79
|
+
리뷰어: "해당 `LottoNumberGenerator`는 object로 활용이 가능할까요? 채채님의 class, object를 나누는 기준이 궁금합니다." — *상태 없음*이면 `object`.
|
|
80
|
+
|
|
81
|
+
### 9. 일급 컬렉션 *비용* — 학생 자가 의문
|
|
82
|
+
|
|
83
|
+
학생: "'일급 컬렉션을 사용하고 원시값을 포장하라' 라는 요구 사항을 지키기 위해 LottoNumber, LottoNumbers, Lotto, Lottos 등 여러 class를 생성. joinToString 등 여러 함수들을 사용하기 위해 코드의 *복잡도가 굉장히 증가*. 어디까지 캡슐화를 해야 하는지, 이것이 진정으로 도움이 되는지 저는 느끼지 못한 거 같습니다." 리뷰어: "일급 컬렉션을 사용하는 것이 *무조건적으로 장점만 존재*하는 게 아닙니다. 그에 따라 값을 가져오거나, 개별 클래스로 나누면서 *추가적인 구현이 필요*해지니까요. 하지만, *각자의 비즈니스 로직을 분리*하면서 캡슐화를 할 수 있어…"
|
|
84
|
+
|
|
85
|
+
## 리뷰어 의견 요지
|
|
86
|
+
|
|
87
|
+
- **랜덤 외부 주입** = 테스트 가능 구조.
|
|
88
|
+
- **일급 컬렉션은 *행위*가 있어야** — 검증만이면 *Lotto 내부 private*.
|
|
89
|
+
- **`Set`/자료구조로 *중복 불가* 표현**.
|
|
90
|
+
- **View 형식(`SPLIT_DELIMITER`)은 View 책임**.
|
|
91
|
+
- **`Pair`보다 data class** — 영구 사용 시.
|
|
92
|
+
- **상수 외부 주입** — 가격 변경 유연.
|
|
93
|
+
- **일급 컬렉션은 *트레이드오프*** — 비용 vs 캡슐화 가치.
|
|
94
|
+
|
|
95
|
+
- **대표 인용:**
|
|
96
|
+
> LottoNumbers 객체가 이미 원시값을 포장한 값을 갖고, *검증 외에는 하는 일이 없네요*.
|
|
97
|
+
> — @KwonDae on `src/main/kotlin/model/LottoNumbers.kt`
|
|
98
|
+
|
|
99
|
+
> `SPLIT_DELIMITER`에 대한 관심은 Controller에서 갖고 있어야 할까요?
|
|
100
|
+
> — @KwonDae on `src/main/kotlin/controller/LottoController.kt`
|
|
101
|
+
|
|
102
|
+
> 다른 개발자가 유지보수를 해야 한다면, Pair 값을 가져다 쓸 때 어떤 값인지 알려면 여기까지 들어와서 파악을 해야겠죠?
|
|
103
|
+
> — @KwonDae on `src/main/kotlin/controller/LottoController.kt`
|
|
104
|
+
|
|
105
|
+
## 얻은 교훈
|
|
106
|
+
|
|
107
|
+
- **랜덤 *외부 주입*** = 테스트 가능 구조.
|
|
108
|
+
- **일급 컬렉션의 *정당화*는 행위** — 검증만이면 *Lotto 내부 private*.
|
|
109
|
+
- ***자료구조 선택*이 invariant 표현** — `Set<LottoNumber>`로 중복 불가 명시.
|
|
110
|
+
- **View 책임 = 입력 형식 변환** — `","` split은 View가, 도메인은 *완성된 데이터*.
|
|
111
|
+
- **`Tell, Don't Ask` 적용 시 OutputView가 깊은 접근 회피**.
|
|
112
|
+
- **상수 외부 주입** — 도메인 정책 변경에 유연.
|
|
113
|
+
- **`Pair`는 일회용**, 영구는 *data class* + 의미 있는 필드명.
|
|
114
|
+
- **class vs object = 상태 유무** — *상태 없음*이면 object.
|
|
115
|
+
- **일급 컬렉션은 *비용*과 *가치*의 trade-off** — 무조건적인 적용 X.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# PR #97 — [로또 2단계] 채채
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@chaehyuns](https://github.com/chaehyuns)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/97
|
|
5
|
+
- **단계:** 2단계 (수동 로또 추가)
|
|
6
|
+
- **리뷰어:** @KwonDae (제이든)
|
|
7
|
+
- **라인 코멘트:** 22
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`LottoNumber.from()` Flyweight** — 1단계 리뷰 반영.
|
|
12
|
+
- **`Lottos`/`LottoStore`/`WinningPrizeCalculator`** 분리 시도.
|
|
13
|
+
- **`NumberGenerator` 인터페이스 + 테스트용 Fake** — 랜덤 격리.
|
|
14
|
+
- **자가 의문 PR에 풍부히 명시** — *WinningLotto 책임 부재*, *List<List<String>> vs List<Lotto>*, *class vs object* 등.
|
|
15
|
+
|
|
16
|
+
## 못한 점 (설계 관점)
|
|
17
|
+
|
|
18
|
+
### 1. `WinningLotto`가 *검증만* — 행위 부재
|
|
19
|
+
|
|
20
|
+
```kotlin
|
|
21
|
+
class WinningLotto(val winningNumbers: Lotto, val bonusNumber: LottoNumber) {
|
|
22
|
+
init { require(!winningNumbers.getMatchBonus(bonusNumber)) }
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
학생: "WinningLotto를 생성하여서 winningNumbers와 bonusNumber를 저장. 하지만 객체를 만들고 나니 이 객체는 *검증만* 하는 역할만 존재하고 다른 역할은 존재하지 않음." 리뷰어: "Controller 입장에서 winningLotto에 대한 정보, profitAmount, profitRate에 대한 관심이 필요할까요? Controller는 단지 *명령만* 내릴 뿐입니다. WinningLotto가 스스로 판단하여 *당첨번호 갯수, 당첨금, 수익률* 같은 정보들을 갖고 있다면 return되는 WinningLotto만을 가지고 활용할 수 있겠네요." — *Tell, Don't Ask* 강조.
|
|
27
|
+
|
|
28
|
+
### 2. `LottoStore.generateManualLottos(List<List<String>>)` — 이중 컬렉션
|
|
29
|
+
|
|
30
|
+
```kotlin
|
|
31
|
+
fun generateManualLottos(manualLottoNumbers: List<List<String>>) {
|
|
32
|
+
manualLottoNumbers.forEach { lottoNumbers ->
|
|
33
|
+
val lotto = Lotto.lottoNumbersOf(lottoNumbers)
|
|
34
|
+
lottos.add(lotto)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
학생 자가 의문: "step1 리뷰를 바탕으로 ',' split을 view에서 하는 게 맞다는 판단. 그렇기에 List<List<String>>을 사용해서 [1,2,3,4,5,6],[1,2,3,4,5,6] 이런 식으로 받아올 수밖에 없는데." 리뷰어: "List<List<String>>을 보면 동료 개발자가 처음 이 코드를 보았을 때 이해하기 쉬울까요? 또한, LottoStore에서 Collection을 정제하는 게 좋은 걸까요? InputView로부터 입력받을 때 지금 채채가 만들어 놓은 Lotto를 활용하여, *List<Lotto>*를 받도록 하는 건 어떨까요?"
|
|
40
|
+
|
|
41
|
+
### 3. `Lottos`의 책임이 `WinningLotto`에 가깝지 않은가
|
|
42
|
+
|
|
43
|
+
```kotlin
|
|
44
|
+
class Lottos(val lottos: MutableList<Lotto> = mutableListOf()) {
|
|
45
|
+
fun winningResult(winningLotto: WinningLotto): Map<WinningRank, Int> {. }
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
리뷰어: "`fun winningResult` 함수도 WinningLotto에서 수행할 수 있을까요? 그럼 Lottos의 클래스가 필요할까요? 사용자가 발행한 로또에 대한 정보(List<Lotto>), 구매 금액 같은 *여러 곳에서 사용할 공통 도메인 모델*을 의미 있게 만들어 보는 건 어떨까요? *hint. 현실에서도 로또 티켓 한 장 안에 어떤 정보들이 담겨 있을까요?*"
|
|
50
|
+
|
|
51
|
+
### 4. `LottoStore.lottos` 외부 노출
|
|
52
|
+
|
|
53
|
+
```kotlin
|
|
54
|
+
class LottoStore(.) {
|
|
55
|
+
var lottos = Lottos()
|
|
56
|
+
private set
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`private set`이지만 *getter*가 외부 노출. Controller가 `lottoStore.lottos`를 직접 사용. → *Tell, Don't Ask* 위반.
|
|
61
|
+
|
|
62
|
+
### 5. `WinningRank` 분기 + DEFAULT_COUNT
|
|
63
|
+
|
|
64
|
+
```kotlin
|
|
65
|
+
WinningRank.entries.forEach { rank ->
|
|
66
|
+
if (rank != WinningRank.NONE) {
|
|
67
|
+
outputView.printRankStatistics(rank, rankCounts[rank] ?: DEFAULT_COUNT)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
리뷰어 첫 코멘트의 후속: "WinningLotto가 *수익률·통계* 메서드를 가지면 Controller에서 *NONE 제외 + DEFAULT_COUNT 분기*가 사라짐."
|
|
73
|
+
|
|
74
|
+
### 6. `class LottoNumberGenerator` vs `object` — 학생 자가 의문
|
|
75
|
+
|
|
76
|
+
학생: "LottoNumberGenerator는 Test 코드에서 TestNumberGenerator을 만들어서 랜덤 값을 제어하기 위한 수단으로 주생성자로 선언해서 관리하고 싶어서 class로 구현." 리뷰어: "class와 object 차이는 *인스턴스화를 통해 객체를 생성, Singleton instance로 생성하는 관점*에 있습니다. 인스턴스화를 통한 객체를 생성하게 되면 *생성하는 객체마다 다른 state*. 현재는 LottoNumberGenerator는 인스턴스화를 통한 각 객체마다의 state가 다를까요? fun generate를 통해 제어." — *상태 유무*가 1차 기준.
|
|
77
|
+
|
|
78
|
+
### 7. `.gitkeep` 잔존
|
|
79
|
+
|
|
80
|
+
리뷰어: "이 파일은 이제 없어도 될 것 같네요!" — 폴더 구조 확정 후 정리.
|
|
81
|
+
|
|
82
|
+
## 리뷰어 의견 요지
|
|
83
|
+
|
|
84
|
+
- **Tell, Don't Ask** — Controller가 *winningLotto의 정보*에 관심 가지면 잘못된 위임.
|
|
85
|
+
- **`Lottos` vs `WinningLotto`** — 매칭/통계는 *WinningLotto*가 자연.
|
|
86
|
+
- **이중 컬렉션 회피** — View가 `List<Lotto>`로 변환 후 도메인에 전달.
|
|
87
|
+
- **`Tell, Don't Ask` 적용 후 Controller가 분기 사라짐**.
|
|
88
|
+
- **class vs object = *state 유무***.
|
|
89
|
+
|
|
90
|
+
- **대표 인용:**
|
|
91
|
+
> Controller 입장에서 winningLotto에 대한 정보, profitAmount, profitRate에 대한 관심이 필요할까요? Controller는 단지 명령만 내릴 뿐입니다.
|
|
92
|
+
> — @KwonDae on `src/main/kotlin/lotto/controller/LottoController.kt`
|
|
93
|
+
|
|
94
|
+
> 사실 지금은 검증만 하고 있기에 단순 wrapping class에 불과합니다. 하지만 WinningLotto에서 과연 할 수 있는 게 정말 없을까요?
|
|
95
|
+
> — @KwonDae on `src/main/kotlin/lotto/model/WinningLotto.kt`
|
|
96
|
+
|
|
97
|
+
> InputView로부터 입력받을 때 지금 채채가 만들어 놓은 Lotto를 활용하여, *List<Lotto>*를 받도록 하는 건 어떨까요?
|
|
98
|
+
> — @KwonDae on `src/main/kotlin/lotto/model/LottoStore.kt`
|
|
99
|
+
|
|
100
|
+
## 얻은 교훈
|
|
101
|
+
|
|
102
|
+
- **검증만 하는 wrapper는 객체가 아님** — `WinningLotto`가 *발행, 매칭, 통계*까지 갖고 가면 진짜 객체.
|
|
103
|
+
- **Tell, Don't Ask 적용 후 Controller는 *명령만***. 매번 *정보 조회 후 분기*는 책임이 잘못된 신호.
|
|
104
|
+
- **이중 컬렉션은 의도 모호** — View에서 `List<Lotto>`까지 변환 후 도메인에 전달.
|
|
105
|
+
- **공통 도메인 모델 ≠ 컬렉션 wrapping** — *Ticket*에 *발행 정보 + 구매 금액*까지 들고 가면 *여러 곳에서 사용할 공통*이 됨.
|
|
106
|
+
- **class vs object = 상태 유무**. *상태 없음*이면 `object`. *각 인스턴스마다 state 다름*이면 `class`.
|
|
107
|
+
- **`.gitkeep`은 *폴더 비어 있을 때*만 의미** — 채워졌으면 제거.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# PR #124 — [로또 1단계] 페토 미션
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@chanho0908](https://github.com/chanho0908)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/124
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @laco-dev
|
|
7
|
+
- **라인 코멘트:** 45
|
|
8
|
+
|
|
9
|
+
## 잘한 점
|
|
10
|
+
|
|
11
|
+
- **PR 본문에 자가 의문** — View → Domain 의존 의문.
|
|
12
|
+
|
|
13
|
+
## 못한 점 + 핵심 지적
|
|
14
|
+
|
|
15
|
+
### 1. View → Domain 의존 의문
|
|
16
|
+
|
|
17
|
+
학생:
|
|
18
|
+
|
|
19
|
+
> 이럼에도 불구하고 View가 domain을 직접 의존해도 된다는 근거가 (정말! 순수한 궁금증!) 조심스래 궁금합니다
|
|
20
|
+
|
|
21
|
+
리뷰어:
|
|
22
|
+
|
|
23
|
+
> 단순하게 도메인을 출력하는 것이 UI의 역할이기 때문이에요. 도메인 없이 그냥 출력만 한다면 뭘 출력할건데? 라는 생각을 할 수 있겠죠.
|
|
24
|
+
|
|
25
|
+
→ Domain 모름 → 출력할 게 없음. View → Domain 의존은 *자연*.
|
|
26
|
+
|
|
27
|
+
### 2. `PurchasePrice`에 LOTTO_PRICE 1000원 박힘
|
|
28
|
+
|
|
29
|
+
```kotlin
|
|
30
|
+
class PurchasePrice(val amount: Int) {
|
|
31
|
+
fun ticketCount(): Int = amount / 1000 // ⚠ 1000원이 여기?
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
> 로또 한장의 가격이 1,000원이라는 것을 이 곳에서 결정하는게 적절할까? 라는 생각이 드네요. A 상점에서는 1,000원 B 상점에서는 2,000원에 팔아야 한다면.? 그렇다면 로또 한장의 가격은 누구의 책임이라고 봐야 할지 애매하군요!
|
|
36
|
+
|
|
37
|
+
→ Lotto 자체 또는 *상점*의 책임이 더 자연. 구매 가격은 *그 자체*만.
|
|
38
|
+
|
|
39
|
+
### 3. `assertThrows { }` 미사용
|
|
40
|
+
|
|
41
|
+
```kotlin
|
|
42
|
+
try { PurchasePrice(-1) } catch (e:.) {. }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
→ `assertThrows<IllegalArgumentException> { PurchasePrice(-1) }`.
|
|
46
|
+
|
|
47
|
+
## 얻은 교훈
|
|
48
|
+
|
|
49
|
+
- **View → Domain 의존은 OK** — Domain 없이 출력할 게 없음. *Domain → View*만 금지.
|
|
50
|
+
- **로또 한장 가격의 책임자 의문** — 누가 가격 정책 소유? 미션에선 단일이지만 미래 가변성.
|
|
51
|
+
- **`assertThrows<T> { }`** = 코틀린 idiom.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# PR #129 — [2단계 - 로또] 라이언
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@chanho0908](https://github.com/chanho0908)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/129
|
|
5
|
+
- **단계:** 2단계 (수동 로또 추가)
|
|
6
|
+
- **리뷰어:** @laco-dev (페로로)
|
|
7
|
+
- **라인 코멘트:** 39
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`fun interface LottoMachine { fun generate(): Lotto }`** — 단일 추상 메서드를 SAM으로 표현, 람다 주입 가능.
|
|
12
|
+
- **`PassivityLottoAmount`/`ManualLottoAmount` `value class` + `private constructor`** — 원시값 포장 + 검증 강제.
|
|
13
|
+
- **`LottoOrderRequest`(주문서)로 입력을 한 객체에 묶음** — 리뷰어 제안 수용해서 *수동/자동 발급 흐름이 Controller에 섞인 문제*를 해소 시도.
|
|
14
|
+
- **Rank의 `requiresBonusMatch` 분기 도입** — `Rank.SECOND`를 enum 사용처에서 하드코딩하지 않음.
|
|
15
|
+
- **`Lotto.contains(bonusNumber)`로 의도 표현** — `value in list.map { it.value }` 같은 변환을 제거.
|
|
16
|
+
|
|
17
|
+
## 못한 점 (설계 관점)
|
|
18
|
+
|
|
19
|
+
### 1. `value class PassivityLottoAmount`가 `PurchasePrice`까지 알아야 함
|
|
20
|
+
|
|
21
|
+
```kotlin
|
|
22
|
+
value class PassivityLottoAmount private constructor(val value: Int) {
|
|
23
|
+
companion object {
|
|
24
|
+
fun create(value: Int, money: PurchasePrice): PassivityLottoAmount {
|
|
25
|
+
val purchasableAmount = money.getPurchasableLottoCount()
|
|
26
|
+
require(value <= purchasableAmount) { INVALID_PASSIVITY_LOTTO_SIZE }
|
|
27
|
+
return PassivityLottoAmount(value)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
리뷰어: "개수를 고려할 거면 수동, 자동 로또 개수를 모두 관리하는 객체를 만드는 게 맞지 않을까요? 수동은 클래스로 만들고 자동은 따로 관리하는 이유가 궁금합니다." 추가로: "수동 로또는 몇 장을 살 건지만 관심사고, 실제로 살 수 있는지 못 사는지는 Price 쪽에서 이미 판단하고 있으니 문제없지 않을까요?" — 검증을 *원시값 포장 객체*에 욱여넣으면서 `Money`에 다시 의존 → 관계 역전.
|
|
34
|
+
|
|
35
|
+
### 2. `LottoGenerator.validateMoney(money)` — 인터페이스 분리 위반
|
|
36
|
+
|
|
37
|
+
```kotlin
|
|
38
|
+
interface LottoGenerator {
|
|
39
|
+
fun generate(quickPickLottoAmount: Int): List<Lotto>
|
|
40
|
+
fun validateMoney(money: PurchasePrice) // ⚠ 테스트 fake가 안 쓰는 메서드 override
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
학생도 자가 의문: "테스트 코드의 `FakeLottoNumberGenerator`에서 사용하지 않는 `validate` 함수를 오버라이드하는 현상이 발생했습니다. 이 경우 인터페이스 분리 원칙(ISP)을 위반하는 것이 아닌가?" — 리뷰어: "근본적으로 돈을 검증하기 위해서 PurchasePrice를 만든 건데 이걸 왜 다시 검증하고 있는 건가요?? 검증된 금액을 LottoGenerator로 넣으면 문제없지 않나요?"
|
|
45
|
+
|
|
46
|
+
### 3. `LottoMatchResult.getWinningCount(rank)`가 미존재 키에 예외
|
|
47
|
+
|
|
48
|
+
```kotlin
|
|
49
|
+
class LottoMatchResult(private val winningCountByRank: Map<Rank, Int>) {
|
|
50
|
+
fun getWinningCount(rank: Rank): Int =
|
|
51
|
+
winningCountByRank[rank] ?: throw IllegalArgumentException(NOT_EXIST_RANK.format(rank))
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
학생 의도: "당첨 순위가 없을 때 == 프로그램을 의도적으로 에러를 발생시킬 만큼 치명적인 상황." 리뷰어: "왜 0이 의미없는 값이라고 생각하시는지 궁금하네요. 당연히 갯수가 아무것도 없다면 0이 나올 것이 자연스럽게 느껴지지 않나요?" — 도메인 어휘에서 *0건*은 자연스러운 상태. 그것에 예외를 띄우면 호출자가 정상 흐름을 try/catch로 감싸게 됨.
|
|
56
|
+
|
|
57
|
+
### 4. `LottoOrderRequest`가 생성된 `List<Lotto>`를 들고 있음
|
|
58
|
+
|
|
59
|
+
```kotlin
|
|
60
|
+
data class LottoOrderRequest(
|
|
61
|
+
val money: PurchasePrice,
|
|
62
|
+
val amount: PassivityLottoAmount,
|
|
63
|
+
val passiveLottoNumber: List<Lotto>, // ⚠ 이미 만들어진 Lotto
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
리뷰어: "아직 주문서라면 로또를 만들기 전일 텐데 Lotto가 생성자에 담겨 있는 게 어색하지 않을까요? 손님 입장이라면 로또 번호를 넘겨줄 텐데, 그렇지 않고 만들어진 로또를 넘겨준다?" — *주문서 vs 발행물* 구분이 흐려짐. 주문서는 *의도*만, Lotto는 *결과*.
|
|
68
|
+
|
|
69
|
+
### 5. `WinningLotto.getRank(buyLotto.numbers)` — Lotto 내부 직접 접근
|
|
70
|
+
|
|
71
|
+
```kotlin
|
|
72
|
+
private fun getRank(buyLotto: List<LottoNumber>): Rank {
|
|
73
|
+
val lottoMatches = buyLotto.intersect(winningLottoNumbers).size
|
|
74
|
+
val isBonusMatched = buyLotto.contains(bonusNumber)
|
|
75
|
+
.
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
리뷰어: "Lotto가 스스로 가지고 있는 numbers에 직접 접근해서 비즈니스 로직을 처리하는 부분이 조금 아쉽습니다. 지금 Lotto 클래스가 아무런 역할이 없는 것 같아서, 메시지를 전달하는 연습을 조금만 더 해 봅시다. Lotto 객체에게 일치하는 개수는 몇 개인지 알려달라고 메시지를 전달해 보세요." — Tell, Don't Ask. `lotto.countMatches(winningNumbers)`.
|
|
80
|
+
|
|
81
|
+
### 6. `sealed class LottoException` — 모든 도메인 오류를 커스텀 sealed로
|
|
82
|
+
|
|
83
|
+
```kotlin
|
|
84
|
+
sealed class LottoException(override val message: String?) : Throwable(message) {
|
|
85
|
+
class InvalidLottoSize : LottoException(INVALID_LOTTO_SIZE)
|
|
86
|
+
class DuplicatedLottoSize : LottoException(DUPLICATED_LOTTO_NUMBERS)
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
리뷰어: "흔히 사용하는 IllegalArgumentException, IllegalStateException 같은 예외 대비 얼마나 이점이 있는지는 잘 모르겠군요. 오류마다 전부 개별적으로 핸들링을 해야 한다면 필요한 게 맞습니다. 그런데 else 케이스도 고려해야 한다는 점도 있습니다." — Custom Exception의 비용(switch의 else, 호출자 부담)을 학생도 결국 수긍.
|
|
91
|
+
|
|
92
|
+
### 7. `PurchasePrice` — 생성자가 `init`만, 함수가 다 함
|
|
93
|
+
|
|
94
|
+
```kotlin
|
|
95
|
+
class PurchasePrice(val value: Int, standardPrice: Int = STANDARD_AMOUNT_UNIT) {
|
|
96
|
+
init { if (value <= 0 && value < standardPrice) throw OverStandardPriceException(standardPrice) }
|
|
97
|
+
fun getPurchasableLottoCount(standardPrice: Int = STANDARD_AMOUNT_UNIT): Int = value / standardPrice
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
리뷰어: "지금은 생성자가 단순 검증만 하고 아무런 기능을 하지 않는데요. 함수로 받는다면 오히려 생성자도 불필요한 게 맞습니다. 반대로 생성자로 한다면, 생성자를 활용하는 게 좋을 것 같아요." 추가: 조건도 잘못 — `value <= 0 && value < standardPrice`는 잘못된 논리(`&&` → `||`).
|
|
102
|
+
|
|
103
|
+
### 8. `check` vs `if-throw` 혼동
|
|
104
|
+
|
|
105
|
+
```kotlin
|
|
106
|
+
check(value >= standardPrice) {. }
|
|
107
|
+
check(numbers.size == this.numbers.size) { throw LottoException.DuplicatedLottoSize() }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
리뷰어: "check 함수가 받는 파라미터가 무엇인지 살펴보셨나요? check 함수가 내부에서 무슨 일을 하고 있는지 찾아보세요." — `check` 자체가 `IllegalStateException`을 던지는 함수인데 람다 안에서 또 throw → 이중 예외.
|
|
111
|
+
|
|
112
|
+
### 9. `value class` + `equals`/`hashCode` 인지 부재
|
|
113
|
+
|
|
114
|
+
학생 자가 학습: "테스트 과정에서 value class는 동일성 검사를 할 수 없다는 것을 확인" — value class 도입의 트레이드오프(인라인 + 동일성 의미 변화)를 사전에 검토하지 않음.
|
|
115
|
+
|
|
116
|
+
## 리뷰어 의견 요지
|
|
117
|
+
|
|
118
|
+
1. **검증 책임은 *값 객체*가 갖되, 다른 값 객체에 의존하지 말 것** — `PurchasePrice`가 가능 수량을 계산하면 `ManualLottoAmount`는 그 결과를 *비교* 하는 게 아니라, *Money - manualCount = autoCount* 같이 호출자가 조합.
|
|
119
|
+
2. **value class의 `value`를 풀어내지 마라** — `getPurchasableLottoCount(): Int`처럼 *원시값 반환*은 포장 의미 소실. `Count` 같은 타입으로 유지.
|
|
120
|
+
3. ***주문서*는 의도, *발행물*은 결과** — 두 개념을 한 객체에 섞으면 시간차 무결성이 깨짐.
|
|
121
|
+
4. **`Tell, Don't Ask`** — Lotto 자체에 `matchCount(other)`, `contains(number)`를 두고 외부는 메시지만 전달.
|
|
122
|
+
5. **Custom Exception은 *분기 처리가 필요할 때*만** — 그렇지 않으면 호출자에게 `else` 처리 부담만 안김.
|
|
123
|
+
6. **`check`/`require`는 Kotlin 표준 어휘** — 람다 안에 다시 throw하면 의도 충돌.
|
|
124
|
+
7. **`null`을 view 내부에서 *재시도*로 흡수** — 비논리적 오류는 *재입력 흐름*, 논리적 오류는 *예외*. 두 흐름을 try-catch 한 그릇에 담지 않음.
|
|
125
|
+
|
|
126
|
+
- **대표 인용:**
|
|
127
|
+
> 근본적으로 돈을 검증하기 위해서 PurchasePrice를 만든 건데 이걸 왜 다시 검증하고 있는 건가요?? 검증된 금액을 LottoGenerator로 넣으면 문제없지 않나요?
|
|
128
|
+
> — @laco-dev on `src/main/kotlin/domain/service/LottoGenerator.kt`
|
|
129
|
+
|
|
130
|
+
> Lotto가 스스로 가지고 있는 numbers에 직접 접근해서 비즈니스 로직을 처리하는 부분이 조금 아쉽습니다. … Lotto 객체에게 일치하는 개수는 몇 개인지 알려달라고 메시지를 전달해 보세요.
|
|
131
|
+
> — @laco-dev on `src/main/kotlin/domain/model/winning/WinningLotto.kt`
|
|
132
|
+
|
|
133
|
+
> 아직 주문서라면 로또를 만들기 전일 텐데 Lotto가 생성자에 담겨 있는 게 어색하지 않을까요?
|
|
134
|
+
> — @laco-dev on `src/main/kotlin/domain/model/LottoOrderRequest.kt`
|
|
135
|
+
|
|
136
|
+
> 당연히 갯수가 아무것도 없다면 0이 나올 것이 자연스럽게 느껴지지 않나요?
|
|
137
|
+
> — @laco-dev on `src/main/kotlin/domain/model/LottoMatchResult.kt`
|
|
138
|
+
|
|
139
|
+
## 얻은 교훈
|
|
140
|
+
|
|
141
|
+
- **값 객체의 검증은 *자기 자신만의 invariant*에 한정**. 다른 값 객체의 가능 수량까지 자기가 알면 그 두 객체가 결합. `PurchasePrice → 가능 수량`만 알고, `manualCount`는 호출자에서 빼서 `autoCount` 만든다.
|
|
142
|
+
- **인터페이스에 모든 도메인 검증을 얹지 말 것**. Fake/Stub에서 빈 override가 생기면 ISP 위반의 *직접 증거*.
|
|
143
|
+
- **0건은 자연스러운 도메인 상태**. 정상 경로에서 도달 가능한 상태를 예외로 만들면 호출자가 try/catch로 정상 흐름을 둘러쌈.
|
|
144
|
+
- ***주문서 vs 발행물* 분리**. 의도 단계의 객체에 결과 단계의 객체를 끼우면 시간차 무결성 + 책임 혼선.
|
|
145
|
+
- **`Tell, Don't Ask`는 컬렉션도 동일**. `lotto.numbers.intersect(other.numbers).size` → `lotto.matchCount(other)`. 외부는 의도만, 계산은 본인이.
|
|
146
|
+
- **Custom Exception 분기의 *비용*은 `else`**. sealed로 닫아도 호출자가 모든 분기 + else를 처리해야 하면 가독성 가치가 사라짐. `IllegalArgumentException` + 의미 있는 메시지가 더 나은 경우가 많음.
|
|
147
|
+
- **`check`/`require` 자체가 예외를 던진다**. 람다 인자는 *메시지 빌더*지 *던지는 곳*이 아님. 두 번 던지면 한 번은 무의미.
|
|
148
|
+
- **value class는 *동일성 의미가 변한다*는 트레이드오프 동반**. 도입 전에 `==`/`===` 의도와 동작 차이를 점검.
|
|
149
|
+
- **`null` + 재시도 vs `try-catch` + 재시도** — 함수 호출 흐름이 5~10단계 이상이면 `try-catch`로 둘러싸는 비용이 폭증. *비논리적 오류*는 호출 위치에서 `null`로 표현하고 재입력. 정말 *치명적인 논리적 오류*만 예외.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# PR #24 — [스캇] 1단계 로또
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@chws0508](https://github.com/chws0508)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/24
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @BeokBeok
|
|
7
|
+
- **라인 코멘트:** 21
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`Rank` enum + `(countOfMatch, winningMoney)`** — 등수/상금 한 곳.
|
|
12
|
+
- **`BonusNumber`/`LottoNumber` 원시값 포장**.
|
|
13
|
+
- **자가 의문 PR에 풍부히 명시** — *매칭 개수의 책임* 등.
|
|
14
|
+
|
|
15
|
+
## 못한 점 (설계 관점)
|
|
16
|
+
|
|
17
|
+
### 1. `check(countOfMatch, matchBonus, rank)` — 함수명 모호
|
|
18
|
+
|
|
19
|
+
```kotlin
|
|
20
|
+
companion object {
|
|
21
|
+
fun valueOf(countOfMatch: Int, matchBonus: Boolean): Rank? {
|
|
22
|
+
return values().find { rank -> check(countOfMatch, matchBonus, rank) }
|
|
23
|
+
}
|
|
24
|
+
private fun check(countOfMatch: Int, matchBonus: Boolean, rank: Rank): Boolean {. }
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
리뷰어: "함수명만 봤을 때에는 무엇을 '체크'하는지 알기가 어렵네요. 함수가 하는 일에 대해서 좀 더 명확하게 작성해 보면 어떨까요?" 학생: "checkRankCondition으로 변경." — `check*`는 *검증 행위* 시사, 의미가 *boolean 반환의 술어*면 `is*`/`matches*`.
|
|
29
|
+
|
|
30
|
+
### 2. 매직리터럴 in `check`
|
|
31
|
+
|
|
32
|
+
```kotlin
|
|
33
|
+
private fun check(countOfMatch: Int, matchBonus: Boolean, rank: Rank): Boolean {
|
|
34
|
+
if (countOfMatch == 5 && !matchBonus) return rank.winningMoney == 1_500_000 // ⚠ 5, 1_500_000
|
|
35
|
+
if (countOfMatch < 3) return rank.countOfMatch < 3
|
|
36
|
+
.
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
리뷰어: "숫자 5와 1_500_000과 같은 것은 *매직리터럴*이라고 합니다. 이 숫자들은 자세히 보시면, Enum에 정의된 값과 동일합니다. 해당 값을 가지고 있는 Enum을 활용해 보면 어떨까요?" 학생: "Enum에 있는 값을 그대로 사용하는 식으로 변경." → `Rank.THIRD.countOfMatch`, `Rank.THIRD.winningMoney`.
|
|
41
|
+
|
|
42
|
+
### 3. `LottoAdministrator.getMatchOfNumber` — 매칭이 Administrator의 책임?
|
|
43
|
+
|
|
44
|
+
```kotlin
|
|
45
|
+
class LottoAdministrator {
|
|
46
|
+
fun getMatchOfNumber(lottoNumber: Lotto, winningNumber: Lotto): Int {. }
|
|
47
|
+
fun isMatchBonus(lottoNumber: Lotto, bonusNumber: BonusNumber): Boolean {. }
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
리뷰어: "보너스 볼을 일치 여부를 확인하는 이유는, 보너스 볼로 인하여 *랭킹이 변경*되기 때문입니다. 그렇다면, LottoAdministrator 클래스보다는 *Rank 클래스에서 구하는 것이 더 적합*하지 않을까요?" — 학생 자가 의문: "매칭 개수는 Rank? Lotto?" — 학생 결론: 일치 개수는 *Lotto의 정보*에 따라 변하므로 `Lotto.count` + Rank는 *그 결과 사용*.
|
|
52
|
+
|
|
53
|
+
### 4. `OutputView`의 *Rank 별 줄 별 하드코딩*
|
|
54
|
+
|
|
55
|
+
```kotlin
|
|
56
|
+
println(
|
|
57
|
+
"3개 일치 (5,000원) - ${if (lottoResult[Rank.FIFTH] == null) 0 else lottoResult[Rank.FIFTH]}개\n" +
|
|
58
|
+
"4개 일치 (50,000원) - ${.}\n" +
|
|
59
|
+
.
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
리뷰어: "만약 요구사항이 변경되어 Rank 클래스의 값이 변경되면, 이 부분도 반드시 변경이 필요합니다. Rank 클래스가 변경되더라도, *출력하는 문구들을 변경하지 않아도 되도록* 코드를 개선해 보면 어떨까요?" 학생: "`fun printLottoRankCount(rank: Rank, lottoResult: HashMap<Rank, Int>) { if (rank != Rank.MISS) println("${rank.countOfMatch}개 일치 (${rank.winningMoney}원) - ${lottoResult[rank] ?: 0} 개") }` 로 수정." — *Rank 데이터*로 자동 포맷.
|
|
64
|
+
|
|
65
|
+
### 5. 랜덤 테스트가 *반드시 성공*
|
|
66
|
+
|
|
67
|
+
```kotlin
|
|
68
|
+
@Test
|
|
69
|
+
fun `1~45의 랜덤번호 6개를 추출한다`() {
|
|
70
|
+
val actual = ShuffledNumberGenerator().generate()
|
|
71
|
+
assertThat(actual.size).isEqualTo(6)
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
리뷰어: "랜덤으로 추출하는 테스트는 *반드시 성공하는 테스트*입니다. 그래서 *랜덤값을 테스트하는 것은 의미가 없습니다*. *내가 원하는 숫자로 로또를 생성*했을 때, 잘 생성이 되는지 확인해 보는 코드를 작성해 보면 어떨까요?"
|
|
76
|
+
|
|
77
|
+
### 6. 테스트명 모호
|
|
78
|
+
|
|
79
|
+
```kotlin
|
|
80
|
+
@Test fun `갯수는 1 이상이다`() {. }
|
|
81
|
+
@Test fun `당첨번호와 보너스번호는 1~45이다`() {. } // ⚠ 실제로는 46 테스트
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
리뷰어: "어떤 갯수가 1 이상일까요?" + "함수명만 봤을 때에는 1부터 45 사이의 숫자를 테스트하는 것으로 보이지만, *실제 구현부는 45보다 큰 46을 테스트*하고 있네요. 테스트하고자 하는 것과, 함수명을 일치시켜 보면 어떨까요?"
|
|
85
|
+
|
|
86
|
+
### 7. Rank 테스트 일부만
|
|
87
|
+
|
|
88
|
+
리뷰어: "현재 당첨번호로 인한 등수가 여러 개가 있습니다. 요구사항에 맞게 등수가 나타나는지 *모든 등수에 대한 테스트* 코드를 작성해 보면 어떨까요?"
|
|
89
|
+
|
|
90
|
+
## 리뷰어 의견 요지
|
|
91
|
+
|
|
92
|
+
- **함수명 = 의도** — `check*`보다 `is*`/`matches*`.
|
|
93
|
+
- **매직리터럴 = enum/상수 활용**.
|
|
94
|
+
- **매칭 책임 = 데이터 소유 객체** — Administrator 같은 *별도 객체*는 응집도 낮춤.
|
|
95
|
+
- **View 출력은 *Rank 데이터*로 자동 포맷** — 변경 동기화.
|
|
96
|
+
- **랜덤 테스트는 *의미 없음*** — *입력 제어*로 의미 있는 검증.
|
|
97
|
+
- **테스트명 = 실제 검증 대상과 일치**.
|
|
98
|
+
|
|
99
|
+
- **대표 인용:**
|
|
100
|
+
> 함수명만 봤을 때에는 무엇을 '체크'하는지 알기가 어렵네요.
|
|
101
|
+
> — @BeokBeok on `src/main/kotlin/domain/Rank.kt`
|
|
102
|
+
|
|
103
|
+
> 숫자 5와 1_500_000과 같은 것은 매직리터럴이라고 합니다. 이 숫자들은 자세히 보시면, Enum에 정의된 값과 동일합니다.
|
|
104
|
+
> — @BeokBeok on `src/main/kotlin/domain/Rank.kt`
|
|
105
|
+
|
|
106
|
+
> 랜덤으로 추출하는 테스트는 반드시 성공하는 테스트입니다. 그래서 랜덤값을 테스트하는 것은 의미가 없습니다.
|
|
107
|
+
> — @BeokBeok on `src/test/kotlin/domain/LottoMachineTest.kt`
|
|
108
|
+
|
|
109
|
+
## 얻은 교훈
|
|
110
|
+
|
|
111
|
+
- **`check*` = 검증/예외 행위 시사**. *반환이 있으면* `is*`/`has*`/`matches*`.
|
|
112
|
+
- **매직리터럴 = enum/상수 활용** — *수치가 enum 값과 일치*하면 반드시 *enum 참조*.
|
|
113
|
+
- **매칭 책임은 *데이터 소유 객체*** — `Administrator` 같은 *행위 객체*에 매칭을 두면 *Lotto가 단순 데이터*가 됨.
|
|
114
|
+
- **View 출력은 *Rank 데이터*로 자동 포맷** — Rank 변경 시 View 변경 X.
|
|
115
|
+
- **랜덤 테스트는 *반드시 성공* 무의미** — *입력 제어*로 *기대 출력* 검증.
|
|
116
|
+
- **테스트명 = 실제 검증 대상과 일치** — 함수명에 *범위* 명시하되 *실제 케이스*와 일치.
|
|
117
|
+
- ***모든 등수 테스트*** — 일부만 테스트하면 *나머지 분기*는 미보장.
|