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,149 @@
|
|
|
1
|
+
# PR #144 — [포르] 2단계 로또
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@jiyuneel](https://github.com/jiyuneel)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/144
|
|
5
|
+
- **단계:** 2단계 (수동 로또)
|
|
6
|
+
- **리뷰어:** @krrong
|
|
7
|
+
- **라인 코멘트:** 16
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`LottoNumber.getAll()` 메시지화** — 학생 직접: "*객체에게 메시지를 던지는 연습을 꾸준히 해야 할 것 같네요..!* 🙂".
|
|
12
|
+
- **`WinningLotto.getLottoResult(lottos)`** — *Tell, Don't Ask*. 리뷰어 칭찬: "*WinningLotto가 스스로 일을 할 수 있도록 만들었네요* 👏".
|
|
13
|
+
- **`LottoCount` value class** — 리뷰어 칭찬: "*로또 개수 포장* 👏".
|
|
14
|
+
- **`Lotto.of` (수동) vs `Lotto.create` (자동) 팩토리 분리** — 후속 라운드에서 의도 명확화.
|
|
15
|
+
- **`LottoMachine` 인터페이스 + `ManualLottoMachine`/`AutomaticLottoMachine`** — Strategy. 리뷰어 칭찬: "*공통 로직을 인터페이스로 추상화* 💯".
|
|
16
|
+
- **학생이 *시도 후 폐기*도 PR에 명시** — 일급 컬렉션 만들어 봤다가 *역할 없어 폐기*.
|
|
17
|
+
|
|
18
|
+
## 못한 점 (설계 관점)
|
|
19
|
+
|
|
20
|
+
### 1. `Lotto.create()` — *자동 발매기 책임을 Lotto가 가져감*
|
|
21
|
+
|
|
22
|
+
```kotlin
|
|
23
|
+
companion object {
|
|
24
|
+
fun create(): Lotto {
|
|
25
|
+
val lottoNumbers =
|
|
26
|
+
LottoNumber.NUMBERS.values
|
|
27
|
+
.shuffled()
|
|
28
|
+
.take(NUMBER_OF_LOTTO_NUMBERS)
|
|
29
|
+
return Lotto(lottoNumbers)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
리뷰어 (1차): "로또가 *스스로를 반환*한다? 저는 *조금 어색하게 느껴*지기도 해요! Lotto가 직접 Lotto를 만들어 반환하도록 만든 *이유는 무엇*인가요? 🤔" 학생 (1차): "*create 함수가 팩토리 함수로써 Lotto 인스턴스를 생성하는 역할*을 하도록 했습니다! private constructor를 사용하여." 리뷰어 (2차): "아하! 제가 코드를 잘못 이해했었던 것 같군요 🙇♂️ — *랜덤으로 6개의 번호를 선택해서 로또를 반환하는 일은 로또의 책임일까요*? *AutomaticLottoMachine이 할 일을 로또가 가져가버린 것처럼* 보여요! 🤔" — *팩토리의 자기 책임 검증*: *어떤 생성 정책*인가에 따라 *책임 위치 다름*. *랜덤 선택*은 발매기 책임.
|
|
35
|
+
|
|
36
|
+
### 2. `LottoMachine.generate(lottoNumbers: List<List<Int>>? = null)` — *nullable 분기*
|
|
37
|
+
|
|
38
|
+
```kotlin
|
|
39
|
+
interface LottoMachine {
|
|
40
|
+
fun generate(
|
|
41
|
+
lottoCount: LottoCount,
|
|
42
|
+
lottoNumbers: List<List<Int>>? = null, // ⚠ nullable 인터페이스
|
|
43
|
+
): List<Lotto>
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
학생 자가 의문: "*자동 발매기는 로또 개수만 필요하고, 수동 발매기는 로또 번호도 필요로 한다는 점*에서 *설계가 복잡*해진 것 같습니다. 결국 *lottoNumbers를 nullable로 선언*하고, *자동 발매기의 경우에는 lottoNumbers가 null*로 오도록 했습니다." 리뷰어: "*과연 로또 번호를 함수로만 넘길 수 있는 것일까*?에 대해 고민해 보면 답을 찾을 수 있을 것 같아요 🤠 *혼자 고민하는데 너무 많은 시간을 쏟지 마시고 어려우면 dm 남겨* 주셔도 됩니다요 😊" 학생: "로또 번호를 *수동 발매기의 생성자를 통해 넘겨주는 방식*으로 리팩터링해 봤습니다! 🤩"
|
|
48
|
+
```kotlin
|
|
49
|
+
class ManualLottoMachine(private val lottoNumbers: List<List<Int>>) : LottoMachine {
|
|
50
|
+
override fun generate(lottoCount: LottoCount): List<Lotto> {. }
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
— *공통 인터페이스 = 공통 시그니처*. *분기 인자*는 *생성자로*.
|
|
54
|
+
|
|
55
|
+
### 3. 인터페이스 추가 *협력 끌어올림* — 함수 주입
|
|
56
|
+
|
|
57
|
+
리뷰어 후속 제안:
|
|
58
|
+
```kotlin
|
|
59
|
+
interface LottoMachine {
|
|
60
|
+
fun generate(count: LottoCount): List<Lotto>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class ManualLottoMachine(
|
|
64
|
+
private val getLottoNumbers: (List<Int>) -> Unit // ⚠ 함수 주입
|
|
65
|
+
): LottoMachine {
|
|
66
|
+
override fun generate(count: Int): List<Lotto> {
|
|
67
|
+
return List(count) { Lotto(getLottoNumbers()) }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
"*나중에 협력 관계를 끌어올린다면 다음처럼 작성*할 수도 있어요." — *함수형 인터페이스*로 *지연 입력*. 매번 *번호 입력*을 함수로.
|
|
73
|
+
|
|
74
|
+
### 4. `List<Lotto>` *일급 컬렉션* 없음
|
|
75
|
+
|
|
76
|
+
학생 자가 답변: "로또 리스트를 감싸는 *일급 컬렉션을 만드는 방법을 생각하고, 실제로 그렇게 구현도 해 봤었*습니다. 하지만 구현을 하고 나니, 해당 클래스가 *List<Lotto>를 감싸는 것 외에는 아무런 역할이나 책임이 없어서 결국 List를 사용*하게 되었습니다! 제가 *고려하지 못한 부분*이 있을까요..?!" 리뷰어 (균형 잡힌 답변):
|
|
77
|
+
> List<Lotto>를 감싸면 간단하게만 생각해 봐도 아래와 같은 장점을 얻을 수 있을 거에요.
|
|
78
|
+
> 1. *도메인 의미를 명확하게 전달*할 수 있다. (클래스명을 잘 지어야 하겠지만요 😅)
|
|
79
|
+
> 2. 컬렉션에 대한 *불변성을 보장*한다. (개발자가 실수로 `MutableList<Lotto>`의 형태로 넘겨도 불변성을 보장)
|
|
80
|
+
> 3. *확장성을 가질 수 있다*. (로또 묶음이 하는 일이 생겼을 때 일급 컬렉션에 로직만 추가하면 되니 변경이 좀 더 자유로움)
|
|
81
|
+
>
|
|
82
|
+
> *하지만 언급한 것처럼 역할과 책임이 없기에 만들지 않는 것도 좋은 근거와 방법*이라고 생각해요 👏
|
|
83
|
+
|
|
84
|
+
— *언제 일급 컬렉션을 만들지*는 *현재 행동* + *예상 확장*의 트레이드오프.
|
|
85
|
+
|
|
86
|
+
### 5. `Lotto.lottoNumbers` *public 노출*
|
|
87
|
+
|
|
88
|
+
```kotlin
|
|
89
|
+
class Lotto(val lottoNumbers: List<LottoNumber>) {. }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
리뷰어: "`LottoNumber`가 가지고 있는 값을 사용 사용하도록 잘 변경해 주었네요 👏 *너가 가진 번호 다 내놔라고 LottoNumber에게 메시지를 던져* 볼까요?" 학생: "*LottoNumber가 가지고 있는 로또 번호를 반환하는 getAll 함수*를 통해 값을 사용할 수 있도록 수정했습니다! *객체에게 메시지를 던지는 연습을 꾸준히 해야 할 것 같네요..!*" — *getter 호출* → *메시지*.
|
|
93
|
+
|
|
94
|
+
### 6. `LottoStore.publish` — 네이밍
|
|
95
|
+
|
|
96
|
+
```kotlin
|
|
97
|
+
class LottoStore {
|
|
98
|
+
fun publish(.) // ⚠ 발행
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
리뷰어: "nit: *상점에서 판매한다 → sell*은 어떤가요? 🤔" 학생: "*sell이 판매한다는 의미를 나타내는 더 명확한 네이밍*인 것 같아서 변경했습니다!" — *현실 메타포 일치* (kiosk).
|
|
103
|
+
|
|
104
|
+
### 7. 테스트 *assertj static import* 권장
|
|
105
|
+
|
|
106
|
+
```kotlin
|
|
107
|
+
Assertions.assertThat(lottos.size).isEqualTo(5)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
리뷰어:
|
|
111
|
+
```kotlin
|
|
112
|
+
import org.assertj.core.api.Assertions.assertThat
|
|
113
|
+
assertThat(lottos.size).isEqualTo(5)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## 리뷰어 의견 요지
|
|
117
|
+
|
|
118
|
+
- **`Lotto.create()` = *발매기 책임을 도메인이 가져간 안티***. *랜덤 선택*은 *AutomaticLottoMachine*.
|
|
119
|
+
- **인터페이스 인자는 *공통*만** — *분기 인자*는 *생성자*.
|
|
120
|
+
- **함수 주입으로 *협력 끌어올림*** — Functional Interface.
|
|
121
|
+
- **일급 컬렉션 = *트레이드오프*** — *현재 행동 없음 ↔ 미래 확장*.
|
|
122
|
+
- **`.lottoNumbers` 노출 → *메시지*** — `lotto.contains(.)`.
|
|
123
|
+
- **네이밍 = *현실 메타포***. `publish` → `sell`.
|
|
124
|
+
- **assertj static import**.
|
|
125
|
+
|
|
126
|
+
- **대표 인용:**
|
|
127
|
+
> 랜덤으로 6개의 번호를 선택해서 로또를 반환하는 일은 *로또의 책임일까요*? *AutomaticLottoMachine이 할 일을 로또가 가져가버린 것처럼* 보여요!
|
|
128
|
+
> — @krrong on `src/main/kotlin/lotto/domain/model/Lotto.kt`
|
|
129
|
+
|
|
130
|
+
> 자동 발매기는 로또 개수만 필요하고, 수동 발매기는 로또 번호도 필요로 한다는 점에서 설계가 복잡해진 것 같습니다. 결국 lottoNumbers를 nullable로 선언하고.
|
|
131
|
+
> — @jiyuneel on `src/main/kotlin/lotto/domain/service/LottoMachine.kt`
|
|
132
|
+
|
|
133
|
+
> 과연 *로또 번호를 함수로만 넘길 수 있는 것일까*?에 대해 고민해 보면 답을 찾을 수 있을 것 같아요 🤠
|
|
134
|
+
> — @krrong on `src/main/kotlin/lotto/domain/service/LottoMachine.kt`
|
|
135
|
+
|
|
136
|
+
> 하지만 언급한 것처럼 *역할과 책임이 없기에 만들지 않는 것도 좋은 근거와 방법*이라고 생각해요 👏
|
|
137
|
+
> — @krrong on `src/main/kotlin/lotto/controller/LottoController.kt`
|
|
138
|
+
|
|
139
|
+
## 얻은 교훈
|
|
140
|
+
|
|
141
|
+
- **`Lotto.create()`는 *책임 침범*** — *랜덤 6개 선택*은 *발매기*. *수동 입력 검증*만 `Lotto` 책임.
|
|
142
|
+
- **공통 인터페이스 = 공통 시그니처** — *수동만 필요한 번호*를 *nullable*로 인터페이스에 넣으면 *자동도 신경 써야*. *생성자 차이*로 해결.
|
|
143
|
+
- **함수 주입으로 협력 끌어올림** — `(Int) -> List<Int>` 같은 *지연 입력*은 *순서 의존*을 *호출 컨텍스트*에서 해결.
|
|
144
|
+
- **일급 컬렉션 = *트레이드오프*** — *역할 없으면 List 사용*도 합리. 단 *불변성/확장성*은 일급 컬렉션 장점.
|
|
145
|
+
- **`.numbers` 노출 → 메시지** — `lotto.numbers.contains(x)` → `lotto.contains(x)`.
|
|
146
|
+
- **네이밍은 *현실 메타포*** — `publish` vs `sell`. *키오스크*에서 *판매*하는 게 자연.
|
|
147
|
+
- **assertj `import static`** — `assertThat(x).isEqualTo(y)`가 *코드 시그널*.
|
|
148
|
+
- **리뷰어의 *DM 제안*은 좋은 신호** — *왕복 4회 이상* 되면 *비동기 한계*. *동기 채널*로 이동.
|
|
149
|
+
- **이미지 첨부/커밋 링크 활용** — 학생이 *5e0de6b 커밋 링크*를 댓글에 첨부.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# PR #58 — [에디] 1단계 로또
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@junjange](https://github.com/junjange)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/58
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @vagabond95
|
|
7
|
+
- **라인 코멘트:** 31
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`Lotto` 중복/크기 검증** — `require`로 도메인 invariant 강제.
|
|
12
|
+
- **`enum class Rank(countOfMatch, winningMoney)`** — 등수+상금 한 곳.
|
|
13
|
+
- **`Range` 재활용** — `LOTTO_NUMBER_RANGE: IntRange = 1..45`.
|
|
14
|
+
- **`Rank.valueOf(countOfMatch, matchBonus)` factory** — 매칭 → Rank 변환 캡슐화.
|
|
15
|
+
- **리뷰 반영을 커밋 해시로 명시** — 변경 추적 용이.
|
|
16
|
+
|
|
17
|
+
## 못한 점 (설계 관점)
|
|
18
|
+
|
|
19
|
+
### 1. Controller가 `","`로 split — View 책임 침범
|
|
20
|
+
|
|
21
|
+
```kotlin
|
|
22
|
+
private fun lottoDraw(): DrawResult {
|
|
23
|
+
val winningNumber = InputView.readWinningNumbers()
|
|
24
|
+
val winningLotto = Lotto((winningNumber.split(",").map { LottoNumber(it.trim()) }))
|
|
25
|
+
.
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
리뷰어: "`,`로 split된다는 내용은 view의 요구사항인데요. view의 요구사항이 바뀔 때 controller에 변경이 발생하는 것을 지양해야 할 것 같습니다!" — 입력 형식은 View 내부에서 *완성된 데이터*로 변환되어야 함.
|
|
30
|
+
|
|
31
|
+
### 2. `LottoMachine(private val price: String)` — 도메인이 String 받음
|
|
32
|
+
|
|
33
|
+
```kotlin
|
|
34
|
+
class LottoMachine(private val price: String) {
|
|
35
|
+
init { require(price.toIntOrNull()?.let { it >= MIN_PRICE } == true) }
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
리뷰어: "LottoNumber, LottoMachine 모두 String으로 넘겨주고 내부적으로 숫자로 타입 변환 및 검증을 처리하고 있는데요. price가 숫자 타입으로 '입력' 되었는지는 View에서 검증하는 것이 좀 더 적절하지 않을까요?" 학생 반박: "View는 입력만, 유효성 검사는 LottoMachine." → 후속 논의에서 *형식 검증 = View*, *비즈니스 검증 = Domain*으로 합의.
|
|
40
|
+
|
|
41
|
+
### 3. `LottoResult.static` — Kotlin 예약어와 혼동되는 명명
|
|
42
|
+
|
|
43
|
+
```kotlin
|
|
44
|
+
class LottoResult(val static: Map<Rank, Int>) {. }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
리뷰어: "kotlin이긴 하지만 static은 기본적으로 '정적 상태'를 의미하는 예약어로 많이 쓰이기 때문에 조금 혼동이 올 수 있을 것 같아요. 좀 더 적절한 네이밍으로 바꿔봐도 좋겠습니다." — `statistic`/`countByRank`.
|
|
48
|
+
|
|
49
|
+
### 4. `LottoTicket` vs `Lotto` — 명명 혼동
|
|
50
|
+
|
|
51
|
+
```kotlin
|
|
52
|
+
fun getLottoTicket(): Int = price.toInt() / MIN_PRICE // ⚠ 수량 반환인데 Ticket
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
리뷰어: "LottoTicket과 Lotto가 네이밍으로 봤을 때, 큰 차이를 알지 못할 것 같아요. 좀 더 적절한 이름은 없을까요~?" — 함수가 *수량*을 반환하면 `getLottoCount`.
|
|
56
|
+
|
|
57
|
+
### 5. `OutputView`가 Rank 순회로 출력
|
|
58
|
+
|
|
59
|
+
```kotlin
|
|
60
|
+
fun printResult(lottoResult: LottoResult) {
|
|
61
|
+
println("당첨 통계"); println("---------")
|
|
62
|
+
Rank.entries.reversed().forEach { rank ->. } // ⚠ Model 구조 가정
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
리뷰어: "Rank를 순회하면서 출력하기보다, lottoResult의 결과를 바로 출력하는 것은 어떨까요? 현재 요구사항에서는 rank를 순회하면서 출력을 해도 차이가 없습니다. 다만, 이것은 View가 'LottoResult에는 모든 등수의 결과가 들어있다.'라는 model의 내부 구현을 암묵적으로 알고 있기 때문에 가능한 것으로 보여요. 만약 LottoResult 내부에 변경사항이 발생하면, View에도 변경사항이 발생할 텐데 이러한 의존관계는 줄여 보면 어떨까요?" → 학생 해결: `LottoResult.toString()`을 커스텀해 View는 *출력만*.
|
|
67
|
+
|
|
68
|
+
### 6. `Lotto`가 `List<LottoNumber>` — Set이 더 적합
|
|
69
|
+
|
|
70
|
+
```kotlin
|
|
71
|
+
class Lotto(val lottoNumbers: List<LottoNumber>) {
|
|
72
|
+
init { require(lottoNumbers.distinct().size == LOTTO_SIZE) }
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
리뷰어: "이미 중복 검증을 잘해 주셨는데, 추가적으로 같이 생각해 보면 좋을 부분이라 코멘트 남깁니다. lottoNumbers의 자료구조는 List인데, Set으로 바꾼다면 기본적으로 '중복을 허용하지 않는 자료구조'이므로 도메인의 의미상 좀 더 적절한 자료구조가 될 수 있습니다." — 자료구조가 *invariant 표현*.
|
|
77
|
+
|
|
78
|
+
### 7. `LottoAnalyzer` class vs object
|
|
79
|
+
|
|
80
|
+
```kotlin
|
|
81
|
+
class LottoAnalyzer(private val lottos: List<Lotto>, private val drawResult: DrawResult) {. }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
리뷰어: "class와 object를 사용하시는 기준이 있으실까요? 해당 클래스를 object로 전환하는 것이 적절할까요? 적절하다면 (혹은 그렇지 않다면) 이유는 무엇일까요?" 학생: "class의 생성자를 메서드의 파라미터로만 사용하고 있어 상태를 가지지 않고, 해당 class는 랭크를 통계 내는 기능만 하므로 object로 바꾸는 것이 더 적절." → `object`로 변환 + `calculateResult` 사용처 객체로 이동.
|
|
85
|
+
|
|
86
|
+
### 8. `LottoMachine` class — 학생도 동일 결론
|
|
87
|
+
|
|
88
|
+
학생: "LottoMachine을 object로 선언했을 때, 하나의 인스턴스만 생성되므로 메모리 측면에서 장점이 있을 것 같습니다. … LottoMachine은 price를 의존하고 있지만, price는 getNumberOfLottoTickets() 메서드에서만 사용되고 있고 LottoMachine이 price의 상태를 가지고 있을 필요가 없기 때문에 object로 바꾸는 게 더 적합." — *상태 없음*이 명확하면 `object`.
|
|
89
|
+
|
|
90
|
+
### 9. `Rank.valueOf` 매번 분기
|
|
91
|
+
|
|
92
|
+
```kotlin
|
|
93
|
+
fun valueOf(countOfMatch: Int, matchBonus: Boolean): Rank {
|
|
94
|
+
if (countOfMatch == THIRD.countOfMatch && !matchBonus) return THIRD
|
|
95
|
+
return entries.find { it.countOfMatch == countOfMatch } ?: MISS
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
리뷰어: "현재는 보너스 번호 때문에 Rank, LottoResult 등의 클래스에서 매번 분기 처리가 필요한 상황인데요. 앞으로도 보너스 번호와 관련된 클래스는 모두 이러한 분기 처리가 들어가야 하고, 이는 추후에 변경사항이 발생할 경우 리소스가 많이 드는 작업이 될 수 있을 것 같아요. 분기 처리 없이 등수를 구하도록 리팩토링 해 볼 수 있을까요?" 학생: "RankState라는 enum class에서 일반 당첨, 보너스 당첨, 미당첨을 구분." 리뷰어 후속: "Rank와 RankState는 잘 보면 유사한 점이 많습니다. matchBonus를 Rank에서 다룬다면 두 클래스를 잘 병합해 볼 수도 있지 않을까요?" — *분기 → 별도 enum* → *두 enum 병합*의 의사결정 흐름.
|
|
100
|
+
|
|
101
|
+
### 10. `Rank` 테스트 일부만
|
|
102
|
+
|
|
103
|
+
```kotlin
|
|
104
|
+
class RankTest {
|
|
105
|
+
@Test fun `5개 일치 + 보너스 → 2등`() {. }
|
|
106
|
+
@Test fun `5개 일치 → 3등`() {. }
|
|
107
|
+
// 1, 4, 5등, MISS 누락
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
리뷰어: "나머지 등수는 테스트하지 않으신 이유가 있을까요?" 학생: "3등을 구하는 로직이 어려울 수 있다고 판단하여 3등과 그 외 다른 2개의 테스트 코드를 작성." → 학생 보강 (1등~MISS 모두).
|
|
112
|
+
|
|
113
|
+
### 11. 일급 컬렉션 `Lottos` 부재
|
|
114
|
+
|
|
115
|
+
리뷰어: "요구사항 중 하나인 일급 컬렉션을 Lotto 리스트에 적용해 볼 수 있을 것 같아요~!" — `List<Lotto>` 자체를 `Lottos`로 감싸면 *발행물의 집합*이 자기 행위를 가질 수 있음.
|
|
116
|
+
|
|
117
|
+
## 리뷰어 의견 요지
|
|
118
|
+
|
|
119
|
+
1. **View 요구사항(`,` split, 형식 변환)이 Controller로 누수되지 말 것** — 입력 형식 변경이 *Controller*까지 영향 가면 책임 경계 깨짐.
|
|
120
|
+
2. **자료구조 = invariant 표현** — `Set`이 도메인 의미를 더 잘 담을 수 있다면 `List` 대신.
|
|
121
|
+
3. **`object` vs `class`** — *상태 없음*이 확실하면 `object`. 메모리 절약은 부차적.
|
|
122
|
+
4. **분기 처리 흩어짐 = 새 enum 등장 신호** — `Rank.SECOND`/`THIRD` 분기가 여러 곳에 나타나면 `RankState` 같은 *새 분류*가 필요.
|
|
123
|
+
5. **결과 객체의 *자기 출력 표현*** — `LottoResult.toString()`을 정의해 View가 *순회 책임*에서 자유로워짐.
|
|
124
|
+
6. **명명은 *도메인 예약어*와 겹치지 않게** — `static`은 Kotlin/Java 키워드 인식.
|
|
125
|
+
|
|
126
|
+
- **대표 인용:**
|
|
127
|
+
> `,`로 split된다는 내용은 view의 요구사항인데요. view의 요구사항이 바뀔 때 controller에 변경이 발생하는 것을 지양해야 할 것 같습니다!
|
|
128
|
+
> — @vagabond95 on `src/main/kotlin/lotto/controller/LottoGameController.kt`
|
|
129
|
+
|
|
130
|
+
> 이것은 View가 'LottoResult에는 모든 등수의 결과가 들어있다.'라는 model의 내부 구현을 암묵적으로 알고 있기 때문에 가능한 것으로 보여요.
|
|
131
|
+
> — @vagabond95 on `src/main/kotlin/lotto/view/OutputView.kt`
|
|
132
|
+
|
|
133
|
+
> 분기 처리 없이 등수를 구하도록 리팩토링 해 볼 수 있을까요?
|
|
134
|
+
> — @vagabond95 on `src/main/kotlin/lotto/model/Rank.kt`
|
|
135
|
+
|
|
136
|
+
> Set으로 바꾼다면 기본적으로 '중복을 허용하지 않는 자료구조'이므로 도메인의 의미상 좀 더 적절한 자료구조가 될 수 있습니다.
|
|
137
|
+
> — @vagabond95 on `src/main/kotlin/lotto/model/Lotto.kt`
|
|
138
|
+
|
|
139
|
+
## 얻은 교훈
|
|
140
|
+
|
|
141
|
+
- **View 형식(`,` split, String→Int)은 Controller로 누수 X**. 입력 *형식 변경*이 도메인 변경으로 이어지면 책임 경계 미설계 신호.
|
|
142
|
+
- **자료구조가 *invariant*를 표현** — `Set<LottoNumber>`이면 *중복 불가*가 타입에 명시. 외부에서 *불필요한 중복 검사*가 사라짐.
|
|
143
|
+
- **`object` = *상태 없음 + 단일성* 단언**. 메모리 절약이 아니라 *의미*가 1차 동기.
|
|
144
|
+
- ***분기가 여러 곳에 흩어지면 새 enum 등장 신호*** — `Rank`에 매번 `if (bonus)`가 붙으면 `RankState`/`BonusMatched` 같은 *새 분류*가 떠오름. 그 후 *원래 enum과 병합*도 검토.
|
|
145
|
+
- **결과 객체의 *자기 표현*** — `toString()` 커스텀으로 View 책임 줄이기. 단, 출력 형식이 자주 바뀌면 *별도 Formatter*가 더 자유로움.
|
|
146
|
+
- **자료구조 선택은 *컬렉션 무조건 List*가 아님** — Set/Map/List의 도메인 의미를 의식.
|
|
147
|
+
- **이름이 Kotlin/Java *예약어와 닮음*** — 의도 전달에 마찰. `static`은 *정적*을 떠올리게 함.
|
|
148
|
+
- **테스트는 *모든 분기*를 명세서로** — *어려운 경우만* 테스트 작성하면 *남은 분기*는 미보장.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# PR #81 — [로또] 에디 2단계 미션
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@junjange](https://github.com/junjange)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/81
|
|
5
|
+
- **단계:** 2단계 (수동 로또 추가)
|
|
6
|
+
- **리뷰어:** @vagabond95
|
|
7
|
+
- **라인 코멘트:** 32
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`sealed class GameState`** — 게임 흐름을 상태 패턴으로 표현.
|
|
12
|
+
- **`ErrorCode` enum + `ExceptionsHandler`** — 검증 로직 공통화 시도.
|
|
13
|
+
- **`LottoBundle.append(other)`** — 자동/수동 로또를 *컬렉션*이 직접 합치는 행위.
|
|
14
|
+
- **`LottoMachine`을 `object`로 복귀** — 상태 없음에 맞는 선택.
|
|
15
|
+
- **`Kiosk + Deposit + Record`로 리팩토링** — 사용자 흐름(잔액 + 거래 기록)을 한 객체로 통합.
|
|
16
|
+
- **`MatchResult` = wrapping → 행위 보유 객체로 진화** — 리뷰어 칭찬.
|
|
17
|
+
|
|
18
|
+
## 못한 점 (설계 관점)
|
|
19
|
+
|
|
20
|
+
### 1. 함수명에 `And` — 두 책임 신호
|
|
21
|
+
|
|
22
|
+
```kotlin
|
|
23
|
+
private fun getLottoBundleAndDrawResult(): Result<LottoResponse> =.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
리뷰어: "네이밍에 And가 들어간다는 것은 해당 함수가 2가지 이상의 역할을 수행한다는 신호인데요. 함수당 한 가지 역할만 수행하도록 개선 가능할까요?"
|
|
27
|
+
|
|
28
|
+
### 2. `LottoManualPurchase` vs `LottoManualPurchaseCount`
|
|
29
|
+
|
|
30
|
+
```kotlin
|
|
31
|
+
data class LottoManualPurchase(val count: Int) {. }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
리뷰어: "`LottoManualPurchaseCount(val count: Int)`에 더 가까울 것 같습니다!" — 클래스명에 *count*가 빠지면 *수동 구매 자체*인지 *수동 구매 수*인지 모름.
|
|
35
|
+
|
|
36
|
+
### 3. 상수 중복 — `LottoMachine`/`Lotto`/`LottoNumber`
|
|
37
|
+
|
|
38
|
+
```kotlin
|
|
39
|
+
class LottoMachine(.) {
|
|
40
|
+
companion object {
|
|
41
|
+
private const val LOTTO_SIZE = 6 // ⚠ Lotto가 이미 보유
|
|
42
|
+
private val LOTTO_NUMBER_RANGE: IntRange = 1..45 // ⚠ LottoNumber가 이미 보유
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
리뷰어: "해당 상수들은 이미 다른 모델에서 선언되어 있는 상수로 보여요. 상수 선언의 중복을 제거해 볼 수 있을까요?" — *상수의 소유*는 한 곳, 다른 곳은 import.
|
|
48
|
+
|
|
49
|
+
### 4. `createLottoBundle(lottoManualPurchaseNumbers: List<List<String>>,.)` — 이중 컬렉션
|
|
50
|
+
|
|
51
|
+
```kotlin
|
|
52
|
+
fun createLottoBundle(
|
|
53
|
+
lottoManualPurchaseNumbers: List<List<String>>,
|
|
54
|
+
lottoPurchaseCount: LottoManualPurchase,
|
|
55
|
+
): LottoBundle {. }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
리뷰어: "이중 컬렉션은 쉽게 타입을 유추하기 어렵게 만드는데요. 일급 컬렉션으로 한번 감싸주는 것은 어떨까요?" — `ManualPurchaseLottos` 같은 일급 컬렉션으로.
|
|
59
|
+
|
|
60
|
+
### 5. 같은 의미 상태가 두 인자로 분리됨
|
|
61
|
+
|
|
62
|
+
```kotlin
|
|
63
|
+
fun createLottoBundle(manualPurchaseLottos: ManualPurchaseLottos, lottoManualPurchaseCount: LottoManualPurchaseCount): LottoBundle
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
리뷰어: "manualPurchaseLottos에서 lottoManualPurchaseCount 값을 추출해 낼 수 있지 않을까요? 같은 의미를 가지는 상태는 최대한 재사용해 보면 좋을 것 같아요!" — `manualPurchaseLottos.size`로 충분.
|
|
67
|
+
|
|
68
|
+
### 6. `LottoMachine.getRandomLottoCount` 호출 무제한 + `price` 불변
|
|
69
|
+
|
|
70
|
+
```kotlin
|
|
71
|
+
class LottoMachine(private val price: Price) {
|
|
72
|
+
fun getRandomLottoCount(.): Int {
|
|
73
|
+
val randomLottoCount = price.getNumberOfLottoTickets() - lottoPurchaseCount.count
|
|
74
|
+
.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
리뷰어: "getRandomLottoCount의 호출에는 제한이 없는데, price는 생성 시에만 주입을 받으므로 로또를 구매했을 때 price 값도 차감되어야 논리적으로 맞지 않을까요~? 추후에 수동으로 로또를 언제든지 구매할 수 있는 요구사항이 추가될 경우 버그가 발생할 수 있는 부분일 것 같아요." — Kiosk 패턴(잔액 추적)으로 발전.
|
|
80
|
+
|
|
81
|
+
### 7. `LottoAnalyzer.calculateResult` — `MatchResultResponse`의 책임
|
|
82
|
+
|
|
83
|
+
```kotlin
|
|
84
|
+
object LottoAnalyzer {
|
|
85
|
+
fun calculateResult(matchResultResponse: MatchResultResponse): LottoResult {. }
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
리뷰어: "calculateResult 내에서 진행되는 로직은 MatchResultResponse 클래스가 '스스로' 수행할 수 있는 동작 아닐까요~? MatchResultResponse 클래스의 역할이 파편화되었다고 볼 수도 있을 것 같아요!" — *Analyzer*는 *대상 객체에 행위*가 있을 때 잉여.
|
|
90
|
+
|
|
91
|
+
### 8. `Price.plusPrice(strMoney: String)` — 시그니처 불일치
|
|
92
|
+
|
|
93
|
+
```kotlin
|
|
94
|
+
data class Price(val money: Int = DEFAULT_MONEY) {
|
|
95
|
+
fun plusPrice(strMoney: String): Price {. } // ⚠ String
|
|
96
|
+
fun minusPrice(): Price {. } // ⚠ 인자 없음
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
리뷰어 ①: "생성자에서는 Int를 전달받고 있는데, plus에서는 String 타입을 받는 구조가 일관성이 없어 보여요." ② "plusPrice가 실제로 더해지고자 하는 값을 받는다면, minusPrice도 동일한 규칙으로 빼고자 하는 값을 인자로 받는 것이 일관성이 있을 것 같아요." ③ "kotlin에서는 `operator` 라는 키워드를 이용하여 산술 연산자 오버라이딩이 가능하므로 이번 기회에 활용해 봐도 좋을 것 같아요." → `operator fun plus(other: Int)`.
|
|
101
|
+
|
|
102
|
+
### 9. `Price`가 `Lotto`에 의존 (`getRandomLottoCount`/`getNumberOfLottoTickets`)
|
|
103
|
+
|
|
104
|
+
```kotlin
|
|
105
|
+
data class Price(val money: Int) {
|
|
106
|
+
fun minusPrice(): Price = copy(money = money - getNumberOfLottoTickets() * MIN_PRICE)
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
리뷰어: "이러한 구조가 가능한 이유는 Price가 `getRandomLottoCount`, `getNumberOfLottoTickets`와 같이 Lotto에 대한 의존성을 가지고 있기 때문이에요. 그런데, 잘 생각해 보면 '가격'과 '로또' 중에 어느 것이 더 상위 개념일까요? 다르게 얘기하면 로또가 가격에 대한 정보를 알고 있는 것과 가격이 로또에 대한 정보를 알고 있는 것 중 어느 것이 더 자연스러울까요?" — *상위 개념(가격)*이 *하위 개념(로또)*을 알지 말 것.
|
|
111
|
+
|
|
112
|
+
### 10. `Deposit.minus`가 음수 검증 누락
|
|
113
|
+
|
|
114
|
+
```kotlin
|
|
115
|
+
operator fun minus(other: Int): Deposit = copy(money = Money(money.value - other))
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
리뷰어: "예치금의 개념이라면 빼고자 하는 값이 현재 남은 금액보다 큰 경우 즉, 마이너스가 되는 상황이 발생할 때의 예외처리가 필요하지 않을까요~?" — 도메인 invariant 누락.
|
|
119
|
+
|
|
120
|
+
### 11. `addDeposit + recordPurchase`가 *외부에서 강제됨*
|
|
121
|
+
|
|
122
|
+
```kotlin
|
|
123
|
+
kiosk.addDeposit(money)
|
|
124
|
+
kiosk.recordPurchase(money)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
리뷰어: "이 과정이 항상 같이 수행되어야 한다면, kiosk 내부에서 한번에 처리해 주는 것은 어떨까요? 개별 스탭을 외부에서 처리해야 할 경우 이러한 사항을 놓칠 수 있고 또 구현상으로도 강제하기 어려워 의도하지 않은 동작을 유발시키기 쉬울 것 같아요." — *호출 순서 강제*는 *외부 컨벤션*이 아니라 *내부 캡슐화*.
|
|
128
|
+
|
|
129
|
+
### 12. 중앙 `ErrorCode` enum
|
|
130
|
+
|
|
131
|
+
```kotlin
|
|
132
|
+
enum class ErrorCode(val status: Int, val reason: String) {. }
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
리뷰어: "에러코드 정리 👍. 그런데, 서비스가 커질수록 모든 에러코드를 한 곳에서 관리했을 때 생길 수 있는 단점도 추후에는 같이 고려가 되면 좋을 것 같아요!" — 중앙 enum이 *god-folder*가 될 위험.
|
|
136
|
+
|
|
137
|
+
### 13. `sealed class GameState` 선택 — Enum/Sealed Interface와의 비교
|
|
138
|
+
|
|
139
|
+
리뷰어: "Enum, Sealed Interface를 활용해도 동일한 목적으로 활용이 가능한데요, 각각 선택하는 기준에 대해 생각해 보면 좋을 것 같습니다." — 학습 방향 제시.
|
|
140
|
+
|
|
141
|
+
## 리뷰어 의견 요지
|
|
142
|
+
|
|
143
|
+
1. **함수명에 `And` = 두 책임 신호** — 분리.
|
|
144
|
+
2. **상수 중복 = 소유권 모호** — Lotto 정체성은 Lotto, LottoNumber 정체성은 LottoNumber.
|
|
145
|
+
3. **이중 컬렉션은 일급 컬렉션으로 감싸기** — 의도 명시.
|
|
146
|
+
4. **시간에 따라 변하는 상태 = 객체 생성자에 박아두지 말 것** — Kiosk/Deposit 패턴으로 잔액 추적.
|
|
147
|
+
5. **연산 인터페이스 *일관성*** — `plus(Int)` + `minus(Int)` + `operator`.
|
|
148
|
+
6. **상위 개념이 하위 개념을 모르게** — Price가 Lotto를 알면 의존 방향 역전.
|
|
149
|
+
7. ***항상 같이 수행*되는 절차는 *외부에서 강제하지 말 것*** — 내부 캡슐화로 호출자 부담 제거.
|
|
150
|
+
8. **중앙 enum = god-folder 위험** — 도메인별 분리 검토.
|
|
151
|
+
9. **단순 wrapping → 행위 보유로 진화** — `MatchResult` 칭찬.
|
|
152
|
+
|
|
153
|
+
- **대표 인용:**
|
|
154
|
+
> 네이밍에 And가 들어간다는 것은 해당 함수가 2가지 이상의 역할을 수행한다는 신호인데요.
|
|
155
|
+
> — @vagabond95 on `src/main/kotlin/lotto/controller/LottoGameController.kt`
|
|
156
|
+
|
|
157
|
+
> 잘 생각해 보면 '가격'과 '로또' 중에 어느 것이 더 상위 개념일까요? 다르게 얘기하면 로또가 가격에 대한 정보를 알고 있는 것과 가격이 로또에 대한 정보를 알고 있는 것 중 어느 것이 더 자연스러울까요?
|
|
158
|
+
> — @vagabond95 on `src/main/kotlin/lotto/model/Price.kt`
|
|
159
|
+
|
|
160
|
+
> 이 과정이 항상 같이 수행되어야 한다면, kiosk 내부에서 한번에 처리해 주는 것은 어떨까요? 개별 스탭을 외부에서 처리해야 할 경우 이러한 사항을 놓칠 수 있고…
|
|
161
|
+
> — @vagabond95 on `src/main/kotlin/lotto/controller/LottoGameController.kt`
|
|
162
|
+
|
|
163
|
+
> calculateResult 내에서 진행되는 로직은 MatchResultResponse 클래스가 '스스로' 수행할 수 있는 동작 아닐까요? MatchResultResponse 클래스의 역할이 파편화되었다고 볼 수도 있을 것 같아요!
|
|
164
|
+
> — @vagabond95 on `src/main/kotlin/lotto/model/LottoAnalyzer.kt`
|
|
165
|
+
|
|
166
|
+
## 얻은 교훈
|
|
167
|
+
|
|
168
|
+
- **함수명에 `And`/`Or`는 *2개 이상 책임* 신호**. 분리하거나 *목적*을 새 명사로.
|
|
169
|
+
- **상수의 *소유권*은 한 곳**. 중복 선언은 *변경 시 양쪽 모두 잊을 위험*.
|
|
170
|
+
- **이중 컬렉션 = 의도 모호** — 일급 컬렉션으로 *무엇의 모음인지* 명시.
|
|
171
|
+
- ***같은 의미의 상태*는 *하나의 인자*** — `manualPurchaseLottos`가 이미 count를 안다면 따로 받지 말 것.
|
|
172
|
+
- **시간에 따라 변하는 상태는 *객체 생성자*에 박지 말 것**. Price가 *최초 입력값*만 알고 있다면 잔액 추적 불가 → Kiosk/Deposit으로 *시간 흐름* 표현.
|
|
173
|
+
- **연산자 시그니처 *일관성*** — `plus(Int)` + `minus(Int)` + `operator`. 한쪽만 인자 없으면 *외부에서 빼는 값을 알 수 없음*.
|
|
174
|
+
- **상위 개념이 하위 개념을 알지 말 것**. *가격*이 *로또*를 알면 의존 방향 역전 — 로또가 가격을 알아야 자연.
|
|
175
|
+
- **항상 같이 수행되는 절차는 *내부 캡슐화*** — 호출자가 *두 번 호출*해야 한다면 빠뜨릴 위험.
|
|
176
|
+
- **중앙 enum은 god-folder 위험** — 도메인별 sealed/예외 분리도 옵션.
|
|
177
|
+
- **단순 wrapping → 행위 보유 객체로 진화**. wrapping만 하던 객체가 행위를 갖기 시작하면 *진짜 객체*가 됨.
|
|
178
|
+
- ***Enum vs Sealed class vs Sealed interface*** — 학습 시드. *상태가 데이터를 보유* 하면 sealed, *순수 분류*면 enum.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# PR #120 — [로또 1단계] 공백 미션 제출합니다
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@junseo511](https://github.com/junseo511)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/120
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @krrong
|
|
7
|
+
- **라인 코멘트:** 71
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`Rank` enum + `matchBonus: Boolean = false` 기본값** — 2등에만 보너스 필드 적용 시도.
|
|
12
|
+
- **PR 본문에 명확한 자가 의문 다수** — TDD 커밋 단위, LottoNumber 필요성, `matchBonus` 기본값 처리 등.
|
|
13
|
+
- **README 체크박스 활용** — 진행 상태 시각화.
|
|
14
|
+
|
|
15
|
+
## 못한 점 (설계 관점)
|
|
16
|
+
|
|
17
|
+
### 1. `Lotto`가 너무 많은 일
|
|
18
|
+
|
|
19
|
+
```kotlin
|
|
20
|
+
class Lotto(val numbers: List<Int>) {
|
|
21
|
+
init {
|
|
22
|
+
validateLottoNumbersCount(numbers)
|
|
23
|
+
validateLottoNumbersRange(numbers)
|
|
24
|
+
validateLottoNumbersDuplicate(numbers)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private fun validateLottoNumbersCount(numbers: List<Int>) {
|
|
28
|
+
require(numbers.size == LOTTO_NUMBER_SIZE) {. }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private fun validateLottoNumbersRange(numbers: List<Int>) {
|
|
32
|
+
require(numbers.all { it in 1..45 }) {. }
|
|
33
|
+
}
|
|
34
|
+
// + 중복 검증
|
|
35
|
+
// + 등수 계산
|
|
36
|
+
// + 보너스 비교
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
학생 의견:
|
|
41
|
+
|
|
42
|
+
> LottoNumber class를 따로 만들어서 번호에 대한 검증을 진행하더라구요?! 저는 근데 가지고 있는 로또 번호들을 Lotto에서 검증해도 괜찮다고 생각합니다. 오히려 너무 class를 보기 위해 가는 길이 가독성을 떨어지게 만드는 느낌이더라구요.
|
|
43
|
+
|
|
44
|
+
리뷰어 답변:
|
|
45
|
+
|
|
46
|
+
> 하지만 `Lotto`클래스가 하는 일이 많아지지 않을까요?
|
|
47
|
+
>. 로또에서 사용하는 숫자는 Int 타입인데요. 외부에서 가져온 이 숫자들이 로또 번호라는 것을 어떻게 알 수 있을까요?
|
|
48
|
+
> ```kotlin
|
|
49
|
+
> val lotto = Lotto(.)
|
|
50
|
+
> val number = lotto.numbers.first()
|
|
51
|
+
> foo(number)
|
|
52
|
+
>
|
|
53
|
+
> fun foo(number: Int) {
|
|
54
|
+
> // number가 로또 번호가 맞나? 검증을 해야할까?
|
|
55
|
+
> }
|
|
56
|
+
> ```
|
|
57
|
+
|
|
58
|
+
→ 가독성과 타입 안전성의 trade-off — Lotto 외부로 *Int를 노출*하면 호출자가 매번 "이게 로또 번호인가?" 의심.
|
|
59
|
+
|
|
60
|
+
### 2. `Rank`의 `matchBonus` 처리 — 5개 일치 SECOND에만 적용
|
|
61
|
+
|
|
62
|
+
```kotlin
|
|
63
|
+
enum class Rank(
|
|
64
|
+
val countOfMatch: Int,
|
|
65
|
+
val winningMoney: Int,
|
|
66
|
+
val matchBonus: Boolean = false,
|
|
67
|
+
) {
|
|
68
|
+
MISS(0, 0),
|
|
69
|
+
FIFTH(3, 5_000),
|
|
70
|
+
FOURTH(4, 50_000),
|
|
71
|
+
THIRD(5, 1_500_000),
|
|
72
|
+
SECOND(5, 30_000_000, true), // ⚠ 5개 일치 둘 중 보너스 일치만 SECOND
|
|
73
|
+
FIRST(6, 2_000_000_000),
|
|
74
|
+
;
|
|
75
|
+
|
|
76
|
+
companion object {
|
|
77
|
+
fun fromMatchResult(countOfMatch: Int, matchBonus: Boolean): Rank {
|
|
78
|
+
// 복잡한 분기 로직.
|
|
79
|
+
throw IllegalArgumentException(.)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
학생 의문:
|
|
86
|
+
|
|
87
|
+
> Rank를 반환하는 과정에서 SECOND일 때 boolean값을 기본으로 가지게 했습니다. 근데 6개 중에서 SECOND만 예외를 둬야 하는 로직 말고도 더 괜찮은 방법이 있을까요?
|
|
88
|
+
|
|
89
|
+
리뷰어 답:
|
|
90
|
+
|
|
91
|
+
> `Rank`는 정말 `matchBonus`가 필요할까요?
|
|
92
|
+
|
|
93
|
+
→ **답:** 보너스 일치 정보는 Rank의 *속성*보다 Rank를 *찾는 데 쓰는 입력*. `Rank.matchBonus` 필드 자체가 어색.
|
|
94
|
+
|
|
95
|
+
리뷰어가 준 힌트:
|
|
96
|
+
|
|
97
|
+
```kotlin
|
|
98
|
+
return entries.find { it.countOfMatch == countOfMatch && it.matchBonus == matchBonus } ?: MISS
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
→ `IllegalArgumentException` 없이 MISS로 fallback.
|
|
102
|
+
|
|
103
|
+
### 3. 테스트 assertion 길게
|
|
104
|
+
|
|
105
|
+
```kotlin
|
|
106
|
+
import org.junit.jupiter.api.Assertions
|
|
107
|
+
Assertions.assertEquals(5, lottoQuantity) // ⚠ 길게
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
→ `import..assertEquals` 후 `assertEquals(5, lottoQuantity)`.
|
|
111
|
+
|
|
112
|
+
### 4. PR 본문의 TDD 커밋 의문
|
|
113
|
+
|
|
114
|
+
학생:
|
|
115
|
+
|
|
116
|
+
> feat부터 커밋을 날려야 하는가? -> 진행한건 test부터 작성했는데 왜 feat부터 만들어야 하지?
|
|
117
|
+
> test부터 커밋을 날려야 하는가? -> test부터 날린 상태로 빌드를 돌리면 컴파일 에러가 발생할 텐데 왜 test부터 날리는거지?
|
|
118
|
+
|
|
119
|
+
리뷰어 답:
|
|
120
|
+
|
|
121
|
+
> 저의 선호도는 **세 번째**(feat과 test를 함께 커밋한다)인데요.
|
|
122
|
+
> 100개의 기능을 TDD로 구현할 때 200개의 커밋 vs 100개의 커밋, 리뷰어가 어떤 PR이 리뷰하기 편할까요?
|
|
123
|
+
|
|
124
|
+
→ TDD = *테스트 주도 사고*. 커밋은 *완결된 단위*.
|
|
125
|
+
|
|
126
|
+
## 리뷰어 의견 요지
|
|
127
|
+
|
|
128
|
+
리뷰어 @krrong (racingcar에서도 reviewee였던 사람이 lotto에서 reviewer로!):
|
|
129
|
+
|
|
130
|
+
1. **`LottoNumber` 도메인 추출 — 가독성 vs 타입 안전성**. 가독성 떨어진다는 학생 의견에 *호출처 의심 비용*으로 반박.
|
|
131
|
+
|
|
132
|
+
2. **`Rank.matchBonus` 필드의 어색함** — Rank의 *속성*인지 *찾기 입력*인지 구분.
|
|
133
|
+
|
|
134
|
+
3. **TDD 커밋 단위 = 완결된 기능 단위** — test/feat 분리는 *과정 기록*이지 *리뷰 단위*가 아님.
|
|
135
|
+
|
|
136
|
+
4. **`Rank` 검색에서 예외 던지지 말고 MISS fallback**.
|
|
137
|
+
|
|
138
|
+
- **대표 인용:**
|
|
139
|
+
> 하지만 `Lotto`클래스가 하는 일이 많아지지 않을까요? 로또 번호인지 검증도 해야하고, 몇 등인지 계산도 해야하고.
|
|
140
|
+
>
|
|
141
|
+
> — @krrong on `src/main/kotlin/lotto/model/Lotto.kt`
|
|
142
|
+
|
|
143
|
+
> `Rank`는 정말 `matchBonus`가 필요할까요?
|
|
144
|
+
>
|
|
145
|
+
> — @krrong on `src/main/kotlin/lotto/model/Rank.kt`
|
|
146
|
+
|
|
147
|
+
## 얻은 교훈
|
|
148
|
+
|
|
149
|
+
- **LottoNumber 추출의 진짜 가치 = *호출처가 의심하지 않게***. 외부에 `Int` 노출 = 매번 "이게 로또 번호 맞나?" 의심. 타입이 정답.
|
|
150
|
+
- **enum 필드의 분류 — *속성* vs *검색 키***. `matchBonus`는 Rank가 *되는 조건*이지 *Rank의 본질 속성*이 아님. enum 필드는 *영구한 속성*만.
|
|
151
|
+
- **MISS/NONE fallback > Exception**. enum이 전 케이스를 표현하면 *예외 던질 일 없음*. `find {. } ?: MISS`.
|
|
152
|
+
- **TDD 커밋 단위 = "다른 사람이 리뷰 가능한 단위"**. 테스트만 있는 커밋은 빌드 실패. 둘을 합치면 *완결된 기능*.
|
|
153
|
+
- **이전 reviewee가 다음 라운드 reviewer로** — racingcar 학생 krrong이 lotto에서 어떻게 학습한 걸 리뷰로 돌려주는지 패턴을 보여주는 PR.
|