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,339 @@
|
|
|
1
|
+
# 우아한테크코스 kotlin-racingcar PR 리뷰 분석 — 총정리
|
|
2
|
+
|
|
3
|
+
133개의 closed PR (라인 코멘트 ≥ 5개), 77명의 reviewee를 분석해 도출한 OOP 설계 교훈 모음.
|
|
4
|
+
|
|
5
|
+
> **분석 범위:** 책임/응집/결합/캡슐화/Tell-Don't-Ask/테스터빌리티/도메인 모델링/일급 컬렉션/원시 강박/의존 방향/명명 설계.
|
|
6
|
+
> **제외:** Kotlin 관용구 (scope function, smart cast, null 처리 idiom, `val/var`, data class *문법* 자체, init 블록 형태, collection API 선택).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 자주 하는 설계 실수 TOP 10
|
|
11
|
+
|
|
12
|
+
리뷰 빈도와 안티패턴의 심각도로 순위.
|
|
13
|
+
|
|
14
|
+
### 1. **Controller가 god-object 되기** — Tell Don't Ask 위반
|
|
15
|
+
|
|
16
|
+
**증상:** RacingController가 InputView/OutputView/Validator/RacingGame 모두를 인스턴스로 보유, `run()` 메서드 하나가 입력 검증, 게임 진행, 우승자 판단, 출력까지 다 함.
|
|
17
|
+
|
|
18
|
+
**예시 PR:** [#108](Hogu59/108-1단계-자동차-경주.md), [#92](kmkim2689/92-1단계-자동차-경주.md), [#144](ijh1298/144-2단계-자동차-경주.md), [#41](whk06061/41-2단계-자동차-경주.md), [#40](EmilyCh0/40-1단계-자동차-경주.md), [#125](Hogu59/125-2단계-자동차-경주.md)
|
|
19
|
+
|
|
20
|
+
**해법 패턴:**
|
|
21
|
+
- Controller는 "명령 + view-domain 연결"만
|
|
22
|
+
- 도메인 주체 (RacingGame)가 상태 관리 + 라운드 진행 + 우승자 판단
|
|
23
|
+
- "체스 비유" — 유저(Controller) → 체스판(RacingGame) → 말(Car)
|
|
24
|
+
|
|
25
|
+
### 2. **검증 위치 혼란** — UI/Domain/Controller 세 갈래 책임 분리 실패
|
|
26
|
+
|
|
27
|
+
**증상:** Validator가 InputView, Controller, Domain init 어디에 가야 할지 모름. 학생마다 다른 답.
|
|
28
|
+
|
|
29
|
+
**예시 PR:** [#85](CFalws/85-2단계-자동차-경주.md), [#108](Hogu59/108-1단계-자동차-경주.md), [#135](moondev03/135-1단계-자동차-경주.md), [#161](moondev03/161-2단계-자동차-경주.md), [#142](jiyuneel/142-2단계-자동차-경주.md), [#34](krrong/34-1단계-자동차-경주.md), [#44](inseonyun/44-1단계-자동차-경주.md), [#76](inseonyun/76-2단계-자동차-경주.md)
|
|
30
|
+
|
|
31
|
+
**해법 패턴 (3분류):**
|
|
32
|
+
- **UI 형식 검증** (빈 문자열, 숫자 아님, 형식) → View
|
|
33
|
+
- **사용자 입력 정책** (재입력 흐름) → Controller
|
|
34
|
+
- **도메인 무결성 invariant** (이름 길이, 자동차 두 대 이상, 중복) → Domain init / 일급 컬렉션
|
|
35
|
+
|
|
36
|
+
이 분류는 학생들이 PR 두세 라운드에 걸쳐 자가 학습으로 도달.
|
|
37
|
+
|
|
38
|
+
### 3. **`Car.position`이 var (외부 변경 가능)** — 캡슐화 누수
|
|
39
|
+
|
|
40
|
+
**증상:** `class Car(var name, var position)` 또는 `val position: Int` 그대로 public.
|
|
41
|
+
|
|
42
|
+
**예시 PR:** 거의 모든 1단계 PR — [#46](Choisehyeon/46-1단계-자동차-경주.md), [#84](Songusika/84-2단계-자동차-경주.md), [#91](s6m1n/91-1단계-자동차-경주.md), [#145](etama123/145-2단계-자동차-경주.md), [#82](drunkenhw/82-2단계-자동차-경주.md), [#92](kmkim2689/92-1단계-자동차-경주.md), 등 다수.
|
|
43
|
+
|
|
44
|
+
**해법 패턴:**
|
|
45
|
+
- `var position: Int = 0; private set` (가장 흔한 권장)
|
|
46
|
+
- backing property `private var _position` + `val position get() = _position` (컬렉션 경우)
|
|
47
|
+
- Tell Don't Ask: 외부에서 position을 읽어 비교하지 말고 `car.isAtMaxPosition(maxPos)` 메시지 던지기
|
|
48
|
+
|
|
49
|
+
### 4. **모호한 클래스 이름** = god-object 안티패턴의 시그널
|
|
50
|
+
|
|
51
|
+
**증상:** `Validator`, `Manager`, `Helper`, `Service`, `Util`, `Common`, `Const`.
|
|
52
|
+
|
|
53
|
+
**예시 PR:** [#41](whk06061/41-2단계-자동차-경주.md), [#52](sujin9/52-2단계-자동차-경주.md), [#103](dpcks0509/103-1단계-자동차-경주.md), [#96](Yunseok-Nam/96-1단계-자동차-경주.md), [#88](JoYehyun99/88-1단계-자동차-경주.md), [#50](hyemdooly/50-1단계-자동차-경주.md), [#68](hyemdooly/68-1단계-자동차-경주.md)
|
|
54
|
+
|
|
55
|
+
**리뷰어 명언:** *"네이밍이 모호하다는 것은 곧 해당 클래스/함수의 역할이 모호하거나 모호해질 수 있다는 신호이기 때문입니다"* — @vagabond95
|
|
56
|
+
|
|
57
|
+
**해법 패턴:** 무엇을 *Validate/Manage/Util*하는지 이름에 명시. `InputValidator`, `RacingGame`, `OutputFormatter` 등.
|
|
58
|
+
|
|
59
|
+
### 5. **상수의 god-folder** — `Const.kt` / `common/` 한 파일에 모든 상수
|
|
60
|
+
|
|
61
|
+
**증상:** 한 클래스에서만 쓰는 상수까지 공용 파일에 박혀 있음. 외부에서 접근 가능.
|
|
62
|
+
|
|
63
|
+
**예시 PR:** [#139](yrsel/139-1단계-자동차-경주.md), [#103](dpcks0509/103-1단계-자동차-경주.md), [#92](kmkim2689/92-1단계-자동차-경주.md), [#52](sujin9/52-2단계-자동차-경주.md), [#31](rhthrhrl0/31-1단계-자동차-경주.md), [#83](yujamint/83-2단계-자동차-경주.md), [#154](donghyun81/154-2단계-자동차-경주.md)
|
|
64
|
+
|
|
65
|
+
**리뷰어 명언:** *"만약 프로젝트에서 사용하는 상수가 1000개 이상이 된다면 어떤 일이 발생할까요?"* — @KwonDae
|
|
66
|
+
|
|
67
|
+
**해법 패턴 (재사용 범위로 결정):**
|
|
68
|
+
- 한 함수만 사용 → 리터럴 OK
|
|
69
|
+
- 한 클래스 내부만 사용 → 그 클래스의 `companion object` + `private`
|
|
70
|
+
- 여러 클래스 사용 → top-level `const val` + 의미 있는 파일명
|
|
71
|
+
|
|
72
|
+
### 6. **랜덤이 도메인에 침투** — 테스트 불가
|
|
73
|
+
|
|
74
|
+
**증상:** `Car.move()`나 `Cars.move()` 안에서 `Random.nextInt(0, 9)` 호출. 결정적 테스트 불가.
|
|
75
|
+
|
|
76
|
+
**예시 PR:** [#108](Hogu59/108-1단계-자동차-경주.md), [#125](Hogu59/125-2단계-자동차-경주.md), [#127](Junyoung-WON/127-2단계-자동차-경주.md), [#117](jinuemong/117-2단계-자동차-경주.md), [#112](dpcks0509/112-2단계-자동차-경주.md), [#103](dpcks0509/103-1단계-자동차-경주.md), [#92](kmkim2689/92-1단계-자동차-경주.md)
|
|
77
|
+
|
|
78
|
+
**해법 패턴 (전략 패턴):**
|
|
79
|
+
1. `interface NumberGenerator { fun generate(): Int }` 또는 `fun interface MoveStrategy { fun isMovable(): Boolean }`
|
|
80
|
+
2. 도메인은 인터페이스만 의존
|
|
81
|
+
3. 프로덕션은 `RandomNumberGenerator` 구현체 주입
|
|
82
|
+
4. 테스트는 `FakeGenerator(values: List<Int>)` 같은 결정적 fake 주입
|
|
83
|
+
|
|
84
|
+
이 패턴은 거의 모든 2단계 PR의 핵심 학습 포인트.
|
|
85
|
+
|
|
86
|
+
### 7. **데이터 클래스 + var** 또는 **data class에 비즈니스 로직**
|
|
87
|
+
|
|
88
|
+
**증상:** `data class Car(val name: String, var position: Int = 0) { fun move() ... }` — equals/hashCode가 주생성자만 보는데 var면 동치성 깨질 위험.
|
|
89
|
+
|
|
90
|
+
**예시 PR:** [#108](Hogu59/108-1단계-자동차-경주.md), [#31](rhthrhrl0/31-1단계-자동차-경주.md), [#175](doabletuple/175-2단계-자동차-경주.md), [#59](boogi-woogi/59-2단계-자동차-경주.md), [#83](yujamint/83-2단계-자동차-경주.md), [#82](drunkenhw/82-2단계-자동차-경주.md)
|
|
91
|
+
|
|
92
|
+
**해법 패턴:**
|
|
93
|
+
- data class = *데이터 운반 + 동치성*만. 행위가 있으면 일반 class.
|
|
94
|
+
- 단일 값 wrapper = `@JvmInline value class` (Kotlin 1.5+, 인라인)
|
|
95
|
+
- VO(값 객체)는 모든 식별 속성을 주생성자에 (data class가 본업)
|
|
96
|
+
|
|
97
|
+
### 8. **테스트 함수명의 추상화** — 시나리오 불분명
|
|
98
|
+
|
|
99
|
+
**증상:** "정상 동작한다", "예외가 발생한다", "올바르지 않은 게임", "유효성 검사".
|
|
100
|
+
|
|
101
|
+
**예시 PR:** [#40](EmilyCh0/40-1단계-자동차-경주.md), [#57](EmilyCh0/57-2단계-자동차-경주.md), [#103](dpcks0509/103-1단계-자동차-경주.md), [#145](etama123/145-2단계-자동차-경주.md), [#54](briandr97/54-1단계-자동차-경주.md), [#46](Choisehyeon/46-1단계-자동차-경주.md), [#88](JoYehyun99/88-1단계-자동차-경주.md)
|
|
102
|
+
|
|
103
|
+
**해법 패턴:**
|
|
104
|
+
- `~하면 ~한다` 형식: `randomNumber가 4 이상이면, 자동차가 움직인다`
|
|
105
|
+
- 시나리오 + 결과 함께
|
|
106
|
+
- 요구사항을 그대로 테스트 이름으로
|
|
107
|
+
- given/when/then 주석 (body 안)
|
|
108
|
+
|
|
109
|
+
### 9. **`it` 연속 사용 + 익명 람다 남용**
|
|
110
|
+
|
|
111
|
+
**증상:** `cars.filter { it... }.map { it... }.find { it... }`에서 it이 무엇을 가리키는지 매번 다름.
|
|
112
|
+
|
|
113
|
+
**예시 PR:** [#41](whk06061/41-2단계-자동차-경주.md), [#40](EmilyCh0/40-1단계-자동차-경주.md), [#52](sujin9/52-2단계-자동차-경주.md), [#82](drunkenhw/82-2단계-자동차-경주.md)
|
|
114
|
+
|
|
115
|
+
**해법 패턴:**
|
|
116
|
+
- 변수명 명시: `cars.filter { car -> ... }` (`it` 대신 `car`)
|
|
117
|
+
- 익명 람다 대신 별도 클래스 — [#115](sh1mj1/115-2단계-자동차-경주.md)에서 `MoveStrategyUsingNumber`를 익명 함수 대신 *별도 클래스*로 둔 게 칭찬받음
|
|
118
|
+
|
|
119
|
+
### 10. **toString이 도메인에 출력 형식 보유** — OutputView 책임 침범
|
|
120
|
+
|
|
121
|
+
**증상:** `Car.toString()`이 `"name : ---"` 같은 출력 형식 반환. 출력 변경 시 도메인 변경.
|
|
122
|
+
|
|
123
|
+
**예시 PR:** [#83](yujamint/83-2단계-자동차-경주.md), [#52](sujin9/52-2단계-자동차-경주.md), [#88](JoYehyun99/88-1단계-자동차-경주.md), [#111](JoYehyun99/111-2단계-자동차-경주.md), [#78](s9hn/78-2단계-자동차-경주.md), [#76](inseonyun/76-2단계-자동차-경주.md)
|
|
124
|
+
|
|
125
|
+
**해법 패턴:**
|
|
126
|
+
- 백엔드 컨벤션 = OutputView가 표현 담당, 도메인은 원시 값만 노출
|
|
127
|
+
- 안드로이드는 toString을 UI에서 쓰는 경우 OK (회색지대)
|
|
128
|
+
- **enum의 데이터에 UI 표현 (`"-"`)을 넣지 말 것** — UI 변경이 도메인 변경 ([#78](s9hn/78-2단계-자동차-경주.md))
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 리뷰어들이 반복적으로 하는 말
|
|
133
|
+
|
|
134
|
+
### 🎯 "이 클래스의 책임을 한 문장으로 적어보세요"
|
|
135
|
+
|
|
136
|
+
SRP 자가 검사법. 그 문장이 모호하거나 길면 SRP 위반.
|
|
137
|
+
|
|
138
|
+
> 단일 책임 원칙이 어긋나 있는지 확인하는 좋은 방법 중 하나는, 이 클래스의 역할과 책임이 무엇인지 한 문장으로 적어보는 것입니다.
|
|
139
|
+
> — @ghojeong on [#91](s6m1n/91-1단계-자동차-경주.md)
|
|
140
|
+
|
|
141
|
+
**출현 PR:** [#91](s6m1n/91-1단계-자동차-경주.md), [#88](JoYehyun99/88-1단계-자동차-경주.md), [#111](JoYehyun99/111-2단계-자동차-경주.md), [#107](sh1mj1/107-1단계-자동차-경주.md), [#115](sh1mj1/115-2단계-자동차-경주.md)
|
|
142
|
+
|
|
143
|
+
### 🎯 "휴가 가도 동료가 일할 수 있는 코드를 짜주세요"
|
|
144
|
+
|
|
145
|
+
함수명 + 시그니처만 보고 동료가 같은 일을 할 수 있는가 = SRP 검사법.
|
|
146
|
+
|
|
147
|
+
> 조직에서 함께 일할 때 중요한 점은, 내가 마음 편하게 휴가를 가더라도, 동료에게 자신의 일을 믿고 맡길 수 있어야 한다는 점입니다... 업계에 떠도는 맨날 야근하는 개발 조직 괴담이 역할과 책임이 명확하지 않은 함수, 클래스, 혹은 모듈로 인해서 생긴다고 생각해주세요.
|
|
148
|
+
> — @ghojeong on [#109](hxeyexn/109-1단계-자동차-경주.md)
|
|
149
|
+
|
|
150
|
+
### 🎯 "객체에 메시지를 던져라 (Tell Don't Ask)"
|
|
151
|
+
|
|
152
|
+
> 클래스를 잘 분리해주신 만큼, 각 클래스(객체)에게 메시지를 던져보는건(입력을 받아!) 어떨까요?
|
|
153
|
+
> — @KwonDae on [#135](moondev03/135-1단계-자동차-경주.md)
|
|
154
|
+
|
|
155
|
+
> 객체가 자동차를 받아, 자동차에게 단지 메세지만 던져 자동차 스스로 판단해 움직일지 말지 역할을 부여하는것 또한 좋은 방법입니다. 이런식으로 역할을 분리해서 depth를 줄일 수 있습니다.
|
|
156
|
+
> — @KwonDae on [#108](Hogu59/108-1단계-자동차-경주.md)
|
|
157
|
+
|
|
158
|
+
**출현 PR:** [#108](Hogu59/108-1단계-자동차-경주.md), [#125](Hogu59/125-2단계-자동차-경주.md), [#127](Junyoung-WON/127-2단계-자동차-경주.md), [#135](moondev03/135-1단계-자동차-경주.md), [#161](moondev03/161-2단계-자동차-경주.md)
|
|
159
|
+
|
|
160
|
+
### 🎯 "테스트하기 쉬운가? = 객체 분리의 기준"
|
|
161
|
+
|
|
162
|
+
> 제가 객체를 쪼개고 합치는 기준을 오직 "테스트 하기 쉬운가?" 로 한다고 말씀드렸는데...
|
|
163
|
+
> — @ghojeong on [#128](hxeyexn/128-2단계-자동차-경주.md)
|
|
164
|
+
|
|
165
|
+
분리해도 테스트가 더 명확해지지 않으면 분리할 이유 없음. *분리의 정당화는 테스트 개선이 와야 함*.
|
|
166
|
+
|
|
167
|
+
### 🎯 "한 문장으로 답할 수 없는 함수 이름 = SRP 위반"
|
|
168
|
+
|
|
169
|
+
> 그런데, 이 함수에는 동사가 2개가 존재합니다. (input, try) 함수에는 하나의 동사만 포함시켜보면 어떨까요?
|
|
170
|
+
> — @BeokBeok on [#68](hyemdooly/68-1단계-자동차-경주.md)
|
|
171
|
+
|
|
172
|
+
> end 라는 의미가 조금 모호한 것 같아요... 해당 함수의 역할이 모호하고 비대해질 수 있는 신호를 가지고 있다고 생각해요.
|
|
173
|
+
> — @vagabond95 on [#112](dpcks0509/112-2단계-자동차-경주.md)
|
|
174
|
+
|
|
175
|
+
### 🎯 "예외는 정말 예외일 때만"
|
|
176
|
+
|
|
177
|
+
Effective Kotlin Item 7 인용 — 리뷰어 5명 이상이 같은 글 인용.
|
|
178
|
+
|
|
179
|
+
> - 논리적인 오류일 때만 예외를 던지세요.
|
|
180
|
+
> - 논리 오류가 아니면 예외를 던지지 말고 null을 반환하세요.
|
|
181
|
+
> - 실패하는 경우가 복잡해서 null로 처리할 수 없으면 sealed class를 반환하세요.
|
|
182
|
+
> - 일반적인 코틀린 코드에서 try-catch를 사용하지 마세요.
|
|
183
|
+
> — @s9hn on [#83](yujamint/83-2단계-자동차-경주.md), @galcyurio on [#34](krrong/34-1단계-자동차-경주.md), [#46](Choisehyeon/46-1단계-자동차-경주.md), @sujin9 on [#82](drunkenhw/82-2단계-자동차-경주.md)
|
|
184
|
+
|
|
185
|
+
### 🎯 "단일 정답 없음, 본인 기준을 가지세요"
|
|
186
|
+
|
|
187
|
+
> 다만, 도메인 로직인지 아닌지에 대한 판단은 개발자마다 다를 수 있어서 저 또한 팀원들이랑 코드리뷰를 하면서 기준이 바뀌기도 합니다. 이 부분은 저도 명확하게 답변을 드리기가 쉽지 않네요
|
|
188
|
+
> — @galcyurio on [#34](krrong/34-1단계-자동차-경주.md)
|
|
189
|
+
|
|
190
|
+
> 계속 미션을 진행하면서 크림만의 기준을 잡고 그 기준이 객체지향에서 문제가 없는지는 리뷰어들이 계속해서 의견을 남겨주실테니 항상 본인의 의견을 이야기 해보는 습관을 들이신다면 너무 좋을거 같네요!
|
|
191
|
+
> — @lee-ji-hoon on [#144](ijh1298/144-2단계-자동차-경주.md)
|
|
192
|
+
|
|
193
|
+
### 🎯 "리뷰어가 *질문으로* 자가 학습 유도"
|
|
194
|
+
|
|
195
|
+
대부분의 리뷰어가 직접 답을 주지 않고 질문으로 학생이 스스로 답하게 함:
|
|
196
|
+
|
|
197
|
+
- "이건 어디서 검증해야 할까요?"
|
|
198
|
+
- "object/class 선택 기준은?"
|
|
199
|
+
- "이 함수가 두 가지 일을 하는 것 같은데, 한 가지로 하려면?"
|
|
200
|
+
- "이 클래스의 책임은 무엇인가요?"
|
|
201
|
+
|
|
202
|
+
가장 칭찬받은 PR [#115](sh1mj1/115-2단계-자동차-경주.md) 리뷰어 평:
|
|
203
|
+
|
|
204
|
+
> 객체지향 패러다임은 사실 별로 안 중요합니다. 심지님이 불편함을 느낀 부분을 스스로 인지하고, 인지한 부분을 다시 스스로 해결하는 과정이 제일 중요합니다.
|
|
205
|
+
> — @ghojeong
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 조영호님 강의 토픽과의 매핑
|
|
210
|
+
|
|
211
|
+
### `god-object` (자기 책임 외 모든 일을 떠안는 객체)
|
|
212
|
+
|
|
213
|
+
- **Controller가 god-object**: [#108](Hogu59/108-1단계-자동차-경주.md), [#92](kmkim2689/92-1단계-자동차-경주.md), [#144](ijh1298/144-2단계-자동차-경주.md), [#41](whk06061/41-2단계-자동차-경주.md)
|
|
214
|
+
- **`Cars`(일급 컬렉션)가 god-object**: 우승자 판단 + 컬렉션 관리 — [#50](hyemdooly/50-1단계-자동차-경주.md), [#46](Choisehyeon/46-1단계-자동차-경주.md)
|
|
215
|
+
- **모호한 이름 = god-object 신호**: [#41](whk06061/41-2단계-자동차-경주.md), [#52](sujin9/52-2단계-자동차-경주.md), [#103](dpcks0509/103-1단계-자동차-경주.md)
|
|
216
|
+
|
|
217
|
+
### `feature-envy` (다른 객체 정보를 묻고 비교)
|
|
218
|
+
|
|
219
|
+
- `name`, `position` getter 호출 후 외부에서 로직 — [#46](Choisehyeon/46-1단계-자동차-경주.md), [#52](sujin9/52-2단계-자동차-경주.md)
|
|
220
|
+
- Controller가 Car를 받고 외부에서 `if (car.position > maxPos)` — 거의 모든 1단계 PR
|
|
221
|
+
|
|
222
|
+
### `non-newable` (`new`로 만들지 않을 객체 — 항상 한 개)
|
|
223
|
+
|
|
224
|
+
- Controller, View 같은 객체는 보통 인스턴스 1개 → object 후보
|
|
225
|
+
- [#91](s6m1n/91-1단계-자동차-경주.md): "object 사용 기준 = 상태 무 + static 메서드/상수만"
|
|
226
|
+
- [#127](Junyoung-WON/127-2단계-자동차-경주.md), [#107](sh1mj1/107-1단계-자동차-경주.md), [#90](Junyoung-WON/90-1단계-자동차-경주.md): object vs class 의문
|
|
227
|
+
|
|
228
|
+
### `mocking-pressure` (테스트 작성 어려움 = 설계 문제 신호)
|
|
229
|
+
|
|
230
|
+
- Random 의존 → 테스트 불가 → 인터페이스 + Fake 주입 — [#108](Hogu59/108-1단계-자동차-경주.md), [#127](Junyoung-WON/127-2단계-자동차-경주.md), [#103](dpcks0509/103-1단계-자동차-경주.md), [#125](Hogu59/125-2단계-자동차-경주.md), [#92](kmkim2689/92-1단계-자동차-경주.md), [#82](drunkenhw/82-2단계-자동차-경주.md)
|
|
231
|
+
- Controller 단위 테스트의 함정 — [#40](EmilyCh0/40-1단계-자동차-경주.md): "Controller는 IO 결합 → 단위 테스트 부적합, 통합 테스트가 맞음"
|
|
232
|
+
|
|
233
|
+
### `Tell-Don't-Ask`
|
|
234
|
+
|
|
235
|
+
- 메서드 호출로 메시지 던지기 vs property로 묻기 — [#46](Choisehyeon/46-1단계-자동차-경주.md), [#92](kmkim2689/92-1단계-자동차-경주.md), [#108](Hogu59/108-1단계-자동차-경주.md), [#135](moondev03/135-1단계-자동차-경주.md), [#127](Junyoung-WON/127-2단계-자동차-경주.md)
|
|
236
|
+
- `cars.filter { it.position == maxPos }` → `cars.findWinners()` 메시지 형태로
|
|
237
|
+
|
|
238
|
+
### `책임-역할-협력` (조영호 "객체지향의 사실과 오해" 3요소)
|
|
239
|
+
|
|
240
|
+
- [#107](sh1mj1/107-1단계-자동차-경주.md): "DI 키워드보다 *역할과 책임* 관점에서. 객체설계 3요소 = 역할, 책임, 협력."
|
|
241
|
+
- [#125](Hogu59/125-2단계-자동차-경주.md): "체스 비유 — 유저(Controller) → 체스판(RacingGame) → 말(Car). 책임의 3층."
|
|
242
|
+
- [#54](briandr97/54-1단계-자동차-경주.md): "차량이 driver를 가짐 — 현실 모델링"
|
|
243
|
+
|
|
244
|
+
### `의존 방향` (Domain ← Infra/UI)
|
|
245
|
+
|
|
246
|
+
- Validator가 OutputView 의존 — [#76](inseonyun/76-2단계-자동차-경주.md), [#68](hyemdooly/68-1단계-자동차-경주.md)
|
|
247
|
+
- 인터페이스는 domain, 구현체는 data/infra — [#117](jinuemong/117-2단계-자동차-경주.md): "RandomNumberMaker 인터페이스가 domain에, Provider가 data에"
|
|
248
|
+
|
|
249
|
+
### `일급 컬렉션`
|
|
250
|
+
|
|
251
|
+
- `Cars` 일급 컬렉션 표준 패턴 — [#46](Choisehyeon/46-1단계-자동차-경주.md): `List<Car>` 생성자 + `get()` override + companion object 팩토리
|
|
252
|
+
- 컬렉션 자체에 도메인 규칙 (중복, 크기) — [#161](moondev03/161-2단계-자동차-경주.md) 예고편으로 등장
|
|
253
|
+
|
|
254
|
+
### `원시 강박 (Primitive Obsession)`
|
|
255
|
+
|
|
256
|
+
- `String` 이름을 그대로 → `Name` 값 객체 — 거의 모든 2단계 PR
|
|
257
|
+
- `Int` 위치를 그대로 → `Position` value class — [#82](drunkenhw/82-2단계-자동차-경주.md), [#83](yujamint/83-2단계-자동차-경주.md), [#24](injoon2019/24-2단계-자동차-경주.md), [#23](awesomeo184/23-2단계-자동차-경주.md)
|
|
258
|
+
- `Int` 시도 횟수 → `TryCount` — [#107](sh1mj1/107-1단계-자동차-경주.md), [#115](sh1mj1/115-2단계-자동차-경주.md)
|
|
259
|
+
|
|
260
|
+
### `명명 설계`
|
|
261
|
+
|
|
262
|
+
- 함수명은 동사형 (`generate()` not `generateNumber()`) — [#46](Choisehyeon/46-1단계-자동차-경주.md), [#102](ii2001/102-1단계-자동차-경주.md), [#110](jaeyeongjo/110-2단계-자동차-경주.md)
|
|
263
|
+
- 클래스명은 도메인 의미 (`STANDARD_NUMBER` vs `MOVEMENT_THRESHOLD`) — [#145](etama123/145-2단계-자동차-경주.md)
|
|
264
|
+
- *오해의 비용*을 최소화 (`InputExceptions`가 Exception처럼 보임) — [#111](JoYehyun99/111-2단계-자동차-경주.md), [#44](inseonyun/44-1단계-자동차-경주.md)
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 단계별 학습 곡선
|
|
269
|
+
|
|
270
|
+
### 1단계 흔한 실수 (1단계 PR 다수에 공통)
|
|
271
|
+
|
|
272
|
+
- `Const.kt` 한 파일에 모든 상수
|
|
273
|
+
- `Validator` / `Util` 같은 모호한 이름
|
|
274
|
+
- Controller가 InputView/OutputView 인스턴스 직접 생성
|
|
275
|
+
- Car.position이 var로 외부 노출
|
|
276
|
+
- 검증을 어디서 할지 결정 못함 (Controller에 그냥 둠)
|
|
277
|
+
- `MutableList`를 외부에 노출
|
|
278
|
+
- 테스트 함수명이 "정상 동작한다" 류
|
|
279
|
+
- 메시지 상수에 매직넘버 박힘 ("1~5글자")
|
|
280
|
+
|
|
281
|
+
### 2단계에서 부각되는 이슈
|
|
282
|
+
|
|
283
|
+
- **전략 패턴** 도입 (`NumberGenerator` 인터페이스) — Random 의존 분리
|
|
284
|
+
- **일급 컬렉션** (`Cars`) 본격 시도
|
|
285
|
+
- **VO** (`Name`, `Position`, `TryCount`) — 원시 강박 탈출
|
|
286
|
+
- **검증 위치 재조정** — Controller에서 도메인으로 이동
|
|
287
|
+
- **메서드 vs 클래스 분리 깊이** — "어디까지 분리할까"의 trade-off
|
|
288
|
+
- **테스트 가능성 의식** — Random/IO 분리 시도
|
|
289
|
+
- **`it` → 명시적 변수명** — 가독성
|
|
290
|
+
|
|
291
|
+
### 1단계 → 2단계 학습 곡선의 시그니처
|
|
292
|
+
|
|
293
|
+
가장 잘된 PR ([#115](sh1mj1/115-2단계-자동차-경주.md), [#161](moondev03/161-2단계-자동차-경주.md), [#114](Yunseok-Nam/114-2단계-자동차-경주.md))은:
|
|
294
|
+
|
|
295
|
+
1. 1단계 피드백을 즉시 흡수 (작은 위생부터 큰 구조까지)
|
|
296
|
+
2. 흡수한 피드백을 *자가 검토*로 다시 평가 (맹목 흡수 아님)
|
|
297
|
+
3. 자신의 결정 *이유*를 PR 본문에 명시
|
|
298
|
+
4. 더 깊은 자가 의문을 던짐 ("Controller가 너무 많은 일?")
|
|
299
|
+
|
|
300
|
+
평범한 학습 곡선 PR은:
|
|
301
|
+
- 1단계 피드백 일부만 반영
|
|
302
|
+
- 같은 안티패턴 (var position, Validator 이름, 매직넘버) 잔존
|
|
303
|
+
- "감사합니다" 답변만 + 자가 회고 부재
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 부록: 가장 강력한 리뷰어 명언 10선
|
|
308
|
+
|
|
309
|
+
1. *"객체지향 패러다임은 사실 별로 안 중요합니다. 불편함을 스스로 인지하고, 인지한 부분을 다시 스스로 해결하는 과정이 제일 중요합니다."* — @ghojeong on [#115](sh1mj1/115-2단계-자동차-경주.md)
|
|
310
|
+
|
|
311
|
+
2. *"휴가를 가도 동료가 일할 수 있는 코드를 짜주세요... 업계에 떠도는 맨날 야근하는 개발 조직 괴담이 역할과 책임이 명확하지 않은 함수, 클래스, 혹은 모듈로 인해서 생긴다고 생각해주세요."* — @ghojeong on [#109](hxeyexn/109-1단계-자동차-경주.md)
|
|
312
|
+
|
|
313
|
+
3. *"네이밍이 모호하다는 것은 곧 해당 클래스/함수의 역할이 모호하거나 모호해질 수 있다는 신호이기 때문입니다."* — @vagabond95 on [#103](dpcks0509/103-1단계-자동차-경주.md)
|
|
314
|
+
|
|
315
|
+
4. *"객체에게 메시지만 던져 자동차 스스로 판단해 움직일지 말지 역할을 부여하는것 또한 좋은 방법입니다. 이런식으로 역할을 분리해서 depth를 줄일 수 있습니다."* — @KwonDae on [#108](Hogu59/108-1단계-자동차-경주.md)
|
|
316
|
+
|
|
317
|
+
5. *"테스트하기 쉬운가?를 기준으로 객체를 쪼개고 합칩니다."* — @ghojeong on [#128](hxeyexn/128-2단계-자동차-경주.md)
|
|
318
|
+
|
|
319
|
+
6. *"클래스명을 보니 Exception을 custom한 것으로 보이지만, 실제로는 Exception 타입이 아니네요. 이 클래스가 하는 책임에 대해서 다시 한번 고민해보면 어떨까요?"* — @BeokBeok on [#44](inseonyun/44-1단계-자동차-경주.md)
|
|
320
|
+
|
|
321
|
+
7. *"DI 라는 키워드에 집착하기 보다는, NumberGenerator 와 의존관계를 가질 class 가 누가 되어야 하는지, 역할과 책임 관점에서 생각을 해보시면 좋을 것 같습니다."* — @ghojeong on [#107](sh1mj1/107-1단계-자동차-경주.md)
|
|
322
|
+
|
|
323
|
+
8. *"기본적으로 테스트만을 위해 프로덕션 코드가 수정되어서는 안된다고 생각합니다. 테스트가 프러덕션을 위해 존재하는 것이지 그 역의 관계는 아니니까요."* — @vagabond95 on [#41](whk06061/41-2단계-자동차-경주.md)
|
|
324
|
+
|
|
325
|
+
9. *"객체는 메서드 뿐만 아니라 맴버로도 구성된다는 사실을 잊지 말아주세요."* — @ghojeong on [#128](hxeyexn/128-2단계-자동차-경주.md)
|
|
326
|
+
|
|
327
|
+
10. *"처음에 최대한도로 세분화하라는 조언은, 보통 합쳐진것을 쪼개는 리팩토링 보다, 쪼개진 것을 합치는 리팩토링이 더 쉽기 때문입니다."* — @ghojeong on [#109](hxeyexn/109-1단계-자동차-경주.md)
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 통계
|
|
332
|
+
|
|
333
|
+
- **분석된 PR:** 133개
|
|
334
|
+
- **분석된 reviewee:** 77명
|
|
335
|
+
- **고유 reviewer:** ~25명 (vagabond95, ghojeong, KwonDae, galcyurio, Gyuil-Hwnag, BeokBeok, laco-dev, malibinYun, sujin9 등이 다수 PR 리뷰)
|
|
336
|
+
- **단계별:** 1단계 = 약 40 PR, 2단계 = 약 90 PR (리팩토링 포함)
|
|
337
|
+
- **분석 기간:** 2022~2025 (closed PR)
|
|
338
|
+
|
|
339
|
+
이 코퍼스는 "OOP 학습 곡선의 살아있는 데이터"로, 리뷰어들이 같은 안티패턴을 반복 지적하면서 학생들이 라운드를 거듭해 자기 기준을 세워가는 과정의 흔적이다.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# PR #37 — [베르] 코틀린 자동차 경주 제출합니다
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@SeongHoonC](https://github.com/SeongHoonC)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-racingcar/pull/37
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @laco-dev
|
|
7
|
+
- **라인 코멘트:** 40
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **MVC 의식적 분리** — Controller / Domain / View / DTO / Data 패키지로 책임 영역 구분 시도.
|
|
12
|
+
- **테스트 코드를 적극 작성** — 도메인 객체에 단위테스트 동반.
|
|
13
|
+
- **자기 판단의 장단점 정리 능력** — 멤버 변수 vs 함수 인자에 대해 장점/단점/생각을 명확히 분리해 답변.
|
|
14
|
+
|
|
15
|
+
## 못한 점 (설계 관점)
|
|
16
|
+
|
|
17
|
+
- **DTO에 검증 로직이 들어감** — `CarNamesDTO`가 자동차 개수/이름 길이/중복 검증을 가지고 있어, DTO의 정체성(계층 간 단순 데이터 운반)을 잃음.
|
|
18
|
+
- **도메인 모델이 DTO를 직접 인지** — `Car`가 DTO를 알고 있으면 의존 방향이 역전됨. DTO는 경계에서만 만져야.
|
|
19
|
+
- **`data` 패키지의 정체 불명** — `ComparisonResult`가 왜 도메인 밖에 있어야 하는지 근거가 약함. data 패키지의 존재 이유 자체가 모호.
|
|
20
|
+
- **`ComparisonResult.NONE` 같은 의미 없는 enum 값** — 비즈니스 도메인에서 "승/패/무"를 벗어나는 NONE이 어떤 상황을 표현하는지 불분명. 도메인 어휘를 잃음.
|
|
21
|
+
- **`Car.compare(winner)`처럼 절대적 이름** — 비교는 상대적인데 인자 이름이 `winner`로 결과를 가정. `other`가 자연스러움.
|
|
22
|
+
- **`Judgement`라는 절차 객체** — 우승자 판별이 멤버 변수를 가지고 있어야 할 이유가 없는데 객체로. 행위만 있는 -ment 명사.
|
|
23
|
+
- **`CarMetadataDTO`라는 의미 없는 이름** — "Metadata"는 도메인 어휘 회피의 신호. 실제 의미는 "경주 결과"인데 일반어로 도망.
|
|
24
|
+
- **Controller가 멤버 변수로 게임 상태를 가짐** — 재실행/재사용이 어렵고, 메서드 인자로 전달할 수 있는 값을 굳이 상태화.
|
|
25
|
+
- **`map` 오남용** — 반환을 안 쓰는 곳에 `map`. forEach가 적절.
|
|
26
|
+
- **이동 조건이 "0-9 중 4 이상"으로 도메인에 박힘** — 0-9 발생은 무작위의 관심사인데 자동차가 알게 됨.
|
|
27
|
+
- **테스트 이름이 추상적** — "자동차 이동 테스트", "오류 발생" 같은 표현이 무엇을 테스트하는지 안 드러냄.
|
|
28
|
+
|
|
29
|
+
## 리뷰어 의견 요지
|
|
30
|
+
|
|
31
|
+
리뷰어 @laco-dev는 **도메인 모델과 DTO의 차이**를 일관되게 짚었다. "DTO는 계층 간 의존성 없이 데이터를 전달하기 위한 것"이며 검증은 도메인이 들어야 한다는 명확한 가이드. 또한 DTO를 도메인이 알게 두면 의존 방향이 역전된다는 점.
|
|
32
|
+
|
|
33
|
+
또 다른 큰 가이드는 **"도메인 우선 구현"** — InputView부터 만들면 도메인이 정의될 때 View가 다시 바뀌므로, 도메인부터 만들고 거꾸로 입출력 경계를 그려라.
|
|
34
|
+
|
|
35
|
+
이름에 대해서도 강력한 가이드: `winner`(상대성 무시), `CarMeta`(도메인 어휘 회피), 테스트 이름의 명세화.
|
|
36
|
+
|
|
37
|
+
- **대표 인용:**
|
|
38
|
+
> DTO의 역할은 무엇일까요? DTO가 필요한 곳마다 이와 같은 검증 로직이 필요하다면, 모든 계층마다 매번 같은 코드를 작성해야 하지는 않을까요?
|
|
39
|
+
>
|
|
40
|
+
> — @laco-dev on `src/main/kotlin/dto/CarNamesDTO.kt`
|
|
41
|
+
|
|
42
|
+
> 비교하는 과정에서 winner라는 것은 상대적이지 않을까요? 이기거나 지거나 하는 결과가 나올 수 있어서 `other` 같은 이름도 괜찮을 것 같아요.
|
|
43
|
+
>
|
|
44
|
+
> — @laco-dev on `src/main/kotlin/domain/Car.kt`
|
|
45
|
+
|
|
46
|
+
> 자동차가 이동하는 조건은 4 이상으로만 볼 수 있지 않을까요? 0 부터 9 사이의 값이 발행되는 것은 랜덤의 관심사로 볼 수 있을 것 같아요.
|
|
47
|
+
>
|
|
48
|
+
> — @laco-dev on `src/main/kotlin/domain/Car.kt`
|
|
49
|
+
|
|
50
|
+
## 얻은 교훈
|
|
51
|
+
|
|
52
|
+
- **DTO는 데이터 운반체, 도메인은 행위와 invariants의 주인.** 두 가지가 섞이면 (1) 검증이 여러 계층에서 중복되고, (2) DTO가 무거워지고, (3) 도메인이 외부 형식에 끌려간다. DTO는 정말 단순한 데이터 컨테이너로 유지.
|
|
53
|
+
- **도메인 우선 구현이 시간을 아낀다.** Input/View부터 짜면 도메인이 등장할 때 두 번 수정한다. 도메인 모델로 시작하면 View가 거기에 맞춰져 한 번에 정해진다.
|
|
54
|
+
- **enum의 값은 도메인 어휘여야 한다.** `NONE`처럼 "없음을 위한 없음"은 보통 모델링 누락의 신호. 진짜 의미가 있으면 그 이름으로, 없으면 그냥 null 또는 다른 모델로.
|
|
55
|
+
- **인자 이름은 호출자 입장에서 본다.** `compare(winner)`처럼 결과를 가정하면 비교를 호출하기 전에 답을 안다는 가정이 코드에 박힌다. `other`처럼 중립적이어야 비교가 진짜 비교가 된다.
|
|
56
|
+
- **무작위/외부 자원의 출력 범위는 그 자원의 관심사.** "0-9 중 4 이상"이 자동차에 박히면 자동차가 난수 표현을 알게 된다. 자동차는 단지 "이번에 움직일까?"라는 boolean을 받는 쪽이 자연스럽다.
|
|
57
|
+
- **`X-er`, `X-ment`, `X-Metadata`는 도메인 어휘 회피의 신호.** 그 이름 뒤에 진짜 도메인 개념이 있다. `Judgement` → `RaceResult`, `CarMetadata` → `RaceRecord` 같은 식으로.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# PR #66 — [베르] 2단계 자동차 경주 미션 제출합니다
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@SeongHoonC](https://github.com/SeongHoonC)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-racingcar/pull/66
|
|
5
|
+
- **단계:** 2단계
|
|
6
|
+
- **리뷰어:** @laco-dev
|
|
7
|
+
- **라인 코멘트:** 12
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`RaceTime` 도메인 객체 도입** — 1단계의 raw Int를 도메인 개념으로 승격. 원시 강박 해소 시도.
|
|
12
|
+
- **`CarsFactory`로 Cars 생성 책임 분리** — 자동차 묶음 생성 로직을 별도 객체로.
|
|
13
|
+
- **`NumberGenerator` 인터페이스 도입** — 무작위 의존을 추상 뒤로 격리.
|
|
14
|
+
- **리뷰 후 빠른 반영과 학습 의지** — 고차 함수 적용을 "너무 신기하네요"라는 반응으로 흡수.
|
|
15
|
+
|
|
16
|
+
## 못한 점 (설계 관점)
|
|
17
|
+
|
|
18
|
+
- **`RaceTime`이 한 번 쓰면 끝나는 가변 객체** — `raceTime.reduceTime()`로 내부 상태가 소진되면 두 번째 호출에서 의도와 다른 동작. 사이드 이펙트가 시그니처 밖에서 발생.
|
|
19
|
+
- **`CarsFactory`가 구체 타입을 받음** — `NumberGenerator` 인터페이스 대신 구현체를 직접 받으면 추상의 가치가 무효.
|
|
20
|
+
- **테스트 이름이 "에러가 발생하지 않는다" 같은 추상 표현** — 무엇이 정상인지를 명세하지 못함.
|
|
21
|
+
- **`Controller.getRaceTime()`이 raw Int 반환** — 도메인 객체 `RaceTime`을 만들었으면서 정작 흐름은 원시 타입을 주고받음.
|
|
22
|
+
- **테스트만을 위한 public 노출** — 에러 메시지 상수 같은 것을 테스트 때문에 외부에 노출.
|
|
23
|
+
|
|
24
|
+
## 리뷰어 의견 요지
|
|
25
|
+
|
|
26
|
+
리뷰어 @laco-dev는 두 가지 중요한 관점을 짚었다.
|
|
27
|
+
|
|
28
|
+
1. **불변성과 재사용성** — `RaceTime`이 자기 상태를 소진하는 가변 객체면 호출자가 라이프사이클을 매번 신경 써야 한다. 고차 함수로 "횟수만 받아서 N번 반복" 형태로 만들면 객체 자체는 불변이 된다.
|
|
29
|
+
2. **테스트 이름은 명세** — "에러가 발생하지 않는다", "정상 작동" 같은 추상 표현 대신 도메인 규칙을 직접 적기. "자동차는 한번에 1대에서 20대 이하로만 만들 수 있다"처럼.
|
|
30
|
+
|
|
31
|
+
또한 **추상 타입을 받기** — Factory가 구체 NumberGenerator 대신 인터페이스를 받아야 추상의 의미가 산다.
|
|
32
|
+
|
|
33
|
+
- **대표 인용:**
|
|
34
|
+
> RaceTime을 파라미터로 넘기다 보면 의도치 않은 동작을 만들 수 있는 사이드 이펙트가 발생할 수 있다는 뜻이 됩니다 ... 재사용 가능하도록 만들려면 어떤 전략을 사용할 수 있을까요? 코틀린의 repeat() 함수처럼 반복하는 기능에 집중을 할 수 있도록 개선 해 보면 어떨까요?
|
|
35
|
+
>
|
|
36
|
+
> — @laco-dev on `src/main/kotlin/domain/RaceTime.kt`
|
|
37
|
+
|
|
38
|
+
> 자동차 개수가 1 이상 20대 이하이고 중복이 없다면 에러가 발생하지 않는다 --> 자동차는 한번에 1대에서 20대 이하로만 만들 수 있다 ... 자동차 이름에 중복이 있으면 에러가 발생한다 --> 자동차는 같은 이름으로 만들 수 없다
|
|
39
|
+
>
|
|
40
|
+
> — @laco-dev on `src/test/kotlin/domain/CarsFactoryTest.kt`
|
|
41
|
+
|
|
42
|
+
## 얻은 교훈
|
|
43
|
+
|
|
44
|
+
- **불변 객체는 라이프사이클의 자유를 준다.** 자기 상태를 소진하는 객체는 호출자가 "이미 썼나?"를 신경 써야 한다. 불변으로 만들면 동일 객체가 N번 안전하게 쓰일 수 있다 — 사이드 이펙트의 첫 번째 격리 전략.
|
|
45
|
+
- **고차 함수로 "반복"을 표현하면 객체는 데이터에만 집중한다.** `RaceTime(5).reduceUntilZero()`보다 `repeat(raceTime) { ... }`이 데이터(횟수)와 행동(반복)을 분리. 객체는 단지 횟수를 알 뿐.
|
|
46
|
+
- **추상은 사용 시점에 받는다.** 구체 타입을 받으면 그 자리에서 추상이 무너진다. Factory/Service가 추상 인터페이스를 받아야 진짜 격리.
|
|
47
|
+
- **테스트 이름 = 시스템 요구사항.** "에러 안 남"은 단언 기준일 뿐 명세가 아니다. 도메인 규칙 그 자체를 문장으로 적어야 코드 외부에서 시스템을 이해할 때 가치를 한다.
|
|
48
|
+
- **도메인 객체를 만들었다면 그 객체로 흐름을 채워라.** `RaceTime` 클래스가 있는데 정작 `getRaceTime()`이 Int를 반환하면, 그 객체는 정의만 있고 사용되지 않는다. 흐름 전체가 도메인 어휘로 통일되어야 의미가 산다.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# PR #84 — [페어 자동차 경주 미션 제출] 송이카
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@Songusika](https://github.com/Songusika), 페어로 진행
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-racingcar/pull/84
|
|
5
|
+
- **단계:** 2단계 (단일 PR)
|
|
6
|
+
- **리뷰어:** @RightHennessy
|
|
7
|
+
- **라인 코멘트:** 24
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **Name, Count, Cars 등 도메인 분리** — 원시 강박 탈출.
|
|
12
|
+
- **`Name`을 data class로 (VO 의도)** — 값 객체 모델링 시도, 페어가 자바 record와의 차이까지 직접 정리.
|
|
13
|
+
- **`RandomNumberGenerator` 인터페이스** — 테스트 가능성 인지.
|
|
14
|
+
- **`RacingGameController`의 재입력 처리** — 사용자 입력 오류 회복 흐름 정리.
|
|
15
|
+
- **페어 진행** — 두 사람의 토론 결과가 PR에 풍부함 (data class vs record 비교 등).
|
|
16
|
+
|
|
17
|
+
## 못한 점 (설계 관점)
|
|
18
|
+
|
|
19
|
+
- **`Car.position`이 외부 접근 가능 (public var)** — `private set` 누락. 리뷰 후 수정.
|
|
20
|
+
- **`Cars`의 `filter().map()` 체이닝 결과를 List로 다시 받음 → 일급 컬렉션을 새로 만들어주는 시점 누락** — `map` 반환이 `List<T>`인데 그걸 또 Cars로 감싸야 했음.
|
|
21
|
+
- **`maxOf` vs `maxBy` 혼용** — 최댓값 vs 최댓값 객체. 도메인 의도에 맞는 선택 안 됨.
|
|
22
|
+
- **`InputView`에서 null 처리를 throw로 끝냄** — smart cast/`readln()`로 도메인 향한 안전 보장 안 함.
|
|
23
|
+
|
|
24
|
+
## 리뷰어 의견 요지
|
|
25
|
+
|
|
26
|
+
리뷰어 @RightHennessy는 **"질문 + 자료 링크"**로 학생의 추가 학습 유도.
|
|
27
|
+
|
|
28
|
+
1. **data class vs record** — "왜 data class를 썼는가? 자바 record와 차이는?" → 페어가 5가지 차이점 정리 (copy, var/val, 비구조화, 상속, 인스턴스 프로퍼티). 그리고 역질문 "Sample1 vs Sample2 차이는?" → 리뷰어가 답: `equals/hashCode`는 주 생성자만 고려 → 주 생성자 밖 프로퍼티는 동치성 비교에서 빠진다.
|
|
29
|
+
|
|
30
|
+
2. **`maxOf` vs `maxBy`** — "최댓값" vs "최댓값을 가진 객체". 도메인 표현(우승자는 객체)에 맞는 함수.
|
|
31
|
+
|
|
32
|
+
3. **`map`의 반환 = `List<T>`** — `filter().map()`이 List를 만드는데, 호출자가 또 List로 감싸 이중 작업.
|
|
33
|
+
|
|
34
|
+
4. **Car.position 캡슐화** — 외부 접근 가능. `private set` 권장.
|
|
35
|
+
|
|
36
|
+
5. **smart cast** — `val input = readLine() ?: throw IllegalArgumentException()` 이후 컴파일러가 input을 non-null로 추론 → 반환 타입을 nullable로 유지할 필요 없음.
|
|
37
|
+
|
|
38
|
+
학생과 리뷰어가 **양방향 질문**으로 진행 — 학생이 역으로 퀴즈를 내고 리뷰어가 답하는 흥미로운 상호작용.
|
|
39
|
+
|
|
40
|
+
- **대표 인용:**
|
|
41
|
+
> Name 클래스를 data class로 만들어주셨군요! 혹시 사용한 이유를 설명해 주실 수 있을까요? 추가적으로, java의 record와는 어떤 차이점이 있을까요?
|
|
42
|
+
>
|
|
43
|
+
> — @RightHennessy on `src/main/kotlin/racingCar/domain/Name.kt`
|
|
44
|
+
|
|
45
|
+
> equals와 hashCode는 주 생성자에 나열된 모든 프로퍼티를 고려해 만들어진다. 이때 주 생성자 밖에 정의된 프로퍼티는 eqauls나 hashCode를 계산할 떄 고려의 대상이 아니다.
|
|
46
|
+
>
|
|
47
|
+
> — @RightHennessy on `src/main/kotlin/racingCar/domain/Name.kt` (kotlin in action 인용)
|
|
48
|
+
|
|
49
|
+
> 현재 Car의 postion은 외부에서 접근이 가능하네요. 외부에서 접근하지 못하도록 변경해보시는 것은 어떨까요 ~ ?
|
|
50
|
+
>
|
|
51
|
+
> — @RightHennessy on `src/main/kotlin/racingCar/domain/Car.kt:5`
|
|
52
|
+
|
|
53
|
+
## 얻은 교훈
|
|
54
|
+
|
|
55
|
+
- **data class의 `equals/hashCode`는 주 생성자만 본다.** "본문에 선언한 프로퍼티"는 동치성 비교에서 빠짐. VO를 만들 때 모든 식별 속성은 주 생성자에 넣어야 함.
|
|
56
|
+
- **`maxOf` vs `maxBy`의 의미 차이.** 도메인이 "우승자(객체)"를 표현해야 하면 `maxBy`. "거리(스칼라)"라면 `maxOf`. 함수 이름이 도메인 의도를 반영.
|
|
57
|
+
- **일급 컬렉션의 변환 = 한 번만 감싼다.** `cars.filter().map()`의 반환이 `List<Car>`인데 다시 `Cars(it)`로 감싸야 하면 중간에 List를 두는 게 의미 없음.
|
|
58
|
+
- **smart cast로 nullable의 흐름 종결.** null 검사 후 컴파일러가 non-null로 좁히면, 반환 타입까지 non-null로 끌어올림. throw 한 줄로 도메인이 깨끗.
|
|
59
|
+
- **페어 프로그래밍의 가치 = PR에 토론이 보임.** "왜 이렇게 했는가"가 두 사람의 합의로 들어오면 리뷰가 그 합의를 검증하는 단계로 격상.
|
|
60
|
+
- **양방향 질문 = 깊이의 신호.** 학생이 "이 두 코드의 차이가 뭘까요?"로 역질문하면 리뷰어가 자료를 인용해 답하면서 토론의 격이 올라감.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# PR #114 — [자동차 경주 - 리팩토링] 서기 미션 제출합니다
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@Yunseok-Nam](https://github.com/Yunseok-Nam)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-racingcar/pull/114
|
|
5
|
+
- **단계:** 2단계 (리팩토링)
|
|
6
|
+
- **리뷰어:** @Gyuil-Hwnag
|
|
7
|
+
- **라인 코멘트:** 6
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **이전 라운드 피드백 흡수 (EOF, 함수 분리, 테스트 네이밍)** — 작은 지적도 끝까지 반영.
|
|
12
|
+
- **`@JvmStatic` 이해 + 자체 정리** — `companion object` 메서드가 자바 변환 시 Companion 내부 메서드가 되고, JUnit5(Java)가 `@MethodSource`에 static 요구 → `@JvmStatic` 필요. 깊이 있는 답변.
|
|
13
|
+
|
|
14
|
+
## 못한 점 (설계 관점)
|
|
15
|
+
|
|
16
|
+
- **테스트 내부 헬퍼 메서드 (`moveTwice`)가 public** — 테스트 클래스 외부에서 접근 가능 (불필요). private 접근 제한자 누락.
|
|
17
|
+
- **`@MethodSource` factory 메서드의 case 데이터를 별도 TestCase 클래스로 분리하지 않음** — 케이스 수 늘면 가독성 저하 가능.
|
|
18
|
+
|
|
19
|
+
## 리뷰어 의견 요지
|
|
20
|
+
|
|
21
|
+
리뷰어 @Gyuil-Hwnag은 **"고민해볼 점"으로 던지고 학생이 자가 답변** 스타일 유지. 이번 라운드는 리팩토링이라 코멘트도 적음 (6개).
|
|
22
|
+
|
|
23
|
+
1. **`@JvmStatic`의 이유** — 정답을 묻지 않고 "차이점이 무엇일까요?"로 던짐. 학생이 자바 변환 코드까지 직접 디컴파일해 정리.
|
|
24
|
+
|
|
25
|
+
2. **테스트 헬퍼의 접근 제한자** — "private으로 막는 방식"이 안 보인다는 지적. 테스트 코드도 캡슐화 대상.
|
|
26
|
+
|
|
27
|
+
3. **TestCase 분리 trade-off 명시** — "별도 파일로 뽑으면 케이스 한눈에 보기 좋다 / 단점은 두 파일을 살펴봐야 함" → 양면 트레이드오프를 학생에게 던짐.
|
|
28
|
+
|
|
29
|
+
- **대표 인용:**
|
|
30
|
+
> moveTwice의 경우 해당 CarTest에서만 사용을 하므로 private 접근 지정자로 외부에서의 접근을 막는 방식으로 가봐도 좋을 것 같습니다!! 그외에 테스트에 대한 케이스 관리를 위해서 TestCase로 뽑아두는 방식도 고민해볼 필요는 있는 것 같습니다~
|
|
31
|
+
>
|
|
32
|
+
> — @Gyuil-Hwnag on `src/test/kotlin/model/CarTest.kt:16`
|
|
33
|
+
|
|
34
|
+
> 과연 @JvmStatic 어노테이션을 정의 안한것이랑 정의한 것에는 어떤 차이점이 있을까요??
|
|
35
|
+
>
|
|
36
|
+
> — @Gyuil-Hwnag on `src/test/kotlin/model/CarsManagerTest.kt:33`
|
|
37
|
+
|
|
38
|
+
## 얻은 교훈
|
|
39
|
+
|
|
40
|
+
- **테스트 코드도 캡슐화 대상.** 헬퍼 함수가 외부에서 안 쓰이면 private. 테스트라고 접근 제한 자유로운 게 아님.
|
|
41
|
+
- **`@JvmStatic`의 본질 = "JVM 바이트코드 레벨 static 강제"**. Kotlin `companion object` 메서드는 Companion 인스턴스 메서드로 컴파일됨. Java가 진짜 static을 요구하는 자리에서는 어노테이션이 필요.
|
|
42
|
+
- **TestCase 분리는 케이스 수의 함수**. 케이스 3-5개면 inline, 10개 넘으면 별도 파일로 빼는 게 가독성. "이 한 줄에서 모든 케이스를 볼 수 있나?"가 기준.
|
|
43
|
+
- **자가 답변의 깊이 = 학습 곡선의 신호.** 리뷰어가 "차이점이 뭘까요?"로 던졌을 때 디컴파일까지 가서 답한 깊이는 다음 라운드의 리뷰 깊이도 끌어올림.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# PR #96 — [자동차 경주] 서기 미션 제출합니다
|
|
2
|
+
|
|
3
|
+
- **Reviewee:** [@Yunseok-Nam](https://github.com/Yunseok-Nam)
|
|
4
|
+
- **PR:** https://github.com/woowacourse/kotlin-racingcar/pull/96
|
|
5
|
+
- **단계:** 1단계
|
|
6
|
+
- **리뷰어:** @Gyuil-Hwnag
|
|
7
|
+
- **라인 코멘트:** 24
|
|
8
|
+
|
|
9
|
+
## 잘한 점 (설계 관점)
|
|
10
|
+
|
|
11
|
+
- **`Validation` object 분리** — 검증 로직 외부화.
|
|
12
|
+
- **`RandomNumber` 인터페이스 도입** — 테스트 가능성 확보를 위한 추상화.
|
|
13
|
+
- **`CarsManager`로 Cars 컬렉션 관리** — 일급 컬렉션의 초기 형태.
|
|
14
|
+
- **`forwardCount`를 주 생성자에서 빼고 내부 초기화** — "Car 생성 시 forwardCount 0이어야 한다"는 invariant 보호.
|
|
15
|
+
- **getter 제거 후 property 사용** — 코틀린식 캡슐화.
|
|
16
|
+
- **`require` 활용** — 도메인 무결성 검증.
|
|
17
|
+
|
|
18
|
+
## 못한 점 (설계 관점)
|
|
19
|
+
|
|
20
|
+
- **`Validation`이라는 일반 이름** — 무엇을 검증하는지 모름. `carName` 같은 동사형으로도 부족 (`checkName`이 낫다).
|
|
21
|
+
- **`Car`가 검증을 직접 안 하고 `Validation` object에 위임** — 도메인 무결성을 외부 유틸리티가 책임.
|
|
22
|
+
- **Controller의 `run`이 여러 단계 (초기화/플레이/결과) 한 메서드에 뭉침** — 함수 분리 필요.
|
|
23
|
+
- **`CarsManager`의 "Manager" 접미사** — 책임이 모호한 일반어. 무엇을 manage 하는지 코드 본문 봐야 앎.
|
|
24
|
+
|
|
25
|
+
## 리뷰어 의견 요지
|
|
26
|
+
|
|
27
|
+
리뷰어 @Gyuil-Hwnag은 **확정 의견보다는 "고민해볼 점" 던지기** 스타일.
|
|
28
|
+
|
|
29
|
+
1. **함수 책임 분리** — Controller의 `run`을 `initialize / play / result` 셋으로 쪼개라.
|
|
30
|
+
|
|
31
|
+
2. **Validation의 위치 토론** — "Car에서 직접 안 하고 ValidationUtils로 뽑은 이유는?" → 학생은 "InputView 선에서 사용자 입력 에러 잡고, 도메인 검증은 입력 재시도 확장에 유리하다"로 답. 리뷰어 수용.
|
|
32
|
+
|
|
33
|
+
3. **테스트 네이밍 GWT** — `자동차가 1칸 이동하면 거리는 1이다` 같은 한국어 fun 이름 + body 안 given/when/then 주석.
|
|
34
|
+
|
|
35
|
+
4. **forwardCount 위치** — 주 생성자 파라미터로 받지 말고 내부에서 0으로 초기화. → 학생이 정확히 이 변경을 적용.
|
|
36
|
+
|
|
37
|
+
5. **함수 이름 = 동사** — `Validation.carName()` 같은 명사 이름은 "이게 뭐 하는 함수냐"가 안 보임. `checkName()`처럼 동사.
|
|
38
|
+
|
|
39
|
+
- **대표 인용:**
|
|
40
|
+
> 참고로 함수 네이밍의 경우 Validation(확인) 이라는 뜻에 맞게 carName -> checkName으로 변경 고려해 해보는 것도 좋을 것 같습니다!! import 하였을 때 단순히 carName 만으로는 어떤 기능을 담당하는 함수인지에 대한 판별이 어려울 수도 있겠다는 생각이 들어
|
|
41
|
+
>
|
|
42
|
+
> — @Gyuil-Hwnag on `src/main/kotlin/util/Validation.kt`
|
|
43
|
+
|
|
44
|
+
> 개인적인 생각이지만 Car라는 class에 fowarCount 값을 파라미터로 가지면서 변경하는 방법도 좋지만 Car 클래스 내부적으로 forwardCount를 가지고 있는 것도 고민해볼 필요는 있는 것 같습니다!
|
|
45
|
+
>
|
|
46
|
+
> — @Gyuil-Hwnag on `src/main/kotlin/model/Car.kt`
|
|
47
|
+
|
|
48
|
+
## 얻은 교훈
|
|
49
|
+
|
|
50
|
+
- **도메인 객체의 초기 상태는 생성자가 아니라 init/default가 담아야 한다.** `Car(name)`로 받고 forwardCount는 0으로 시작. 외부가 초기 위치를 정할 권리가 없다.
|
|
51
|
+
- **함수 이름은 동사형 + 무엇에 대한 동사**. `carName()`은 명사라 부르는 쪽에서 "이 함수는 뭘 하는 거지?"가 됨. `checkName()`, `validateName()`처럼 동사로.
|
|
52
|
+
- **검증의 위치 = 입력 재시도 확장성으로 정해질 수 있다.** "도메인 init에서 던지면 catch해서 재입력 어렵다 → InputView/Validator 선에서 잡고 정상 흐름으로"라는 논리가 성립.
|
|
53
|
+
- **getter 메서드 제거 = property 활용.** Kotlin에서 `getForwardCount()` 자바식 메서드는 자동 생성된 property getter가 이미 있는데 또 만든 셈. 호출 측에서 `car.forwardCount`로 단순화.
|
|
54
|
+
- **"Manager", "Util", "Helper" 같은 일반어 접미사는 책임 회피의 흔적.** 무엇을 관리하는지 / 무엇을 돕는지가 이름에 드러나야 함.
|