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,158 @@
|
|
|
1
|
+
# PR #114 — [로또 1단계] 토바에 미션
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@tobae-time](https://github.com/tobae-time)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/114
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @KwonDae (제이든)
|
|
7
|
+
- **라인 코멘트:** 36
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **TODO + 기능 목록을 README에 상세 기록** — 자기 작업 흐름 가시화.
|
|
12
|
+
- **`fun interface LottoGenerator`** 도입 — 랜덤 외부 주입 적용.
|
|
13
|
+
- **검증 책임 *입력 vs 도메인*을 학생이 스스로 정리** — "형식 검증은 InputView, 도메인 요구사항은 객체 스스로".
|
|
14
|
+
- **`data class Lotto`로 보일러플레이트 제거** — `equals`/`hashCode` override 직접 작성 후 리뷰 반영.
|
|
15
|
+
- **`PurchaseAmountValidator`/`WinningNumberValidator`/`BonusNumberValidator` 분리** — 초기 시도는 분리 정신 잘 적용 (이후 객체 통합).
|
|
16
|
+
|
|
17
|
+
## 못한 점 (설계 관점)
|
|
18
|
+
|
|
19
|
+
### 1. `Lotto(randomNumbers: List<Int>)` — invariant 없음
|
|
20
|
+
|
|
21
|
+
```kotlin
|
|
22
|
+
class Lotto(randomNumbers: List<Int>) {
|
|
23
|
+
val numbers: List<Int> = randomNumbers.sorted()
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
리뷰어: "Lotto 도메인에 대해 테스트가 이루어졌을까요? `Lotto(listOf(1,2,1,2,1,2))`와 같은 객체도 생성될 수 있겠네요." 이어서: "randomNumbers의 각 원소들이 1~45 사이에 들어간다는 걸 확신할 수 있을까요? *모든 원시 값과 문자열을 포장한다* 요구사항을 참고해 보시죠!" — 변수명만으로 invariant 보장 X. `List<LottoNumber>` 시그니처면 범위·중복이 *타입에 새겨짐*.
|
|
28
|
+
|
|
29
|
+
### 2. `Validator` 클래스 남발 — 객체로의 위임 부재
|
|
30
|
+
|
|
31
|
+
```kotlin
|
|
32
|
+
class PurchaseAmountValidator(input: String) { init { require(.) } }
|
|
33
|
+
class WinningNumberValidator(input: List<String>) { init {. } }
|
|
34
|
+
class BonusNumberValidator(bonus: String, winning: List<Int>) { init {. } }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
리뷰어: "구매 금액에 대한 검증은 어느 객체에게 역할을 부여할 수 있을까요? 만약, 검증해야 할 종류가 늘어난다면 그만큼 Validator 클래스가 생성되어야 할 텐데, 일급컬렉션을 통해 객체가 스스로 판단할 수 있게끔 해보는 건 어떨까요?" — Validator는 *행위*만 있고 *상태가 없음*. 도메인 객체의 `init`이 자기 검증을 가져야 응집.
|
|
38
|
+
|
|
39
|
+
### 3. 테스트가 *Lotto가 아니라 RandomGenerator*를 검증
|
|
40
|
+
|
|
41
|
+
```kotlin
|
|
42
|
+
@Test
|
|
43
|
+
fun `로또 번호는 1~45 사이이다`() {
|
|
44
|
+
val number: List<Int> = listOf(1, 2, 3, 4, 5, 6)
|
|
45
|
+
val lotto = Lotto(number)
|
|
46
|
+
assertThat(lotto.numbers.all { it in 1..45 }).isTrue() // ⚠ 입력 그대로 검증
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Test
|
|
50
|
+
fun `로또 번호는 중복되지 않는 6개의 숫자를 갖는다`() {
|
|
51
|
+
val randomGenerator = RandomGenerator()
|
|
52
|
+
val lotto = Lotto(randomGenerator.getRandomNumberList())
|
|
53
|
+
assertThat(lotto.numbers.size).isEqualTo(6)
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
리뷰어: "이 테스트는 RandomGenerator()에 대한 테스트일까요? 언뜻 봐서는 랜덤요소를 테스트한 걸로 착각할 수 있을 거 같아요. '로또 번호는 중복되지 않아야 한다'는 누구의 역할이고 책임이 있을까요?" — 테스트 대상은 *입력으로 직접 깨뜨려*야 의미가 있음. `Lotto(listOf(1, 1,.))`를 넣어 예외를 확인.
|
|
58
|
+
|
|
59
|
+
### 4. `LottoMachine.buyLottos`가 테스트 불가능 — 랜덤 내장
|
|
60
|
+
|
|
61
|
+
```kotlin
|
|
62
|
+
class LottoMachine {
|
|
63
|
+
fun buyLottos(purchaseAmount: Int): List<Lotto> {
|
|
64
|
+
val randomGenerator = RandomGenerator() // ⚠ 내장
|
|
65
|
+
.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
리뷰어: "buyLotto()에 대해 테스트가 불가능하네요. 실제로 테스트 코드 작성이 되어 있지 않습니다. 왜 테스트가 불가하고, 어떻게 개선할 수 있을까요?" — `LottoGenerator`를 인자/생성자로 주입받아야 *Fake*로 테스트 가능.
|
|
71
|
+
|
|
72
|
+
### 5. `LottoNumber` 인스턴스 폭증
|
|
73
|
+
|
|
74
|
+
```kotlin
|
|
75
|
+
data class LottoNumber(val number: Int) {
|
|
76
|
+
init { validateLottoNumberRange() }
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
리뷰어: "로또 번호는 1~45로 정해져 있습니다. 만약 동일한 로또 번호가 다른 게임에도 여러 번 사용이 된다면 해당 로또 번호는 다른 객체이어야만 할까요? 로또를 발행할 때마다 새로운 인스턴스가 생성이 된다면 리소스가 많이 들어갈 것 같아요." — *Flyweight*. `(1..45)`를 사전 캐싱 + `private constructor`.
|
|
81
|
+
|
|
82
|
+
### 6. `Lotto`가 `val lotto: List<LottoNumber>` 외부 공개
|
|
83
|
+
|
|
84
|
+
```kotlin
|
|
85
|
+
class Lotto(val lotto: List<LottoNumber>) {. }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
리뷰어: "외부에서 직접 lotto에 접근이 가능한데요. 외부에서 직접 접근하는 대신 Lotto 객체가 의미있는 값을 반환할 수 있다면 어떨까요?" — Tell, Don't Ask. `lotto.matchCount(other)`, `lotto.contains(number)` 같은 행위 메서드.
|
|
89
|
+
|
|
90
|
+
### 7. `LottoPayment`가 검증만 — 일급 객체 의미 부재
|
|
91
|
+
|
|
92
|
+
```kotlin
|
|
93
|
+
class LottoPayment(private val amount: Int) {
|
|
94
|
+
init { require(amount >= MINIMUM_INPUT_PRICE) }
|
|
95
|
+
fun toInt() = amount
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
리뷰어: "이 클래스의 역할은 무엇일까요? 단순 로또 구입 금액만 갖고 있는 클래스로 보이는데요!" — 학생 수긍: "검증만 필요한 거라면 클래스로 구현하지 않아도 될 것 같다는 생각이 들었습니다." → 도메인 객체로 살리려면 *수량 계산*, *잔돈 계산* 등 행위 추가 필요.
|
|
100
|
+
|
|
101
|
+
### 8. `LottoMachine`이 `run()` 안에서 매번 생성
|
|
102
|
+
|
|
103
|
+
```kotlin
|
|
104
|
+
fun run() {
|
|
105
|
+
val lottos = LottoMachine().buyLottos(purchaseAmount)
|
|
106
|
+
.
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
리뷰어: "LottoMachine은 run()이 생성될 때마다 새로운 객체가 생성되어야 하는 존재일까요?" 학생 답: "LottoMachine은 게임 시작 전에 한 번만 생성되어도 됩니다!" → *상태 없는* 객체는 단일 인스턴스(생성자 주입 또는 `object`).
|
|
111
|
+
|
|
112
|
+
### 9. `LottoMachine`을 클래스 바디로 옮긴 후 학생의 새로운 혼란
|
|
113
|
+
|
|
114
|
+
학생: "로또 머신이 가지고 있는 것은 발행된 로또인데, run을 할 때마다 로또 머신 인스턴스가 생성되어야 하는 것이 아닌가? 하는 생각이 듭니다." — *발행물*을 기계 안에 두느냐 외부로 내보내느냐. 발행물을 보유하면 매 run마다 새 인스턴스, 발행 후 즉시 반환이면 단일 인스턴스.
|
|
115
|
+
|
|
116
|
+
### 10. `runCatching` 적용에 학생의 자가 의문
|
|
117
|
+
|
|
118
|
+
학생: "최소한의 입력 검증에 대해서는 runCatching 구문으로 변경하였으나, 객체가 가진 기능 요구사항에 대한 검증은 runCatching으로 변경하는 것이 고민됩니다. 첫 번째는 테스트 코드로 작성할 수 없다는 점이고 두 번째는 inputView를 호출하게 되지 않을까? 하는 생각이 듭니다."
|
|
119
|
+
|
|
120
|
+
## 리뷰어 의견 요지
|
|
121
|
+
|
|
122
|
+
1. **타입 시그니처가 invariant 표현** — `Set<LottoNumber>` 또는 `List<LottoNumber>`가 *List<Int>*보다 강력. "초기화 체크 vs 자료구조 선택"의 차이를 학생이 직접 정리.
|
|
123
|
+
2. **Validator 클래스 = 상태 없는 행위 객체** — 같은 행위가 도메인 객체의 `init`으로 옮겨가야 응집도↑.
|
|
124
|
+
3. **테스트는 *대상*을 *직접 깨뜨려*야 함** — Random을 거쳐 검증하면 Random을 테스트.
|
|
125
|
+
4. **랜덤 요소는 *주입*해서 테스트 격리** — `fun interface LottoGenerator`로 자동/수동/테스트 fake.
|
|
126
|
+
5. **Flyweight = 도메인 객체 수가 유한할 때의 표준** — 1~45 캐싱.
|
|
127
|
+
6. **Tell, Don't Ask** — `lotto.lotto` 노출 대신 `lotto.matchCount`.
|
|
128
|
+
7. **검증만 하는 클래스는 객체가 아님** — 도메인 메서드 없이는 *struct + factory*.
|
|
129
|
+
8. **상태 없는 협력자는 단일 인스턴스** — `LottoMachine()`을 매 run마다 새로 만들 이유 없음.
|
|
130
|
+
|
|
131
|
+
- **대표 인용:**
|
|
132
|
+
> Lotto 도메인에 대해 테스트가 이루어졌을까요? `Lotto(listOf(1,2,1,2,1,2))`와 같은 객체도 생성될 수 있겠네요.
|
|
133
|
+
> — @KwonDae on `src/main/kotlin/lotto/domain/Lotto.kt`
|
|
134
|
+
|
|
135
|
+
> 2인승 자동차에 인원을 태우면서 더이상 타지 못함을 알리는 것 보다 2인승 자동차라는 것을 알려준다면 보다 효과적으로 외부에도 알리기도 쉽고 추가 검증도 필요 없겠죠?
|
|
136
|
+
> — @KwonDae on `src/main/kotlin/lotto/domain/Lotto.kt`
|
|
137
|
+
|
|
138
|
+
> buyLotto()에 대해 테스트가 불가능하네요. … 왜 테스트가 불가하고, 어떻게 개선할 수 있을까요?
|
|
139
|
+
> — @KwonDae on `src/main/kotlin/lotto/domain/LottoMachine.kt`
|
|
140
|
+
|
|
141
|
+
> 로또 번호는 1~45로 정해져 있습니다. 만약 동일한 로또 번호가 다른 게임에도 여러 번 사용이 된다면 해당 로또 번호는 다른 객체이어야만 할까요?
|
|
142
|
+
> — @KwonDae on `src/main/kotlin/lotto/domain/LottoNumber.kt`
|
|
143
|
+
|
|
144
|
+
> 이 클래스의 역할은 무엇일까요? 단순 로또 구입 금액만 갖고 있는 클래스로 보이는데요! 필요성에 대해 궁금합니다.
|
|
145
|
+
> — @KwonDae on `src/main/kotlin/lotto/domain/LottoPayment.kt`
|
|
146
|
+
|
|
147
|
+
## 얻은 교훈
|
|
148
|
+
|
|
149
|
+
- **타입 시그니처가 invariant**. `List<Int>` → `Set<LottoNumber>`로 가는 순간 *개수·범위·중복*이 타입으로 강제됨.
|
|
150
|
+
- **2인승 자동차 비유** — 타고 나서 "더 못 타"라고 하는 대신 *2인승*이라고 말하는 것이 외부에도 친절. 자료구조 선택이 *말해주는* 도구.
|
|
151
|
+
- **Validator 클래스는 도메인의 `init`이어야 한다** — Validator만 늘어나는 구조는 *행위 위주*. 도메인 객체로 위임하면 *위치-검증-사용* 한 곳.
|
|
152
|
+
- **테스트 대상은 *입력으로 직접 깨뜨려야* 의미**. Random을 거쳐 검증하면 Random을 테스트. `Lotto(listOf(1, 1,.))`로 예외 발생을 확인.
|
|
153
|
+
- **랜덤 요소는 *외부 주입*** — `fun interface LottoGenerator`에 자동/수동/테스트 fake를 다 끼울 수 있어야 격리 가능.
|
|
154
|
+
- **유한 원시 도메인은 Flyweight**. `LottoNumber.from(value)`로 캐싱 인스턴스 조회 + `private constructor`.
|
|
155
|
+
- ***Tell, Don't Ask*는 컬렉션도 동일**. `lotto.lotto` 공개는 외부가 컬렉션 메서드를 호출. `lotto.matchCount(other)`로 행위 위임.
|
|
156
|
+
- **검증만 하는 클래스는 객체가 아니다**. `LottoPayment`가 검증만 하면 `data class` + 단순 함수가 더 정직. *상태로 무엇을 하는가*가 객체의 정체성.
|
|
157
|
+
- ***상태 없는 협력자는 단일 인스턴스*** — `LottoMachine()`을 매 run마다 생성한다면 *상태가 있을 가능성*을 암시. 의도가 *상태 없음*이면 클래스 바디 또는 `object`.
|
|
158
|
+
- **`runCatching`의 한계 = *검증 결과를 잃음***. 테스트에서 *오류 자체*가 검증 대상이면 `runCatching`이 아니라 `assertThrows`. 도메인 검증은 *예외를 던지는* 쪽으로 두고, 입력 단계만 `runCatching`.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# PR #145 — [로또 2단계] 토바에 미션
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@tobae-time](https://github.com/tobae-time)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/145
|
|
5
|
+
- **단계:** 2단계 (수동 로또 추가)
|
|
6
|
+
- **리뷰어:** @KwonDae (제이든)
|
|
7
|
+
- **라인 코멘트:** 24
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`LottoNumber` `value class`** — 학생이 *data class vs value class* 차이를 정확히 정리.
|
|
12
|
+
- **`Order` 도메인 객체 도입** — 구매 정보 묶기.
|
|
13
|
+
- **`LottoManualGenerator` + `LottoRandomGenerator`** — Strategy 인터페이스 활용.
|
|
14
|
+
- **리뷰 반영 커밋 해시 명시** — 변경 추적 용이.
|
|
15
|
+
|
|
16
|
+
## 못한 점 (설계 관점)
|
|
17
|
+
|
|
18
|
+
### 1. 1000원 미만 = 종료, 거스름돈 안내 부재
|
|
19
|
+
|
|
20
|
+
리뷰어: "현재 1000원 미만을 입력하게 되면 프로그램이 종료되고 1500원과 같은 나머지 금액이 발생해도 별다른 안내가 이루어지지 않고 있습니다. 이것들을 모두 *논리 오류*라고 부르게 되는데요. 2단계의 요구사항은 *예외 처리를 통해 에러가 발생하지 않도록 한다. 논리적인 오류일 때만 예외를 던진다. 논리적인 오류가 아니면 예외를 던지지 말고 null을 반환한다*." + "만약 500원 단위의 돈이 남았다고 해도 사용자는 받을 수 없을 거예요." — 거스름돈은 *도메인 시나리오*. 단순 종료는 UX 부족.
|
|
21
|
+
|
|
22
|
+
### 2. `Order`의 `var manualCount` + `setManualCount` 패턴
|
|
23
|
+
|
|
24
|
+
```kotlin
|
|
25
|
+
class Order(private val purchaseAmount: Int) {
|
|
26
|
+
var manualCount: Int = 0
|
|
27
|
+
private set
|
|
28
|
+
fun setManualCount(count: Int) {
|
|
29
|
+
require(count <= totalCount) { ERROR_OVER_MAX_COUNT }
|
|
30
|
+
manualCount = count
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
학생: "처음에는 수동 개수도 생성자로 받았으나, 구매 금액에 대한 검증이 수동 로또 구매 이후라서 생성자에서 제거하고 코드의 순서를 변경하였습니다. 더 좋은 방법이 있을 것 같은데 잘 떠오르지 않습니다." 리뷰어: "현재 LottoMachine이라는 객체를 활용해 보면 어떨까요? `fun makeLottoTicket(purchaseAmount: Int, manualCount: Int): List<Lotto>`. 구매 금액에 대한 검증도 LottoMachine에서 가능할 것 같아요" — *생성 시 모든 정보*를 받게 만들면 setter 불필요.
|
|
36
|
+
|
|
37
|
+
### 3. `LottoMachine`이 발행된 티켓 보유
|
|
38
|
+
|
|
39
|
+
```kotlin
|
|
40
|
+
class LottoMachine {
|
|
41
|
+
private val lottoTickets: MutableList<Lotto> = mutableListOf()
|
|
42
|
+
fun buyLottoTicket(lottoGenerator: LottoGenerator) { lottoTickets.add(.) }
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
리뷰어: "LottoMachine이 티켓을 갖고 있는 게 어색해 보입니다. 실제로도 *로또 상점이 티켓에 대한 상태*를 갖고 있을까요? 로또 티켓의 데이터는 어디 있는 게 자연스러울까요?" — *발행 도구*가 *발행물*을 보유하는 것은 현실 비유와도 안 맞음.
|
|
47
|
+
|
|
48
|
+
### 4. `Order`의 *manualCount만 사용*
|
|
49
|
+
|
|
50
|
+
리뷰어: "사실상 현재 프로그램에서 manualCount만 사용되고 있어서 반드시 필요한가? 생각이 들었습니다. `val manualLotto: List<Lotto> =.; val autoLotto: List<Lotto> =.`로도 관리가 가능해 보이는데." — *도메인 객체*가 *한 필드만 사용*되면 *추상화 가치*가 약함.
|
|
51
|
+
|
|
52
|
+
### 5. `prepareLottoTicket` — 한 함수가 많은 일
|
|
53
|
+
|
|
54
|
+
```kotlin
|
|
55
|
+
private fun prepareLottoTicket(purchaseAmount: Int): List<Lotto> {
|
|
56
|
+
val order = Order(purchaseAmount)
|
|
57
|
+
val manualLottoCount = getManualLottoCount()
|
|
58
|
+
order.setManualCount(manualLottoCount)
|
|
59
|
+
generateLottoTicket(order)
|
|
60
|
+
val lottoTickets = lottoMachine.getLottoTickets()
|
|
61
|
+
outputView.printPurchasedLottoTickets(manualLottoCount, lottoTickets)
|
|
62
|
+
return lottoTickets
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
리뷰어: "현재 `prepareLottoTicket` 함수가 너무 많은 일을 하고 있습니다. *함수(또는 메서드)가 한 가지 일만 잘 하도록 구현*한다 요구사항을 만족해 볼까요?" + "`val ticket = lottoMachine.createLottoTicket(amount, manualCount)`. 객체에게 보다 *주체적으로 일하게끔* 메시지를 던져 볼 수 있을까요?"
|
|
67
|
+
|
|
68
|
+
### 6. `toInt` vs `toIntOrNull` 의도
|
|
69
|
+
|
|
70
|
+
```kotlin
|
|
71
|
+
fun getManualLottoCount(): String {
|
|
72
|
+
val input = readln()
|
|
73
|
+
if (validateInteger(input)) { return input }
|
|
74
|
+
return getManualLottoCount() // ⚠ 재귀
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
리뷰어: "기존 kotlin에서 `toInt`와 `toIntOrNull` 둘 다 개발한 건 어떤 의도였을까요? *논리적인 오류가 아니면 예외를 던지지 말고 null을 반환*." — `toIntOrNull()` + `?:` 흐름.
|
|
79
|
+
|
|
80
|
+
### 7. `data class` vs `value class` 학생 정리 (정확)
|
|
81
|
+
|
|
82
|
+
학생: "data class에서 자동으로 생성되는 메서드는 toString(), equals(), hashCode(), copy(), componentN(). value class는 copy(), componentN()이 없음. data class는 var 허용, value class는 val만. data class는 property 제한 없음, value class는 하나의 property만." — *언어 특징의 명확한 비교*.
|
|
83
|
+
|
|
84
|
+
### 8. 테스트 데이터 — `setOf` 직접 활용
|
|
85
|
+
|
|
86
|
+
```kotlin
|
|
87
|
+
Lotto(listOf(LottoNumber(1), LottoNumber(2),.).toSet())
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
리뷰어: "`setOf(..)` 함수로도 가능할 것 같아요. 또한, 테스트 내부 *팩토리 함수*를 통해 보다 간결하게도 테스트 코드 작성도 도전해 볼 수 있겠어요!"
|
|
91
|
+
|
|
92
|
+
## 리뷰어 의견 요지
|
|
93
|
+
|
|
94
|
+
- ***논리적 오류 처리* = 종료가 아니라 *재시도* 또는 *거스름돈*** — UX 시나리오 추가.
|
|
95
|
+
- **setter 패턴 = 책임 누수** — 생성 시 모든 정보를 받는 객체로.
|
|
96
|
+
- **상태(*발행된 티켓*) 보유 객체와 *발행 도구* 분리** — *Machine*은 *발행 행위만*.
|
|
97
|
+
- **도메인 객체가 *한 필드만 사용*되면 추상화 약함** — 직접 List 보유도 옵션.
|
|
98
|
+
- **함수 한 가지 일** — 조립/입력/출력이 한 함수에 섞이지 않게.
|
|
99
|
+
- **`toInt` vs `toIntOrNull` 선택은 *오류 처리 전략***.
|
|
100
|
+
|
|
101
|
+
- **대표 인용:**
|
|
102
|
+
> LottoMachine이 티켓을 갖고 있는 게 어색해 보입니다. 실제로도 로또 상점이 티켓에 대한 상태를 갖고 있을까요?
|
|
103
|
+
> — @KwonDae on `src/main/kotlin/lotto/domain/LottoMachine.kt`
|
|
104
|
+
|
|
105
|
+
> 만약 500원 단위의 돈이 남았다고 해도 사용자는 받을 수 없을 거예요.
|
|
106
|
+
> — @KwonDae on `src/main/kotlin/lotto/domain/Order.kt`
|
|
107
|
+
|
|
108
|
+
> 객체에게 보다 주체적으로 일하게끔 메시지를 던져 볼 수 있을까요?
|
|
109
|
+
> — @KwonDae on `src/main/kotlin/lotto/controller/LottoController.kt`
|
|
110
|
+
|
|
111
|
+
## 얻은 교훈
|
|
112
|
+
|
|
113
|
+
- **거스름돈 = 도메인 시나리오** — 1500원 입력 시 1장 + 500원 잔돈. UX 명세에 포함.
|
|
114
|
+
- **`runCatching` 재시도**가 *종료*보다 사용자 친화.
|
|
115
|
+
- **setter 패턴 회피** — `var + setManual()`은 *시간 결합*. 생성자에 *모든 정보*.
|
|
116
|
+
- **객체의 *상태 보유*와 *행위*는 명확히 구분** — `LottoMachine`이 *티켓을 누적*하면 *발행 도구 + 저장소*가 됨.
|
|
117
|
+
- **도메인 객체가 *한 필드만 사용*되면 *추상화 가치 약함*** — 직접 변수로 두고, *진짜 필요한 책임*을 묶을 때 객체로.
|
|
118
|
+
- **함수 한 가지 일** — Controller 메서드도 *조립* 외 *반복 + 출력 + 검증*이 섞이면 분리.
|
|
119
|
+
- **value class vs data class** — *불변성/한 필드*는 value, *copy/componentN/var* 필요면 data.
|
|
120
|
+
- **테스트 팩토리 메서드**로 *반복 setup*을 짧게.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# PR #42 — [베리] 2단계 로또
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@whk06061](https://github.com/whk06061)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/42
|
|
5
|
+
- **단계:** 2단계
|
|
6
|
+
- **리뷰어:** @galcyurio
|
|
7
|
+
- **라인 코멘트:** 14
|
|
8
|
+
|
|
9
|
+
## 핵심 지적
|
|
10
|
+
|
|
11
|
+
- **`e.printStackTrace()` 추가** — 디버깅 정보.
|
|
12
|
+
|
|
13
|
+
```kotlin
|
|
14
|
+
try {. } catch (e: Exception) {
|
|
15
|
+
e.printStackTrace() // ⚠ 누락 → 추가
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 얻은 교훈
|
|
20
|
+
|
|
21
|
+
- **예외 디버깅 정보 = stacktrace 보존**. catch에서 그냥 메시지만 출력하면 호출 경로 잃음.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# PR #9 — [베리] 1단계 로또
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@whk06061](https://github.com/whk06061)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/9
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @galcyurio
|
|
7
|
+
- **라인 코멘트:** 21
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`Rank` enum + factory** — 등수 결정 로직 캡슐화.
|
|
12
|
+
- **`LottoMoney`/`LottoNumber` 원시값 포장 시도**.
|
|
13
|
+
- **`TestNumberGenerator`로 랜덤 격리 시도**.
|
|
14
|
+
|
|
15
|
+
## 못한 점 (설계 관점)
|
|
16
|
+
|
|
17
|
+
### 1. 패키지 구분 — `constants` vs `domain`
|
|
18
|
+
|
|
19
|
+
학생: "Rank enum class의 패키지가 constants 패키지가 맞는지 domain 패키지가 맞는지 잘 모르겠어서." 리뷰어: "패키지는 가능하면 *기능 단위*로 분리해 주시면 좋습니다." 학생: "view, domain, controller 구조로 분리하는 것이 좋을 것 같아 Rank 클래스의 패키지를 domain 패키지로 옮겼습니다."
|
|
20
|
+
|
|
21
|
+
### 2. `LottoNumber`의 *일급 객체화* 의문
|
|
22
|
+
|
|
23
|
+
학생: "로또 숫자 하나를 일급 객체로 감싸는 이유가 아직 잘 와닿지 않습니다. 데이터의 유효성 검증을 하기 위해 감싸는 걸까요?" 리뷰어 답: "객체지향적으로 사용하기 위함입니다. 로또 숫자가 *Int로 넘어오면* `1~45가 맞을까? 0이거나 음수로 넘어오면 어떡하지?` 로또 숫자가 *LottoNumber로 넘어오면* LottoNumber를 만들려면 *반드시 1~45*여야 하니까 안심하고 쓸 수 있겠구나. 위와 별개로 *도메인 관련 로직*을 LottoNumber에 포함시키면 조금 더 객체 지향적인 코드가 됩니다."
|
|
24
|
+
|
|
25
|
+
### 3. `LottoNumber.LOTTO_NUMBER_RANGE_ERROR` 하드코딩
|
|
26
|
+
|
|
27
|
+
```kotlin
|
|
28
|
+
private const val LOTTO_NUMBER_RANGE_ERROR = "로또 번호는 1과 45 사이여야 합니다."
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
리뷰어: "만약 로또의 정책이 변경되어 1, 45가 바뀌는 경우 *2개 상수를 수정*해야 합니다. `LOTTO_NUMBER_RANGE_ERROR`에서는 하드코딩 대신 *기존에 선언되어 있는 상수*를 활용해 주세요."
|
|
32
|
+
|
|
33
|
+
### 4. `Rank.valueOf`의 `!!` 강제 언패킹
|
|
34
|
+
|
|
35
|
+
```kotlin
|
|
36
|
+
return values().findLast { rank -> rank.countOfMatch == countOfMatch }!!
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
리뷰어: "`!!`을 사용하는 대신 null 처리 또는 *null을 처리하지 않아도 되는 코드*로 변경해 보세요." 학생: "예외를 던지도록 수정했습니다. 다만 한 가지 여쭤보고 싶은 점이 있는데, 만약 상응하는 Rank가 없어서 예외가 발생한 경우 이 예외를 따로 처리해 줘야 될까요?" 리뷰어: "이 경우는 *논리 오류*일 때 예외를 던지는 케이스이기 때문에 따로 예외 처리하기보다는 `setDefaultUncaughtExceptionHandler()`와 같이 *전역적으로 설정된 예외 처리*에 걸리도록 해 주셔야 합니다."
|
|
40
|
+
|
|
41
|
+
### 5. *유효성 검사 vs 논리 오류 require* 학생 의문
|
|
42
|
+
|
|
43
|
+
학생: "LottoMoney를 생성할 때 입력값 그대로를 (String 타입으로) 넘겨준 후, Int 변환 검사를 LottoMoney 클래스 내에서 진행하는 방식 중 어떤 방식이 나은지 판단이 잘 안 됩니다." 리뷰어: "*유효성 검사*는 보통 요구사항으로 입력이 잘못된 경우에 *다시 유저에게 입력*을 받아야 하므로 View에서 다시 입력받도록 만들어야 합니다. *논리 오류일 때 예외 던지기*는 개발자의 실수로 이러한 유효성 검사를 지나치면 *디버깅하기가 어려우므로 빠르게 실패*하도록 만들어 줘야 합니다. *최악 대신 차악*이 되도록 만드는 개념입니다."
|
|
44
|
+
|
|
45
|
+
### 6. 테스트 데이터의 *본문 밖 정의*
|
|
46
|
+
|
|
47
|
+
```kotlin
|
|
48
|
+
@MethodSource("matchingCountNumbers")
|
|
49
|
+
@ParameterizedTest
|
|
50
|
+
fun `당첨 번호와 몇개 일치 하는지 판단 한다`(.) {. }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
리뷰어: "좋은 테스트 코드는 *테스트 본문만 보아도 테스트하는 의도*를 모두 알 수 있어야 합니다. MethodSource는 테스트 본문에서 분리되므로 *두 곳을 모두 확인*해야 합니다. … 이러한 상황에는 `@CsvSource`를 추천드립니다." 후속: "CsvSource에서 내부적으로 `valueOf()`를 통해 enum을 가져올 수 있습니다."
|
|
54
|
+
|
|
55
|
+
### 7. 테스트 코드의 *중복 제거 vs 가독성*
|
|
56
|
+
|
|
57
|
+
학생: 중복 setup을 `makeUserLotto`/`makeWinningNumbers` 팩토리로 분리. 리뷰어: "훨씬 더 짧아져서 가독성이 좋아졌네요. 추가적으로 테스트 코드는 *어떻게 하면 어떻게 되는지*를 코드로 나누어 주시면 더 좋습니다. 흔히 *given, when, then* 주석으로 나누는 패턴입니다." + "테스트 코드에서는 *중복을 제거하는 것보다 가독성을 향상시키는 게 더 중요*합니다. 때에 따라서는 중복을 제거했을 때, *가독성을 해친다면 중복을 그대로* 두기도 합니다."
|
|
58
|
+
|
|
59
|
+
## 리뷰어 의견 요지
|
|
60
|
+
|
|
61
|
+
- **패키지는 *기능 단위*** — `constants`는 *모든 상수*면 god-folder, *기능별*로.
|
|
62
|
+
- **일급 객체 = 검증 + 도메인 행위** — *둘 다* 갖춰야 의미.
|
|
63
|
+
- **상수 + 메시지 = *상수 참조***로 변경 동기화.
|
|
64
|
+
- **`!!` 회피** — null 처리 또는 *null이 안 되는 구조*.
|
|
65
|
+
- **유효성 검사 (재입력) vs 논리 오류 (예외)** — *재입력*은 View, *디버깅*은 require.
|
|
66
|
+
- **`@CsvSource` + enum 자동 변환** — 본문에 의도 명시.
|
|
67
|
+
- **테스트 중복 제거는 *가독성 우선*** — 분리는 *서명만 보이게*.
|
|
68
|
+
- **given-when-then 패턴**.
|
|
69
|
+
|
|
70
|
+
- **대표 인용:**
|
|
71
|
+
> 로또 숫자가 LottoNumber로 넘어오면 LottoNumber를 만들려면 반드시 1~45여야 하니까 안심하고 쓸 수 있겠구나.
|
|
72
|
+
> — @galcyurio on `src/main/kotlin/lotto/domain/LottoNumber.kt`
|
|
73
|
+
|
|
74
|
+
> 좋은 테스트 코드는 테스트 본문만 보아도 테스트하는 의도를 모두 알 수 있어야 합니다.
|
|
75
|
+
> — @galcyurio on `src/test/kotlin/lotto/domain/LottoTest.kt`
|
|
76
|
+
|
|
77
|
+
> *유효성 검사*는 보통 요구사항으로 입력이 잘못된 경우에 다시 유저에게 입력을 받아야 하므로 View에서. *논리 오류*는 디버깅하기가 어려우므로 빠르게 실패하도록.
|
|
78
|
+
> — @galcyurio on `src/main/kotlin/lotto/domain/LottoMoney.kt`
|
|
79
|
+
|
|
80
|
+
## 얻은 교훈
|
|
81
|
+
|
|
82
|
+
- **패키지는 *기능 단위*** — *모든 상수*가 한 곳이면 god-folder. 도메인별로.
|
|
83
|
+
- **일급 객체화의 *2가지 가치*** — 검증 + 도메인 행위. 둘 다 갖춰야 *비용 정당화*.
|
|
84
|
+
- **상수 + 메시지 = 상수 참조** — 메시지 안의 숫자가 *하드코딩*이면 *변경 동기화 실패*.
|
|
85
|
+
- **`!!`는 *코드의 자가 의심***. *null이 안 되는 구조*로 가거나, *명시적 null 처리*.
|
|
86
|
+
- ***유효성 검사 vs 논리 오류*** — *재입력*은 View, *디버깅*은 require. 둘은 다른 흐름.
|
|
87
|
+
- **테스트 본문에 *의도 명시*** — MethodSource보다 CsvSource로 *본문 안에서* 케이스 + 기대값.
|
|
88
|
+
- **테스트 중복 제거는 *가독성 우선*** — 분리 시 *팩토리 메서드*로, 본문은 *given-when-then*.
|
|
89
|
+
- **enum 자동 변환** — CsvSource가 `valueOf()`로 enum 자동 매핑.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# PR #118 — [로또 1단계] 모찌 미션
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@wondroid-world](https://github.com/wondroid-world)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/118
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @Gyuil-Hwnag
|
|
7
|
+
- **라인 코멘트:** 60
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`Lotto`, `LottoMachine`, `Rank` 분리**.
|
|
12
|
+
- **companion object 활용**.
|
|
13
|
+
|
|
14
|
+
## 못한 점 (설계 관점)
|
|
15
|
+
|
|
16
|
+
### 1. `Constants.kt` 단일 파일
|
|
17
|
+
|
|
18
|
+
```kotlin
|
|
19
|
+
object Constants {
|
|
20
|
+
const val LOTTO_PRICE = 1000
|
|
21
|
+
const val MIN_NUMBER = 1
|
|
22
|
+
const val MAX_NUMBER = 45
|
|
23
|
+
//. 계속 늘어남
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> 상수화도 잘해주셨네요~ 추후 상수 관련된 내용이 많아진다면, 모두 Constants 내에 모이게 되는걸까요?
|
|
28
|
+
|
|
29
|
+
→ god-folder 시뮬레이션 압박. 도메인별 분리.
|
|
30
|
+
|
|
31
|
+
### 2. `Lotto`의 bonusNumber가 nullable
|
|
32
|
+
|
|
33
|
+
```kotlin
|
|
34
|
+
class Lotto(val numbers: List<Int>, val bonusNumber: Int? = null) {. }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> bonusNumber를 nullable 하게 설정하신 이유가 있을까요..?
|
|
38
|
+
|
|
39
|
+
→ 당첨 로또에만 보너스 있음. `Lotto`/`WinningLotto` 분리가 더 자연스러움.
|
|
40
|
+
|
|
41
|
+
### 3. `numbers.toList()` 중복
|
|
42
|
+
|
|
43
|
+
```kotlin
|
|
44
|
+
class Lotto(val numbers: List<Int>) {
|
|
45
|
+
val sortedNumbers: List<Int> = numbers.toList().sorted() // ⚠ 이미 List인데 toList()
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
> 이미 numbers는 List Collection 인데, toList()를 붙히신 이유가 궁금합니다!
|
|
50
|
+
|
|
51
|
+
→ 방어적 복사 의도였다면 명시적으로. 무의식 호출은 noise.
|
|
52
|
+
|
|
53
|
+
### 4. Lotto가 자기 번호 생성까지
|
|
54
|
+
|
|
55
|
+
```kotlin
|
|
56
|
+
class Lotto(.) {
|
|
57
|
+
companion object {
|
|
58
|
+
fun create(): Lotto = Lotto((1..45).shuffled().take(6)) // ⚠ 자기 생성
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
> 로또 번호 생성도 로또 객체의 책임이라고 지정을 하신 이유가 궁금합니다~
|
|
64
|
+
|
|
65
|
+
→ 생성 책임은 *Factory*/*Generator*. Lotto 자체는 *주어진 번호의 검증/매칭/조회*만.
|
|
66
|
+
|
|
67
|
+
### 5. `LottoMachine.lottos` — 책임 모호
|
|
68
|
+
|
|
69
|
+
```kotlin
|
|
70
|
+
class LottoMachine {
|
|
71
|
+
val lottos: List<Lotto> =. // ⚠ "lottos"가 무엇을 의미?
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> LottoMachine.lottos로 보니까 뭔가 어떤기능을 담당하는지 잘 눈에 안들어오는 느낌이 들었는데
|
|
76
|
+
> ```kotlin
|
|
77
|
+
> val purchaseLottos = LottoMachine.purchase(count)
|
|
78
|
+
> vs
|
|
79
|
+
> val purchaseLottos = LottoMachine.lottos
|
|
80
|
+
> ```
|
|
81
|
+
|
|
82
|
+
→ 메서드 (`purchase`)가 *행위*를 명시. property는 *상태*만.
|
|
83
|
+
|
|
84
|
+
## 리뷰어 의견 요지
|
|
85
|
+
|
|
86
|
+
리뷰어 @Gyuil-Hwnag의 가르침:
|
|
87
|
+
|
|
88
|
+
1. **god-folder 시뮬레이션 — "추후 상수가 많아지면?"**
|
|
89
|
+
|
|
90
|
+
2. **WinningLotto vs Lotto 분리** — Lotto가 bonus를 nullable로 가지면 *두 개념을 합친 상태*.
|
|
91
|
+
|
|
92
|
+
3. **생성 책임의 분리** — Factory/Generator로.
|
|
93
|
+
|
|
94
|
+
4. **메서드 vs property — 행위 vs 상태 구분**.
|
|
95
|
+
|
|
96
|
+
## 얻은 교훈
|
|
97
|
+
|
|
98
|
+
- **god-folder 시뮬레이션 = "추후 N배로 늘면?"** lotto에서도 racingcar에서도 동일 패턴. `Constants.kt` 시작은 깔끔해도 시간 갈수록 god-folder.
|
|
99
|
+
- **nullable로 두 개념 합치기 회피**. `Lotto` (bonus 없음) vs `WinningLotto` (bonus 있음) → 두 클래스. nullable은 *부재의 표현*이지 *분기의 표현*이 아님.
|
|
100
|
+
- **메서드와 property의 의미 차이** — `machine.lottos` (보유) vs `machine.purchase(count)` (행위). lotto 미션에서 "기계는 로또를 *준다*" 행위.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# PR #150 — [로또 2단계] 모찌 미션
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@wondroid-world](https://github.com/wondroid-world)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-lotto/pull/150
|
|
5
|
+
- **단계:** 2단계 (수동 로또 추가)
|
|
6
|
+
- **리뷰어:** @Gyuil-Hwnag
|
|
7
|
+
- **라인 코멘트:** 41
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`LottoTicketGenerator` 인터페이스 + `AutoLottoTicketGenerator`/`ManualLottoTicketGenerator`** — 자동/수동을 인터페이스로 묶어 분리. Strategy.
|
|
12
|
+
- **`LottoStoreCashier`로 금전 처리 분리** — 가능 수량 계산/잔돈/검증을 한 객체로.
|
|
13
|
+
- **`LottoTicket.matchNumbersSize(other)`** — 매칭 개수 계산을 *내가 알고 있는 정보*에 위치시킴.
|
|
14
|
+
- **각 객체에 *역할 정의 주석*을 남기는 습관** — 학생이 "객체 하나당 한 역할을 한다고 정의하고 싶어서"라고 동기를 명시.
|
|
15
|
+
|
|
16
|
+
## 못한 점 (설계 관점)
|
|
17
|
+
|
|
18
|
+
### 1. `LottoTicket`이 `LottoIssueType`(자동/수동)을 필드로 보유
|
|
19
|
+
|
|
20
|
+
```kotlin
|
|
21
|
+
class LottoTicket(
|
|
22
|
+
private val lottoIssueType: LottoIssueType,
|
|
23
|
+
private val numbers: List<LottoNumber>,
|
|
24
|
+
)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
리뷰어: "type이 꼭 있어야 하는 이유가 있을까요? 현재 LottoTicket에서는 전혀 사용을 안 하고 있는 것 같은데, 추가를 하신 이유가 궁금합니다." 학생 답: "현실에서 로또를 발행했을 때, 번호 옆에 자동/수동이 표시" — *표시 정보*를 도메인 필드로 끌어들임. 표시 형식이 도메인의 정체성이 되면 표현 변경이 도메인 변경.
|
|
28
|
+
|
|
29
|
+
### 2. `LottoTicketIssueManager` — 함수/필드명 비대
|
|
30
|
+
|
|
31
|
+
```kotlin
|
|
32
|
+
class LottoTicketIssueManager(
|
|
33
|
+
customerWantBuyLottoTicketCount: Int,
|
|
34
|
+
customerWantToBuyManualLottoTicketCount: Int,
|
|
35
|
+
manualLottoNumbers: List<List<Int>>,
|
|
36
|
+
) {
|
|
37
|
+
fun getCustomerWantToBuyManualLottoTicketCount(): Int =.
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
리뷰어: "함수명이 어마무시하게 길군요. 무조건 짧아야 한다는 아니지만, 엄청 긴데 무슨 기능을 하는지 한눈에도 안 들어오는 느낌이 살짝 드는군요." — *문장형 변수명*은 도메인 어휘 부재의 신호. `manualLottoCount`/`autoLottoCount`로 충분.
|
|
42
|
+
|
|
43
|
+
### 3. 모든 메서드에 한 줄 주석
|
|
44
|
+
|
|
45
|
+
```kotlin
|
|
46
|
+
// 로또 발행하는 머신
|
|
47
|
+
class LottoMachine {
|
|
48
|
+
// 로또 티켓을 발행한다.
|
|
49
|
+
fun issueLottoTickets(.) =.
|
|
50
|
+
|
|
51
|
+
// 자동 로또를 발행
|
|
52
|
+
private fun purchaseAutoLottoTickets(.) {. }
|
|
53
|
+
|
|
54
|
+
// 수동 로또를 발행
|
|
55
|
+
private fun purchaseManualLottoTickets(.) {. }
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
리뷰어: "함수명 or 구현된 코드를 보고도 유추할 수 있는 모든 내용들에 주석이 존재한다면 오히려 구현을 이해하는데 혼동을 줄 수도 있기는 해서 추후 개발을 하면서 어떤 부분에 남겨야 할지 모찌만의 기준을 잘 잡으셨으면 좋겠습니다." — 함수명과 *완전히 동일한 정보*를 가진 주석은 잡음. 주석은 *왜*를 설명할 때만.
|
|
60
|
+
|
|
61
|
+
### 4. `LottoTicketCount.toInt()` — 의미 없는 변환
|
|
62
|
+
|
|
63
|
+
```kotlin
|
|
64
|
+
class LottoTicketCount(private val count: Int) {
|
|
65
|
+
fun toInt() = count
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
리뷰어: "`toInt()`로 표현을 하면, 어떤 것을 나타내는지에 대해서 불명확해질 수도 있겠다는 생각도 들긴 하네요!" — 원시값 포장의 의미가 `toInt()` 호출 시점에 다시 사라짐. 도메인 메서드(`value`, `count`)로 어휘 유지.
|
|
70
|
+
|
|
71
|
+
### 5. `InputView`/`OutputView`가 사실상 위임만 함
|
|
72
|
+
|
|
73
|
+
```kotlin
|
|
74
|
+
object InputView { fun getUserInput(): String = readln().trim() }
|
|
75
|
+
object OutputView {
|
|
76
|
+
fun printlnMessage(msg: Any) = println(msg)
|
|
77
|
+
fun printMessage(msg: Any) = print(msg)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
리뷰어: "OutputView와 InputView에서 너무 담당을 하는 것이 없다는 생각이 드네요. `UserInterface`에서 입출력에 대해서 모든 기능을 담당하고 있으므로, 해당 InputView/OutputView의 내용을 UserInterface의 하나의 함수로 만들어 보는 것이 나을 수도 있겠다는 생각이 듭니다!" — 단순 위임만 하는 객체는 *간접 계층*만 추가. 책임이 없으면 객체가 아님.
|
|
82
|
+
|
|
83
|
+
### 6. `UserInterface` → `ViewFlow` 명명
|
|
84
|
+
|
|
85
|
+
리뷰어: "ViewFlow로 변경이 되었군요. 사실 기대를 했던 건 LottoView 등의 이름을 기대했었어요." — `*Flow`는 구현 기법, 도메인 어휘 아님.
|
|
86
|
+
|
|
87
|
+
### 7. `Result<Unit>` + `runCatching`로 Controller 흐름 감싸기
|
|
88
|
+
|
|
89
|
+
```kotlin
|
|
90
|
+
fun run(): Result<Unit> {
|
|
91
|
+
return kotlin.runCatching {
|
|
92
|
+
.
|
|
93
|
+
}.map { Result.success(Unit) }
|
|
94
|
+
.getOrElse { e -> Result.failure(Exception("(로또 실행 중 오류 발생) : ${e.message}")) }
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
학생 자가 분석: "비논리적 오류와 논리적 오류를 잘 구분하지 못해서, 비즈니스 오류에서 나오는 것을 모두 출력하고 프로그램을 종료하고자 위와 같이 구현." — *최상위 try-catch with retry*가 비즈니스 오류와 시스템 오류를 한 그릇에 담아 책임 흐려짐.
|
|
99
|
+
|
|
100
|
+
### 8. `Generator`가 `model` 패키지에
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
lotto/model/AutoLottoTicketGenerator.kt
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
리뷰어: "Generator는 생성자인데, model에 있는 것이 좋을까 싶긴 합니다! 다른 패키지로 옮긴다면 어떤 패키지로 옮겨볼 수 있을까요?" — *생성 서비스*는 도메인 데이터와 다른 계층. `service`/`factory` 패키지로 의도가 드러남.
|
|
107
|
+
|
|
108
|
+
### 9. `class LottoMachine` vs `object`
|
|
109
|
+
|
|
110
|
+
리뷰어 질문: "class 외에 object라는 키워드가 있는데, 이 둘은 어떤 차이점이 있을까요?" — `LottoMachine`이 *상태*를 가지지 않으면 `object`(singleton). 매번 `LottoMachine()`을 생성할 이유가 없음.
|
|
111
|
+
|
|
112
|
+
## 리뷰어 의견 요지
|
|
113
|
+
|
|
114
|
+
1. **표현용 정보는 도메인 필드에 넣지 말 것** — 자동/수동 *표시*는 출력 형식, 티켓의 정체성이 아님.
|
|
115
|
+
2. ***문장형* 식별자는 도메인 어휘 부재의 신호** — `customerWantToBuy.Count` → `manualCount`로 압축.
|
|
116
|
+
3. **자명한 주석 = 잡음** — 함수명과 같은 정보를 반복하는 주석은 가독성을 *낮춤*.
|
|
117
|
+
4. **위임만 하는 객체는 객체가 아님** — `InputView`가 `readln()` 하나면 그 객체의 의미가 없음.
|
|
118
|
+
5. **`object` vs `class`** — 상태 없으면 `object`로 단일 인스턴스화.
|
|
119
|
+
|
|
120
|
+
- **대표 인용:**
|
|
121
|
+
> type이 꼭 있어야 하는 이유가 있을까요? 현재 LottoTicket에서는 전혀 사용을 안 하고 있는 것 같은데, 추가를 하신 이유가 궁금합니다.
|
|
122
|
+
> — @Gyuil-Hwnag on `src/main/kotlin/lotto/model/AutoLottoTicketGenerator.kt`
|
|
123
|
+
|
|
124
|
+
> 함수명이 어마무시하게 길군요. 무조건 짧아야 한다는 아니지만, 엄청 긴데 무슨 기능을 하는지 한눈에도 안 들어오는 느낌이 살짝 드는군요.
|
|
125
|
+
> — @Gyuil-Hwnag on `src/main/kotlin/lotto/model/LottoTicketIssueManager.kt`
|
|
126
|
+
|
|
127
|
+
> toInt()로 표현을 하면, 어떤 것을 나타내는지에 대해서 불명확해질 수도 있겠다는 생각도 들긴 하네요!
|
|
128
|
+
> — @Gyuil-Hwnag on `src/main/kotlin/lotto/model/LottoTicketCount.kt`
|
|
129
|
+
|
|
130
|
+
> Generator는 생성자인데, model에 있는 것이 좋을까 싶긴 합니다! 다른 패키지로 옮긴다면 어떤 패키지로 옮겨볼 수 있을까요?
|
|
131
|
+
> — @Gyuil-Hwnag on `src/main/kotlin/lotto/model/AutoLottoTicketGenerator.kt`
|
|
132
|
+
|
|
133
|
+
## 얻은 교훈
|
|
134
|
+
|
|
135
|
+
- **표시 형식은 도메인 필드가 아님**. `LottoIssueType`은 *출력 시 보여줄 라벨* — 티켓의 정체성이라면 매칭 로직에서 쓰여야 함. 안 쓰는 필드는 ViewModel/DTO로.
|
|
136
|
+
- ***문장형 변수명*은 도메인 어휘 부재의 신호**. `customerWantToBuyManualLottoTicketCount` 같은 이름이 나타나면 *그 개념을 부르는 도메인 단어*가 없다는 뜻 — 새 객체나 새 단어를 찾아야 한다.
|
|
137
|
+
- **주석은 *왜*에만**. `// 자동 로또를 발행` 같이 함수명과 정보가 똑같은 주석은 잡음. 본문 메서드는 잘 이름지어 *없어도 읽히도록*.
|
|
138
|
+
- **원시값 포장의 의미는 *경계*에 있음**. `toInt()`로 빠져나오는 순간 포장 의미 소실 — Count를 받는 쪽도 `LottoTicketCount`로 받아 끝까지 어휘 유지.
|
|
139
|
+
- **위임만 하는 객체는 객체가 아니라 함수**. `InputView`가 `readln()` 하나면 그 추상화는 *비용*만 만듦. 객체는 *상태 또는 정책*이 있어야 한다.
|
|
140
|
+
- **`Result<Unit>` 같은 결과 타입은 *경계*에서만**. 도메인 내부 흐름을 `runCatching`으로 통째 감싸면 비즈니스 오류와 시스템 오류가 한 그릇에. *논리적 오류 = 비즈니스, 비논리적 오류 = 시스템* — 처리 위치가 다름.
|
|
141
|
+
- **`object`는 *상태 없는 단일성*의 표시**. 매번 `LottoMachine()` 생성한다는 것은 "상태가 있을 수도 있다"는 약속 — 정말 상태가 없다면 `object`로 단언.
|
|
142
|
+
- **패키지명도 책임 분류**. `model/Generator`는 *상태와 행위*를 섞은 패키지 — `service`/`factory`로 옮기면 호출 흐름이 패키지 트리에서 자체 설명.
|