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,304 @@
|
|
|
1
|
+
# OOP 설계 스타일 가이드
|
|
2
|
+
|
|
3
|
+
`woowacourse/kotlin-racingcar` 133개 PR 리뷰에서 추출한 보편 원칙 모음. MCP의 자동 검증(`oop_design_validate`)이 잡지 못하지만 **워크숍/리뷰에서 안내할 만한** 규칙들.
|
|
4
|
+
|
|
5
|
+
자세한 사례는 [lessons/woowacourse-racingcar/SUMMARY.md](woowacourse-racingcar/SUMMARY.md) 참고.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 명명 원칙
|
|
10
|
+
|
|
11
|
+
### 1-1. 함수 이름 = 동사 하나만
|
|
12
|
+
|
|
13
|
+
- 안 됨: `executeInputTryNumber()`, `setRacingResult()`, `runOrStop()`
|
|
14
|
+
- 됨: `inputTryNumber()`, `tryMove()`, `stop()`
|
|
15
|
+
|
|
16
|
+
> "이 함수에는 동사가 2개가 존재합니다. (input, try) 함수에는 하나의 동사만 포함시켜보면 어떨까요?" — @BeokBeok ([PR #68](woowacourse-racingcar/hyemdooly/68-1단계-자동차-경주.md))
|
|
17
|
+
|
|
18
|
+
### 1-2. 이름의 *오해 비용* 최소화
|
|
19
|
+
|
|
20
|
+
- `XxxException` 접미사는 **Exception 타입**을 의미. 검증 객체에 붙이면 동료 혼란.
|
|
21
|
+
- `XxxValidator` / `XxxValidation` 으로.
|
|
22
|
+
- `Manager`, `Helper`, `Util`은 거의 항상 god-object 신호 (자동 검증 `vague-class-name` 룰로도 잡힘).
|
|
23
|
+
|
|
24
|
+
### 1-3. 상수 이름 = 의미, 값이 아님
|
|
25
|
+
|
|
26
|
+
- 안 됨: `","`, `STANDARD_NUMBER`, `MAX = 5`
|
|
27
|
+
- 됨: `NAME_DELIMITER`, `MOVEMENT_THRESHOLD`, `MAX_NAME_LENGTH`
|
|
28
|
+
|
|
29
|
+
> "STANDARD_NUMBER는 자동차 경주 게임에 대한 지식이 없는 사람이 보았을 때도 한 번에 알아볼 수 있는 의미를 담은 이름일까요?" — @malibinYun ([PR #145](woowacourse-racingcar/etama123/145-2단계-자동차-경주.md))
|
|
30
|
+
|
|
31
|
+
### 1-4. 메서드명에 컨텍스트 중복 금지
|
|
32
|
+
|
|
33
|
+
- 안 됨: `NumberGenerator.generateNumber()` (Generator + generateNumber → 동어반복)
|
|
34
|
+
- 됨: `NumberGenerator.generate()`
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2. 메시지와 에러
|
|
39
|
+
|
|
40
|
+
### 2-1. 메시지 상수에 매직넘버 박지 말 것
|
|
41
|
+
|
|
42
|
+
```kotlin
|
|
43
|
+
// 안 됨 — 요구사항 변경 시 두 곳 수정
|
|
44
|
+
const val ERROR = "이름은 1~5글자여야 합니다"
|
|
45
|
+
|
|
46
|
+
// 됨 — 한 줄 수정으로 끝
|
|
47
|
+
const val MIN_LEN = 1
|
|
48
|
+
const val MAX_LEN = 5
|
|
49
|
+
val errorMsg = "이름은 $MIN_LEN~${MAX_LEN}글자여야 합니다"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
> "1, 5와 같은 내용이 상수 문자열에 포함될 경우, 요구사항의 변경에 따라 항상 수정이 필요하게 됩니다." — @vagabond95
|
|
53
|
+
|
|
54
|
+
### 2-2. 에러 메시지에 *입력값*을 담아라
|
|
55
|
+
|
|
56
|
+
운영 디버깅의 거의 무료 정보. "잘못된 입력" 대신 "잘못된 입력 'foo bar baz'".
|
|
57
|
+
|
|
58
|
+
### 2-3. 에러 케이스별로 구분된 메시지
|
|
59
|
+
|
|
60
|
+
같은 공통 메시지로 통합하면 어느 경로 실패인지 모름.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 3. 검증 책임의 3분류
|
|
65
|
+
|
|
66
|
+
> **이 원칙은 MCP의 `validation-misplacement` 룰로도 자동 검증된다.**
|
|
67
|
+
|
|
68
|
+
| 검증 종류 | 자리 | 예시 |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| UI 형식 검증 | Interfacer (View) | 빈 문자열, 숫자 아님, 형식 |
|
|
71
|
+
| 사용자 입력 정책 | Coordinator | 재입력 흐름, 종료 조건 |
|
|
72
|
+
| 도메인 무결성 invariant | InformationHolder / Structurer init | 이름 길이, 자동차 두 대 이상, 중복 |
|
|
73
|
+
|
|
74
|
+
`require()` / `check()`를 도메인 init에 두면 invariant 보호가 자동.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 4. 의존 방향
|
|
79
|
+
|
|
80
|
+
> **MCP의 `dependency-direction` 룰로 자동 검증.**
|
|
81
|
+
|
|
82
|
+
- **Domain은 UI/Interfacer를 모른다.** Validator가 OutputView를 의존하면 의존 역전.
|
|
83
|
+
- Coordinator만 Interfacer 협력 허용.
|
|
84
|
+
- 더 엄격: 인터페이스를 Domain에서 정의, Interfacer가 구현 (DIP).
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 5. 책임의 3층 구조 (체스 비유)
|
|
89
|
+
|
|
90
|
+
> @KwonDae ([PR #125](woowacourse-racingcar/Hogu59/125-2단계-자동차-경주.md))
|
|
91
|
+
|
|
92
|
+
- **유저(Controller)** = 명령만 (이 말을 저기로)
|
|
93
|
+
- **체스판(RacingGame)** = 상태 + 명령 해석 (체스판 위에서 일어나는 모든 일)
|
|
94
|
+
- **말(Car)** = 자기 위치 + 자기 행위 (앞으로 한 칸)
|
|
95
|
+
|
|
96
|
+
Controller가 "이 말이 어디로 가야 할지" 판단하면 체스판의 책임이 Controller로 누수된 것.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 6. 자가 점검 질문
|
|
101
|
+
|
|
102
|
+
설계 결정마다 던질 질문 (실제 리뷰어들이 던진 질문):
|
|
103
|
+
|
|
104
|
+
### 6-1. "이 클래스의 책임을 한 문장으로 적어보세요"
|
|
105
|
+
|
|
106
|
+
> "단일 책임 원칙이 어긋나 있는지 확인하는 좋은 방법 중 하나는, 이 클래스의 역할과 책임이 무엇인지 한 문장으로 적어보는 것입니다." — @ghojeong
|
|
107
|
+
|
|
108
|
+
문장이 모호하거나 길면 SRP 위반.
|
|
109
|
+
|
|
110
|
+
### 6-2. "휴가 가도 동료가 일할 수 있는 코드인가?"
|
|
111
|
+
|
|
112
|
+
함수명 + 시그니처만 보고 동료가 같은 일을 할 수 있는가 = SRP 검사법.
|
|
113
|
+
|
|
114
|
+
> "업계에 떠도는 맨날 야근하는 개발 조직 괴담이 역할과 책임이 명확하지 않은 함수, 클래스, 혹은 모듈로 인해서 생긴다고 생각해주세요." — @ghojeong
|
|
115
|
+
|
|
116
|
+
### 6-3. "이 분리가 테스트를 더 명확하게 만드는가?"
|
|
117
|
+
|
|
118
|
+
> **MCP의 `propose_alternatives`가 모든 대안에 이 질문을 첨부함.**
|
|
119
|
+
|
|
120
|
+
분리해도 테스트가 더 명확해지지 않으면 분리할 이유 없음. 분리의 정당화는 테스트 개선이 와야 한다.
|
|
121
|
+
|
|
122
|
+
### 6-4. "도메인이 N배로 늘면 이 구조가 견디는가?"
|
|
123
|
+
|
|
124
|
+
> **MCP의 `propose_alternatives`가 모든 대안에 이 질문을 첨부함.**
|
|
125
|
+
|
|
126
|
+
확장 시나리오 압박 시뮬레이션. KoreanCar/EnglishCar로 늘어도, 상수 1000개로 늘어도, 자동차 1000대로 늘어도.
|
|
127
|
+
|
|
128
|
+
### 6-5. "무슨 객체가 개선되었나?"
|
|
129
|
+
|
|
130
|
+
> "객체지향 패러다임에 들어맞느냐라는 질문에는 제가 아니라 심지님 스스로, 무슨 '객체' 가 개선되었는지 답할 수 있으면 됩니다." — @ghojeong ([PR #115](woowacourse-racingcar/sh1mj1/115-2단계-자동차-경주.md))
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 7. Tell-Don't-Ask 응용
|
|
135
|
+
|
|
136
|
+
### 7-1. 외부에서 getter로 묻고 비교하지 말 것
|
|
137
|
+
|
|
138
|
+
```kotlin
|
|
139
|
+
// 안 됨 — feature-envy
|
|
140
|
+
val maxPos = cars.maxOf { it.position }
|
|
141
|
+
cars.filter { it.position == maxPos }.map { it.name }
|
|
142
|
+
|
|
143
|
+
// 됨 — 일급 컬렉션에 메시지
|
|
144
|
+
cars.findWinners().map { it.name }
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 7-2. element가 스스로 상태 변경하면 컬렉션은 immutable
|
|
148
|
+
|
|
149
|
+
```kotlin
|
|
150
|
+
// 안 됨 — 매번 새 컬렉션
|
|
151
|
+
class Cars(val value: List<Car>) {
|
|
152
|
+
fun moveAll() = Cars(value.map { it.copy(position = it.position + ...) })
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 됨 — element가 자기 상태 변경
|
|
156
|
+
class Cars(val value: List<Car>) {
|
|
157
|
+
fun moveAll() = value.forEach { it.move(...) }
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
> @vagabond95 ([PR #92](woowacourse-racingcar/kmkim2689/92-1단계-자동차-경주.md))
|
|
162
|
+
|
|
163
|
+
### 7-3. depth 줄이기 = 함수 분리 ≠ 재귀로 indentation 감추기
|
|
164
|
+
|
|
165
|
+
> "depth 를 이야기할 때, 쉬운 설명을 위해서 indentation 을 이야기하지만, 엄밀히 이야기하면 abstraction level 을 뜻합니다." — @ghojeong
|
|
166
|
+
|
|
167
|
+
재귀로 들여쓰기만 줄이면 abstraction level은 그대로. **함수 분리**로 abstraction level을 낮춰야 SRP가 살아남.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 8. 외부 비결정성 분리
|
|
172
|
+
|
|
173
|
+
> **MCP의 `non-newable` 룰로 자동 검증.**
|
|
174
|
+
|
|
175
|
+
`Random`, `Clock`, `System` 같은 외부 자원은 *도메인에 직접 의존*하지 말 것.
|
|
176
|
+
|
|
177
|
+
**패턴:**
|
|
178
|
+
1. `interface NumberGenerator { fun generate(): Int }` 또는 `fun interface MoveStrategy { fun isMovable(): Boolean }`
|
|
179
|
+
2. 도메인은 인터페이스만 의존
|
|
180
|
+
3. 프로덕션은 `RandomNumberGenerator` 구현체 주입
|
|
181
|
+
4. 테스트는 `FakeGenerator(values: List<Int>)` 같은 결정적 fake 주입
|
|
182
|
+
|
|
183
|
+
함수형 인터페이스 (Kotlin `fun interface`)는 람다로도 구현 가능해 경량.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 9. 캡슐화 패턴
|
|
188
|
+
|
|
189
|
+
### 9-1. `var position; private set`
|
|
190
|
+
|
|
191
|
+
```kotlin
|
|
192
|
+
class Car(val name: String) {
|
|
193
|
+
var position: Int = 0
|
|
194
|
+
private set
|
|
195
|
+
fun move() { position++ }
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
원시값은 이게 가장 간결. backing property는 컬렉션의 mutable/immutable 분리 시에만.
|
|
200
|
+
|
|
201
|
+
### 9-2. data class + var는 위험
|
|
202
|
+
|
|
203
|
+
`equals/hashCode`가 주생성자 프로퍼티만 보는데 var면 동치성이 깨질 수 있음. data class는 immutable VO가 본업.
|
|
204
|
+
|
|
205
|
+
### 9-3. 단일 값 wrapper = value class
|
|
206
|
+
|
|
207
|
+
```kotlin
|
|
208
|
+
@JvmInline value class Position(val value: Int) {
|
|
209
|
+
init { require(value >= 0) }
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
data class보다 인라인되어 런타임 오버헤드 없음.
|
|
214
|
+
|
|
215
|
+
### 9-4. 정규화는 팩토리 함수, 주 생성자는 검증된 값만
|
|
216
|
+
|
|
217
|
+
```kotlin
|
|
218
|
+
class CarName private constructor(val value: String) {
|
|
219
|
+
init { require(value.isNotBlank() && value.length <= 5) }
|
|
220
|
+
companion object {
|
|
221
|
+
fun of(raw: String) = CarName(raw.trim())
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
주 생성자가 trim까지 하면 "객체 생성 시 입력이 어떻게 변형되는가"가 불투명.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 10. 테스트
|
|
231
|
+
|
|
232
|
+
### 10-1. 테스트 함수명 = 시나리오 + 결과
|
|
233
|
+
|
|
234
|
+
- 안 됨: "정상 동작한다", "예외가 발생한다"
|
|
235
|
+
- 됨: `randomNumber가 4 이상이면 자동차가 움직인다`, `자동차 이름은 5자를 초과할 수 없다`
|
|
236
|
+
|
|
237
|
+
### 10-2. 테스트 setup은 우회 메서드 없이
|
|
238
|
+
|
|
239
|
+
Car의 위치를 5로 만들기 위해 `tryMove()`를 5번 호출하지 말 것. 생성자에 직접 받기.
|
|
240
|
+
|
|
241
|
+
### 10-3. 분기 들어가면 두 테스트로 쪼개라
|
|
242
|
+
|
|
243
|
+
테스트 코드에 `if/when`이 나오면 그건 두 케이스를 한 함수에 담은 것.
|
|
244
|
+
|
|
245
|
+
### 10-4. 자기가 구현 안 한 부분은 자기가 테스트 안 한다
|
|
246
|
+
|
|
247
|
+
`Random.nextInt`, `String.split` 같은 표준 라이브러리는 단위 테스트 대상이 아님.
|
|
248
|
+
|
|
249
|
+
### 10-5. 테스트가 *깨지지 않게* 보편화하는 것 vs 요구사항 바뀌면 갈아엎기
|
|
250
|
+
|
|
251
|
+
> "제 입장에서 테스트 코드란 구현해야할 요구 사항이지, 요구사항에 대한 구현체가 아니기 때문입니다." — @ghojeong
|
|
252
|
+
|
|
253
|
+
지나친 보편화 ("기준 숫자 이하")는 미래의 자기 통제권을 줄임. 요구사항 바뀌면 테스트도 바꿔라.
|
|
254
|
+
|
|
255
|
+
### 10-6. Controller는 단위 테스트 X (통합 테스트로)
|
|
256
|
+
|
|
257
|
+
> "컨트롤러는 UI나 콘솔과 같이 실행에 밀접한 관련이 있기 때문에 일반적으로 단위 테스트를 작성하지는 않습니다." — @laco-dev
|
|
258
|
+
|
|
259
|
+
도메인 테스트에 집중.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 11. 객체 vs 함수
|
|
264
|
+
|
|
265
|
+
> **MCP의 `function-not-object` 룰로 자동 검증.**
|
|
266
|
+
|
|
267
|
+
- **객체 = 메서드 + 멤버 둘 다**. 멤버 없이 함수 하나만 가진 클래스는 객체 아님 → top-level fun 또는 object의 메서드로.
|
|
268
|
+
- **상태 없는 클래스 = object**. 인스턴스마다 다른 상태가 필요할 때만 class.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 12. DI는 키워드가 아니라 역할-책임-협력
|
|
273
|
+
|
|
274
|
+
> "DI 라는 키워드에 집착하기 보다는, NumberGenerator 와 의존관계를 가질 class 가 누가 되어야 하는지, 역할과 책임 관점에서 생각을 해보시면 좋을 것 같습니다." — @ghojeong ([PR #107](woowacourse-racingcar/sh1mj1/107-1단계-자동차-경주.md))
|
|
275
|
+
|
|
276
|
+
조영호 "객체지향의 사실과 오해" 3요소 = **역할, 책임, 협력**. DI는 그 결과.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 13. 커밋과 PR
|
|
281
|
+
|
|
282
|
+
- 커밋 단위 = 의미 단위. "스켈레톤 코드 작성" 같은 무의미한 커밋 회피.
|
|
283
|
+
- 같은 메시지의 중복 커밋 = 책임 단위 모호의 신호.
|
|
284
|
+
- 자가 의문/결정 이유를 PR 본문에 명시. 리뷰어가 더 깊은 토론으로 응답.
|
|
285
|
+
- 페어 프로그래밍의 가치 = 토론이 PR에 보임.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 14. 출력 책임
|
|
290
|
+
|
|
291
|
+
- **toString이 도메인에 출력 형식 보유 X** — OutputView 책임 침범. (단, 안드로이드 UI 모델은 회색지대)
|
|
292
|
+
- **enum의 데이터에 UI 표현(`"-"`) 박지 말 것** — UI 변경이 도메인 변경. (MCP의 `side-effect-in-holder` 룰이 잡음)
|
|
293
|
+
- **출력 책임 일원화** — Service/도메인/Controller 어디든 출력 문구가 생기면 OutputView로 옮기기.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 부록: 리뷰어 명언 베스트
|
|
298
|
+
|
|
299
|
+
1. *"객체지향 패러다임은 사실 별로 안 중요합니다. 불편함을 스스로 인지하고, 인지한 부분을 다시 스스로 해결하는 과정이 제일 중요합니다."* — @ghojeong
|
|
300
|
+
2. *"네이밍이 모호하다는 것은 곧 해당 클래스/함수의 역할이 모호하거나 모호해질 수 있다는 신호입니다."* — @vagabond95
|
|
301
|
+
3. *"객체에게 메시지만 던져 자동차 스스로 판단해 움직일지 말지 역할을 부여하세요."* — @KwonDae
|
|
302
|
+
4. *"테스트하기 쉬운가?를 기준으로 객체를 쪼개고 합칩니다."* — @ghojeong
|
|
303
|
+
5. *"객체는 메서드 뿐만 아니라 멤버로도 구성된다는 사실을 잊지 말아주세요."* — @ghojeong
|
|
304
|
+
6. *"처음에 최대한도로 세분화하라는 조언은, 보통 합쳐진것을 쪼개는 리팩토링 보다, 쪼개진 것을 합치는 리팩토링이 더 쉽기 때문입니다."* — @ghojeong
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# PR #33 — [블랙잭 1단계] 멧돼지 미션
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@2chang5](https://github.com/2chang5)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-blackjack/pull/33
|
|
5
|
+
- **단계:** 1단계 (페어)
|
|
6
|
+
- **리뷰어:** @namjackson
|
|
7
|
+
- **라인 코멘트:** 30 (리뷰어 19 / 리뷰이 11)
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`CardBunch private constructor + vararg`** + `validateSize()`로 초기 카드 수 invariant.
|
|
12
|
+
- **`Set<Card>` 중복 차단 — `validateSize` + `addCard` 중복 검사**.
|
|
13
|
+
- **`Participant` 인터페이스 + `Player`/`Dealer` 구현** — 공통 추상화.
|
|
14
|
+
- **`Shape.korean` 분리 (`OutputView`에서 직접 매핑)** — 카드 출력 책임이 OutputView로.
|
|
15
|
+
- **`Participants` 일급 컬렉션 + `progressPlayersAddCard(getDecision, printPlayerCard)` callback** — 진행 로직 응집 (못한 점 §10 참고).
|
|
16
|
+
- **후속 반영 — `CardNumber.value: Int?` (Ace null) → 명시 처리 / Ace 보정 단순화 / Set 중복 허용 / OutputView when 단순화**.
|
|
17
|
+
|
|
18
|
+
## 못한 점 (설계 관점)
|
|
19
|
+
|
|
20
|
+
### 1. `CardNumber.value: Int?` Ace를 null로 표현 — 직관성 ↓
|
|
21
|
+
|
|
22
|
+
```kotlin
|
|
23
|
+
enum class CardNumber(val value: Int?) {
|
|
24
|
+
ACE(null),
|
|
25
|
+
TWO(2), THREE(3), ..., KING(10);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
리뷰어: "*ACE의 value를 null처리되는 구현부를 보기전에는 예상하지 못하고, 직관적이지 않은거 같아요* ㅠ,ㅠ *점수 계산할때 isAce로 체크해서 따로 관리하는게 좀더 직관적*이지 않을까요?"
|
|
30
|
+
|
|
31
|
+
학생 자가 인정: "*뭔가 null 을 새롭게 이용해보자는 목표를 가져봤는데 오히려 직관적이지 못했던것 같네요*🐗 수정해보겠습니다!!!!" — **`null = 특수 케이스 표현`은 호출자가 매번 `?:` 처리**. `value: Int = 1` + `isAce: Boolean` 가 의도 명확. *기능 시도 욕구*가 *가독성 비용*을 만든 패턴 (PR #29·#65·#135와 같은 결).
|
|
32
|
+
|
|
33
|
+
### 2. `CardBunch.getTotalScore()` — `sortedBy + reversed + checkAceValue` 복잡
|
|
34
|
+
|
|
35
|
+
```kotlin
|
|
36
|
+
fun getTotalScore(): Int {
|
|
37
|
+
var result = 0
|
|
38
|
+
val sortedCards = cards.sortedBy { it.cardNumber.value }.reversed()
|
|
39
|
+
sortedCards.forEach {
|
|
40
|
+
result += it.cardNumber.value ?: checkAceValue(result)
|
|
41
|
+
}
|
|
42
|
+
return result
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
리뷰어: "*순서에 따라 checkAceValue에 파라미터가 변경되기 때문에, 몇몇 케이스에서는 실패할 가능성도 있어요!* Ace,Ace,King. *ace를 1 계산하고, Sum의 결과값에 따라 +10 추가 하는방식*등으로 단순화할수 있을거 같아요!" — **순서 의존 알고리즘이 *Ace 두 장 케이스*에서 실패**. 정렬 후 Ace를 마지막에 두는 트릭은 *Ace 두 장이면 첫 Ace가 11, 둘째 Ace도 11로 결정 → Bust*. *Ace 합 계산 알고리즘*은 *순서 무관 단일 룰*(*Ace 있으면 +10이 21 이하면 +10*)이 정답. PR #10·#79·#114·#28과 같은 결.
|
|
47
|
+
|
|
48
|
+
### 3. `Player.consequence: lateinit var` — *상태 캐싱 + 사이드 이펙트*
|
|
49
|
+
|
|
50
|
+
```kotlin
|
|
51
|
+
class Player(val name: String, override val cardBunch: CardBunch) : Participant {
|
|
52
|
+
lateinit var consequence: Consequence
|
|
53
|
+
fun chooseWinner(score: Int) {
|
|
54
|
+
val playerScore = cardBunch.getTotalScore()
|
|
55
|
+
consequence = if (playerScore > MAX_SCORE_CONDITION) Consequence.LOSE
|
|
56
|
+
else if (playerScore > score) Consequence.WIN
|
|
57
|
+
...
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
리뷰어: "*consequence를 초기화하지 않았는데 접근하거나, cardBunch에 따라 결정되는 값으로, chooseWinner가 실행시점에 다라 다른값을 캐싱*할수 있을 것 같아요. *상태값을 불필요하게 들고 있기보다, 결과값을 반환*해주면 어떨까요?" — **`lateinit + 사이드 이펙트 setter`는 *호출 순서 invariant 누락*** + *cardBunch가 변하면 consequence가 stale*. `fun chooseWinner(score: Int): Consequence` 반환이 자연. PR #114·#29·#92와 같은 결.
|
|
63
|
+
|
|
64
|
+
### 4. `Player.chooseWinner` 다중 `if/else if` — when 활용 미흡
|
|
65
|
+
|
|
66
|
+
```kotlin
|
|
67
|
+
consequence = if (playerScore > MAX_SCORE_CONDITION) Consequence.LOSE
|
|
68
|
+
else if (playerScore > score) Consequence.WIN
|
|
69
|
+
else if (playerScore == score) Consequence.DRAW
|
|
70
|
+
else if (score > MAX_SCORE_CONDITION) Consequence.WIN
|
|
71
|
+
else Consequence.LOSE
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
리뷰어: "*if else 문외에 when을 활용해보면 어떨까요?* when, if-else는 어느경우에 쓰는게 좋을까요? 가볍게 읽어보면 좋을거같아요! https://kotlinlang.org/docs/coding-conventions.html#if-versus-when"
|
|
75
|
+
|
|
76
|
+
학생 자가 변호: "*조건이 비교연산자가 들어있는 식이라 when을 사용할수 있는 방법을 찾지못하여* if문을 사용하였습니다 ㅠㅠㅠ. [...] 단순 *else문이 안들어갔다 뿐 차이점이 전혀 없다고 생각*하여 이또한 문제가 있는 코드라고 생각합니다."
|
|
77
|
+
|
|
78
|
+
리뷰어: "*비교연산자도 when 을 활용할 수 있습니다!* ```when { playerScore > MAX_SCORE_CONDITION -> Consequence.LOSE; playerScore > dealerScore -> Consequence.WIN; ... else -> ... }```" — **Kotlin `when` 조건문 = if/else 분기의 표현력 향상**. *비교 연산자도 가능*함을 학생이 몰랐던 *문법 미숙*.
|
|
79
|
+
|
|
80
|
+
### 5. `CardDeck` 정적 메서드 + 그 외 멤버 없음
|
|
81
|
+
|
|
82
|
+
```kotlin
|
|
83
|
+
class CardDeck() {
|
|
84
|
+
companion object {
|
|
85
|
+
private val Cards: List<Card> = Shape.values().fold(listOf()) { cards, shape -> cards + makeCard(shape) }
|
|
86
|
+
private fun makeCard(shape: Shape): List<Card> = CardNumber.values().map { Card(shape, it) }
|
|
87
|
+
fun drawCard(): Card = Cards.shuffled().first()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
리뷰어: "*내부에 companion object밖에없는 클래스라면, 객체화가 의미가 없을거 같아요! object 를 사용해보면 어떨까요?*" / "*카드를 뽑게되면, 뽑은 카드는 줄어들어야하지 않을까요?*"
|
|
93
|
+
|
|
94
|
+
→ **세 가지 문제 한꺼번에**:
|
|
95
|
+
1. `class CardDeck()` no-arg + 모든 멤버 companion = *object 또는 top-level fun*이 자연.
|
|
96
|
+
2. `Cards.shuffled().first()` = *매 호출마다 셔플 + 첫 카드*. **카드 소진 X** → 동일 카드 무한 반복 가능.
|
|
97
|
+
3. 학생이 *덱 = 정적 상수* 가정으로 *상태 변화 부재*.
|
|
98
|
+
|
|
99
|
+
PR #65 (kmkim2689) Singleton + 재귀 / PR #79 (ii2001) Singleton과 같은 결.
|
|
100
|
+
|
|
101
|
+
### 6. `CardDeck` Singleton + `Participants`가 직접 호출 — 강한 의존
|
|
102
|
+
|
|
103
|
+
```kotlin
|
|
104
|
+
class Participants(names: List<String>) {
|
|
105
|
+
val dealer: Dealer = Dealer(makeCardBunch())
|
|
106
|
+
private fun makeCardBunch(): CardBunch = CardBunch(CardDeck.drawCard(), CardDeck.drawCard()) // ⚠ static call
|
|
107
|
+
private fun positiveGetCard(player: Player, ...) {
|
|
108
|
+
player.cardBunch.addCard(CardDeck.drawCard()) // ⚠ static call
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
리뷰어: "*CardDeck을 싱글턴으로 접근하게 되면, 어떤 단점이 있을까요?* *CardDeck을 싱글턴으로 사용하는 Participants에서 CardDeck에 대한 강한 의존이 생긴것 같아요!*"
|
|
114
|
+
|
|
115
|
+
학생 자가 인정: "*테스트하기도 힘들고 변화에 대응하기도 힘들것같습니다.* 이부분에서 *테스트를 아직 진행하지않아서 필요성에의해서 추상화와 분리를 시도해보려 했는데 떄가 된것 같습니다!!!*" — **Singleton = 의존성 주입 못 함 = 테스트 격리 ↓**. 학생 자가 깨달음.
|
|
116
|
+
|
|
117
|
+
### 7. `Controller`가 `player.cardBunch`에 직접 접근
|
|
118
|
+
|
|
119
|
+
```kotlin
|
|
120
|
+
private fun makeCardBunch(): CardBunch = CardBunch(cardDeck.drawCard(), cardDeck.drawCard())
|
|
121
|
+
private fun askGetCard(player: Player) { ... player.cardBunch.addCard(cardDeck.drawCard()) ... }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
리뷰어: "*player의 cardBunch에게 접근하지 말고, player에게 카드를 받을수 있는 상태인지 확인*하면 어떨까요? *좀더 객체지향적인 코드*가 될거같아요!" — *Tell-Don't-Ask*. `player.canReceiveCard()` + `player.receiveCard(card)`. PR #29·#114·#92·#65·#28과 같은 결.
|
|
125
|
+
|
|
126
|
+
### 8. `Participants` 책임 비대 — *진행자 역할까지 흡수*
|
|
127
|
+
|
|
128
|
+
```kotlin
|
|
129
|
+
class Participants(names: List<String>) {
|
|
130
|
+
val dealer: Dealer = ...
|
|
131
|
+
val players: List<Player> = ...
|
|
132
|
+
fun progressPlayersAddCard(getDecision, printPlayerCard) { ... }
|
|
133
|
+
fun progressEachPlayerAddCard(...) { ... }
|
|
134
|
+
fun progressEachTurn(...) { ... }
|
|
135
|
+
fun positiveGetCard(...) { ... }
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
리뷰어: "*Participants에 대한 책임이 많이 모여있는것으로 보여요!* 참가자를 관리하는것 외에도, *각자의 턴을 진행하고, 카드를 뽑는등 사실상 BlackJack게임에 대한 전반적인 책임 또한 있는*것 같아요! *책임을 분리하는 방법을 고민*해보아도 좋을거 같아요! 해당 *클래스들의 테스트코드를 작성해보셔도* 좋을거같아요!" — *Participants*가 *컬렉션 일급* + *진행자 역할*까지 흡수. `BlackJackGame` 같은 *진행자 별도 객체*가 자연. PR #92 `runBlackJackGame` 흐름 응집과 같은 결.
|
|
140
|
+
|
|
141
|
+
### 9. `Participants`의 *callback 인자 폭증*
|
|
142
|
+
|
|
143
|
+
```kotlin
|
|
144
|
+
fun progressPlayersAddCard(getDecision: (Player) -> Boolean, printPlayerCard: (Player) -> Unit) { ... }
|
|
145
|
+
fun progressEachTurn(player, getDecision: (Player) -> Boolean, printPlayerCard: (Player) -> Unit): Boolean { ... }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
PR #65 (kmkim2689)·#28과 같은 *callback 폭증*. *도메인 함수가 View 함수 reference를 받음* = *도메인 → View 의존*.
|
|
149
|
+
|
|
150
|
+
### 10. `Dealer.compareScore(playerScore: Int): Consequence` — *Int 비교*
|
|
151
|
+
|
|
152
|
+
```kotlin
|
|
153
|
+
class Dealer(override val cardBunch: CardBunch) : Participant {
|
|
154
|
+
fun compareScore(playerScore: Int): Consequence {
|
|
155
|
+
val dealerScore = cardBunch.getTotalScore()
|
|
156
|
+
if (playerScore > MAX_SCORE_CONDITION) return Consequence.LOSE
|
|
157
|
+
...
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`compareScore(playerScore: Int)`는 *Int를 받음*. PR #125·#10·#28과 같은 *상대를 Int로 받음 = 동일 추상에 메시지 못 보냄*. `dealer.compareScore(player: Player)` 또는 *Tell-Don't-Ask로 `player.match(dealer)`*.
|
|
163
|
+
|
|
164
|
+
### 11. `Dealer`와 `Player` 추상화 공유 부족
|
|
165
|
+
|
|
166
|
+
리뷰어: "*플레이어와 딜러가 어떤 공통점이 있고, 어떤 부분을 추상화하면 좋을지 고민*해보셔도 좋을거같아요!" — `Participant` 인터페이스에 *cardBunch*만 있고 *행위*는 거의 없음. *공통 행위 (점수 계산, 카드 받기)*를 추상화하면 *Participants가 균등 처리*.
|
|
167
|
+
|
|
168
|
+
### 12. `OutputView`에 *카드 출력 매핑 + 결과 카운트 + 승패 계산* 혼재
|
|
169
|
+
|
|
170
|
+
```kotlin
|
|
171
|
+
private fun printDealerResult(participants: Participants) {
|
|
172
|
+
val result = mutableListOf(0, 0, 0)
|
|
173
|
+
participants.players.forEach { player ->
|
|
174
|
+
result[decideDealerResult(participants.getConsequence(player))]++
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
리뷰어: "*딜러 승패를 계산하는것은 View가 아닌 도메인의 책임으로 볼수도 있을것 같아요!*" — *View 안에서 결과 집계*. *View = 표현만*. *집계는 도메인* (`Map<Player, Consequence>` + groupBy).
|
|
180
|
+
|
|
181
|
+
또 `DEALER_WIN = 0` / `DEALER_LOSE = 1` / `DRAW = 2` 같은 *인덱스 상수*로 *3원소 리스트* 다루기 = *enum + map 자연 표현* 회피.
|
|
182
|
+
|
|
183
|
+
### 13. `CardBunchTest` 케이스명 — *given/when/then 부재*
|
|
184
|
+
|
|
185
|
+
```kotlin
|
|
186
|
+
@Test fun `같은 카드를 받으면 에러가 발생한다`() { ... }
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
리뷰어: "*케이스명도 구체적으로 작성*해보면 어떨까요? 저는 *GIVEN,WHEN,THEN으로 분리*하여 사용하곤합니다. *"서로 다른 카드로, 카드 뭉치를 생성하면, 에러가 발생하지 않는다" "(Given), (When), (Then)"* 좀더 직관적이고 명확한 테스트 케이스" — *시나리오 라벨 → 시나리오 + 결과 + 조건*.
|
|
190
|
+
|
|
191
|
+
### 14. `CardBunch.constructor(vararg cards: Card)` *초기 2장 invariant* — *2장만 강제* 과잉
|
|
192
|
+
|
|
193
|
+
```kotlin
|
|
194
|
+
constructor(vararg cards: Card) : this(cards.toMutableSet()) {
|
|
195
|
+
validateSize()
|
|
196
|
+
}
|
|
197
|
+
private fun validateSize() {
|
|
198
|
+
require(_cards.size == INITIAL_CARD_SIZE) { INITIAL_SIZE_ERROR }
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
리뷰어: "*이부분도 개인적인 생각이니 참고만해주셔도 되요, player의 게임시작 후, 카드 2장을 받게되는것으로, 초기값이 2장일수 있지만, 2장의 카드로만 초기화할수 있는 부분은 불필요한거 같단 생각이 들어요*" — `CardBunch`가 *2장으로만 초기화*면 *테스트 시 다른 시나리오*(예: 1장 받은 시점)가 *생성 불가*. *초기 2장 invariant*는 *Player/Dealer 생성 흐름*에 두는 것이 자연. `CardBunch` 자체는 *0~∞장* 허용.
|
|
203
|
+
|
|
204
|
+
### 15. `DealerTest`에서 *Player 함수 검증*
|
|
205
|
+
|
|
206
|
+
```kotlin
|
|
207
|
+
class DealerTest {
|
|
208
|
+
@Test fun `플레이어가 카드를 추가로 받을지 결정한다`() { ... }
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
리뷰어: "*dealerTest에서는 dealer 테스트에 집중*해보아요! *player 함수는 PlayerTest에서 검증*해보아요!" — *테스트 대상 ≠ 테스트 시나리오*. PR #116 `HandsTest`에 Player 등장과 같은 결.
|
|
213
|
+
|
|
214
|
+
### 16. *Set 중복 차단*과 *카지노 룰* 충돌
|
|
215
|
+
|
|
216
|
+
```kotlin
|
|
217
|
+
class CardBunch ... {
|
|
218
|
+
fun addCard(card: Card) {
|
|
219
|
+
val originSize = _cards.size
|
|
220
|
+
_cards.add(card)
|
|
221
|
+
require(originSize != _cards.size) { DUPLICATE_ERROR }
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
리뷰어: "*블랙잭은 보통 여러 카드덱 세트를 혼합하여 사용하기 때문에, 중복된 카드도 허용*할수 있긴해요!" / "*카드Deck의 종류에 따라서는, 카드뭉치도 같은 카드를 받을수 있지않을까요?* 실제 카지노에서 *블랙잭은 보통 3~4개의 카드 세트를 덱*으로 ..."
|
|
227
|
+
|
|
228
|
+
학생 자가 인정: "중복을 허용하도록 변경하였습니다!!!" — **현실 블랙잭 룰 정확 이해**. *학생의 invariant*가 *도메인 룰을 좁게 해석*. *카지노 = 6~8덱 슈*. PR #112·#128 *블랙잭 룰 오해*와 같은 결.
|
|
229
|
+
|
|
230
|
+
### 17. `Dealer.compareScore`에 *블랙잭 룰 누락* — Ace + 10 두 장만 블랙잭
|
|
231
|
+
|
|
232
|
+
리뷰어: "*BlackJack승패에 대한 조건에 Ace와 10 ( = 10,K,Q,J) 단 두장으로만 21이 되면, 블랙잭이 됩니다. 블랙잭과 3장 이상의 조합으로 21의 숫자와 승패를 결정하면 블랙잭이 승리를 하게됩니다.* 이런 룰을 추가해보셔도 좋을거같아요!" — **블랙잭의 핵심 룰**: 21점 == 블랙잭이 아님. *2장으로 21 = 블랙잭*, *3장 이상으로 21 = 일반 21*. 학생 코드는 *21점이면 모두 동치*. PR #128·#10·#92와 같은 결.
|
|
233
|
+
|
|
234
|
+
### 18. `CardBunch.getTotalScore`에 *Ace 단 1회 +10* 룰 미적용
|
|
235
|
+
|
|
236
|
+
리뷰어: "*Ace가 여러장 있더라도, ACE_SCORE_GAP은 단 1회만 체크하여 추가*해주면 될거같아요! *Ace가 두장이상일 경우에도 11로 두번이상 계산된다면 22가 되기떄문이예요!*" — 학생 후속: 적용. PR #10·#79 권고와 동일.
|
|
237
|
+
|
|
238
|
+
## 리뷰어 의견 요지
|
|
239
|
+
|
|
240
|
+
- ***`CardNumber.value: Int?` Ace null = 직관성 ↓, 호출자 매번 `?:`*** — `isAce: Boolean` 분리.
|
|
241
|
+
- ***Ace 보정 순서 의존 알고리즘 = Ace 두 장 케이스 실패*** — *Ace 있으면 +10이 21 이하*면 단일 룰.
|
|
242
|
+
- ***`lateinit consequence` + 사이드 이펙트 setter < 결과 반환***.
|
|
243
|
+
- ***Kotlin when 조건문은 비교 연산자도 가능***.
|
|
244
|
+
- ***`CardDeck` companion만 있는 class = object 또는 top-level fun***.
|
|
245
|
+
- ***`Cards.shuffled().first()` = 카드 소진 X = 무한 반복***.
|
|
246
|
+
- ***Singleton → 강한 의존*** — 테스트/변화 대응 ↓.
|
|
247
|
+
- ***Controller가 `player.cardBunch.addCard`에 직접 접근*** — Tell-Don't-Ask.
|
|
248
|
+
- ***`Participants`가 진행자 역할까지 = 책임 비대*** — `BlackJackGame` 별도.
|
|
249
|
+
- ***Callback (`getDecision`, `printPlayerCard`) 폭증 = 도메인 → View 의존***.
|
|
250
|
+
- ***`compareScore(Int)` < `compareTo(player: Player)`*** — 동일 추상 메시지.
|
|
251
|
+
- ***Dealer/Player 공통 추상 = `Participant` 행위 보강***.
|
|
252
|
+
- ***View가 승패 계산 = 도메인 책임 누수***.
|
|
253
|
+
- ***테스트 케이스명 = GIVEN/WHEN/THEN 또는 시나리오 + 결과***.
|
|
254
|
+
- ***`CardBunch` *2장만 강제 invariant*는 다른 시점 생성 불가***.
|
|
255
|
+
- ***DealerTest에 Player 함수 = 테스트 대상 ≠ 시나리오***.
|
|
256
|
+
- ***블랙잭 = Ace + 10 두 장만 (3장 이상 21은 일반 21)***.
|
|
257
|
+
- ***Set 중복 차단 = 카지노 6~8덱 룰과 충돌***.
|
|
258
|
+
|
|
259
|
+
## 대표 인용
|
|
260
|
+
|
|
261
|
+
> *순서에 따라 checkAceValue에 파라미터가 변경되기 때문에, 몇몇 케이스에서는 실패할 가능성도 있어요!* Ace,Ace,King. *ace를 1 계산하고, Sum의 결과값에 따라 +10 추가 하는방식*등으로 단순화할수 있을거 같아요!
|
|
262
|
+
> — @namjackson on `CardBunch.kt`
|
|
263
|
+
|
|
264
|
+
> *consequence를 초기화하지 않았는데 접근하거나, cardBunch에 따라 결정되는 값으로, chooseWinner가 실행시점에 다라 다른값을 캐싱*할수 있을 것 같아요. *상태값을 불필요하게 들고 있기보다, 결과값을 반환*해주면 어떨까요?
|
|
265
|
+
> — @namjackson on `Player.kt`
|
|
266
|
+
|
|
267
|
+
> *CardDeck을 싱글턴으로 접근하게 되면, 어떤 단점이 있을까요?* CardDeck을 *싱글턴으로 사용하는 Participants에서 CardDeck에 대한 강한 의존*이 생긴것 같아요!
|
|
268
|
+
> — @namjackson on `Participants.kt`
|
|
269
|
+
|
|
270
|
+
> Participants에 대한 *책임이 많이 모여있는것으로 보여요!* 참가자를 관리하는것 외에도, *각자의 턴을 진행하고, 카드를 뽑는등 사실상 BlackJack게임에 대한 전반적인 책임 또한 있는*것 같아요!
|
|
271
|
+
> — @namjackson on `Participants.kt`
|
|
272
|
+
|
|
273
|
+
> *BlackJack승패에 대한 조건에 Ace와 10 ( = 10,K,Q,J) 단 두장으로만 21이 되면, 블랙잭*이 됩니다. *블랙잭과 3장 이상의 조합으로 21의 숫자와 승패를 결정하면 블랙잭이 승리*를 하게됩니다.
|
|
274
|
+
> — @namjackson on `Dealer.kt`
|
|
275
|
+
|
|
276
|
+
## 얻은 교훈
|
|
277
|
+
|
|
278
|
+
- ***`null = 특수 케이스 표현`은 호출자가 매번 `?:` 처리*** — `isAce: Boolean` + 정수값 분리가 의도 명확. *기능 시도 욕구가 가독성 비용*을 만든 패턴 (PR #29·#65·#135 결).
|
|
279
|
+
- ***Ace 보정 = 순서 무관 단일 룰*** — *Ace 1 시작 + 합 ≤ 11이면 +10*. PR #10·#79·#114·#28 모두 같은 권고.
|
|
280
|
+
- ***`lateinit + 사이드 이펙트 setter` = 호출 순서 invariant 누락 + stale*** — `fun chooseWinner(score: Int): Consequence` 반환.
|
|
281
|
+
- ***Kotlin when은 비교 연산자도 가능*** — *문법 미숙*이 *if/else if 폭증*. https://kotlinlang.org/docs/coding-conventions.html#if-versus-when
|
|
282
|
+
- ***companion만 있는 class = object*** — *no-arg + 정적 멤버*면 object/top-level.
|
|
283
|
+
- ***`Cards.shuffled().first()` = 카드 소진 부재 = 무한 반복*** — *덱 = mutable 상태 + 셔플 한 번 + pop*.
|
|
284
|
+
- ***Singleton 강한 의존 = 테스트 격리 X + 변화 대응 X*** — 학생 자가 인정. *주입형 인스턴스*가 자연.
|
|
285
|
+
- ***`player.cardBunch.addCard(card)` 직접 접근 < `player.receiveCard(card)`*** — Tell-Don't-Ask. *공통 안티패턴*.
|
|
286
|
+
- ***Participants 일급 컬렉션 ≠ 진행자*** — `BlackJackGame` 별도 객체로 *진행 책임 분리*. PR #92와 같은 결.
|
|
287
|
+
- ***도메인 함수가 View callback을 받으면 도메인 → View 의존*** — *State 변경 또는 결과 반환*으로 *View 호출*은 호출자 책임.
|
|
288
|
+
- ***`compareScore(Int)` = 동일 추상 메시지 못 보냄*** — `match(player: Player)` Tell-Don't-Ask.
|
|
289
|
+
- ***View가 승패 카운트 = 도메인 책임 누수*** — *집계는 도메인* (`Map<Player, Consequence>` + groupBy).
|
|
290
|
+
- ***`CardBunch` 2장 invariant는 다른 시점 생성 불가*** — *Player 생성 흐름*에 두기.
|
|
291
|
+
- ***DealerTest에 Player 함수 = 테스트 대상 ≠ 시나리오*** — *대상의 책임만 테스트*. PR #116과 같은 결.
|
|
292
|
+
- ***블랙잭 룰 = Ace + 10 두 장만 블랙잭, 3장 이상 21 = 일반 21*** — *현실 블랙잭 룰 정확 이해*. **반복 패턴: 학생들의 블랙잭 룰 부정확 이해**. PR #10·#92·#128·#116·#10도 같은 결.
|
|
293
|
+
- ***Set 중복 차단 = 카지노 6~8덱 룰과 충돌*** — *학생의 invariant가 도메인 룰을 좁게 해석*. *현실 도메인 조사*가 *과잉 invariant 방지*.
|