@k2works/claude-code-booster 2.7.1 → 3.1.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/lib/assets/docs/article/functional-desgin-ppp/all/01-immutability-and-data-transformation.md +475 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/02-function-composition.md +519 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/03-polymorphism.md +537 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/04-data-validation.md +300 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/05-property-based-testing.md +320 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/06-tdd-and-functional.md +498 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/07-composite-pattern.md +298 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/08-decorator-pattern.md +291 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/09-adapter-pattern.md +336 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/10-strategy-pattern.md +303 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/11-command-pattern.md +286 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/12-visitor-pattern.md +322 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/13-abstract-factory-pattern.md +319 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/14-abstract-server-pattern.md +365 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/15-gossiping-bus-drivers.md +156 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/16-payroll-system.md +178 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/17-video-rental-system.md +312 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/18-concurrency-system.md +287 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/19-wa-tor-simulation.md +286 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/20-pattern-interactions.md +274 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/21-best-practices.md +294 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/22-oo-to-fp-migration.md +337 -0
- package/lib/assets/docs/article/functional-desgin-ppp/all/index.md +388 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/01-immutability-and-data-transformation.md +271 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/02-function-composition.md +380 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/03-polymorphism.md +384 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/04-clojure-spec.md +350 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/05-property-based-testing.md +352 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/06-tdd-in-functional.md +383 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/07-composite-pattern.md +529 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/08-decorator-pattern.md +395 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/09-adapter-pattern.md +399 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/10-strategy-pattern.md +485 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/11-command-pattern.md +566 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/12-visitor-pattern.md +567 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/13-abstract-factory-pattern.md +475 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/14-abstract-server-pattern.md +462 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/15-gossiping-bus-drivers.md +323 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/16-payroll-system.md +401 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/17-video-rental-system.md +450 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/18-concurrency-system.md +475 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/19-wator-simulation.md +739 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/20-pattern-interactions.md +562 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/21-best-practices.md +506 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/22-oo-to-fp-migration.md +526 -0
- package/lib/assets/docs/article/functional-desgin-ppp/clojure/index.md +197 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/01-immutability-and-data-transformation.md +381 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/02-function-composition.md +374 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/03-polymorphism.md +375 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/04-data-validation.md +195 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/05-property-based-testing.md +268 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/06-tdd-and-fp.md +294 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/07-effects-and-pure-functions.md +164 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/08-error-handling-strategies.md +168 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/09-io-and-external-systems.md +254 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/10-concurrency-patterns.md +269 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/11-command-pattern.md +148 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/12-visitor-pattern.md +176 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/13-abstract-factory-pattern.md +604 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/14-abstract-server-pattern.md +729 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/15-gossiping-bus-drivers.md +291 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/16-payroll-system.md +420 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/17-video-rental-system.md +319 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/18-concurrency-system.md +466 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/19-wator-simulation.md +523 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/20-pattern-interactions.md +287 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/21-best-practices.md +340 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/22-oo-to-fp-migration.md +395 -0
- package/lib/assets/docs/article/functional-desgin-ppp/elixir/index.md +204 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/01-immutability-and-data-transformation.md +382 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/02-function-composition.md +452 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/03-polymorphism.md +495 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/04-data-validation.md +416 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/05-property-based-testing.md +382 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/06-tdd-functional.md +687 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/07-composite-pattern.md +442 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/08-decorator-pattern.md +479 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/09-adapter-pattern.md +479 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/10-strategy-pattern.md +427 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/11-command-pattern.md +428 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/12-visitor-pattern.md +339 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/13-abstract-factory-pattern.md +309 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/14-abstract-server-pattern.md +596 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/15-gossiping-bus-drivers.md +353 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/16-payroll-system.md +350 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/17-video-rental-system.md +412 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/18-concurrency-system.md +367 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/19-wator-simulation.md +401 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/20-pattern-interactions.md +291 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/21-best-practices.md +320 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/22-oo-to-fp-migration.md +322 -0
- package/lib/assets/docs/article/functional-desgin-ppp/fsharp/index.md +230 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/01-immutability-and-data-transformation.md +298 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/02-function-composition.md +304 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/03-polymorphism.md +362 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/04-data-validation.md +257 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/05-property-based-testing.md +254 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/06-tdd-functional.md +283 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/07-composite-pattern.md +395 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/08-decorator-pattern.md +319 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/09-adapter-pattern.md +382 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/10-strategy-pattern.md +287 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/11-command-pattern.md +303 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/12-visitor-pattern.md +326 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/13-abstract-factory-pattern.md +332 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/14-abstract-server-pattern.md +379 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/15-gossiping-bus-drivers.md +175 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/16-payroll-system.md +219 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/17-video-rental-system.md +244 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/18-concurrency-system.md +363 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/19-wator-simulation.md +438 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/20-pattern-interactions.md +323 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/21-best-practices.md +403 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/22-oo-to-fp-migration.md +469 -0
- package/lib/assets/docs/article/functional-desgin-ppp/haskell/index.md +174 -0
- package/lib/assets/docs/article/functional-desgin-ppp/index.md +90 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/01-immutability-and-data-transformation.md +448 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/02-function-composition.md +463 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/03-polymorphism.md +425 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/04-data-validation.md +273 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/05-property-based-testing.md +247 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/06-tdd-and-functional.md +841 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/07-composite-pattern.md +384 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/08-decorator-pattern.md +383 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/09-adapter-pattern.md +339 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/10-strategy-pattern.md +331 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/11-command-pattern.md +356 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/12-visitor-pattern.md +379 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/13-abstract-factory-pattern.md +361 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/14-abstract-server-pattern.md +392 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/15-gossiping-bus-drivers.md +300 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/16-payroll-system.md +297 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/17-video-rental-system.md +304 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/18-concurrency-system.md +315 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/19-wator-simulation.md +311 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/20-pattern-interactions.md +304 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/21-best-practices.md +336 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/22-oo-to-fp-migration.md +349 -0
- package/lib/assets/docs/article/functional-desgin-ppp/rust/index.md +199 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/01-immutability-and-data-transformation.md +326 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/02-function-composition.md +348 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/03-polymorphism.md +357 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/04-data-validation.md +364 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/05-property-based-testing.md +515 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/06-tdd-functional.md +557 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/07-composite-pattern.md +363 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/08-decorator-pattern.md +327 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/09-adapter-pattern.md +517 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/10-strategy-pattern.md +441 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/11-command-pattern.md +407 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/12-visitor-pattern.md +379 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/13-abstract-factory-pattern.md +398 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/14-abstract-server-pattern.md +476 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/15-gossiping-bus-drivers.md +389 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/16-payroll-system.md +342 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/17-video-rental-system.md +324 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/18-concurrency-system.md +730 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/19-wator-simulation.md +624 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/20-pattern-interactions.md +512 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/21-best-practices.md +427 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/22-oo-to-fp-migration.md +682 -0
- package/lib/assets/docs/article/functional-desgin-ppp/scala/index.md +199 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/01-todo-list-and-first-test.md +166 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/02-fake-it-and-triangulation.md +162 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/03-obvious-implementation-and-refactoring.md +135 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/04-version-control-and-conventional-commits.md +88 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/05-package-management-and-static-analysis.md +299 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/06-task-runner-and-ci-cd.md +241 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/07-protocols-and-records.md +131 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/08-multimethods-and-design-patterns.md +130 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/09-namespaces-and-module-design.md +127 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/10-higher-order-functions-and-composition.md +114 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/11-persistent-data-and-pipeline.md +138 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/12-error-handling-and-spec.md +161 -0
- package/lib/assets/docs/article/getting-start-tdd/clojure/index.md +65 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter01.md +232 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter02.md +244 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter03.md +202 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter04.md +92 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter05.md +256 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter06.md +195 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter07.md +214 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter08.md +249 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter09.md +174 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter10.md +166 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter11.md +192 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/chapter12.md +211 -0
- package/lib/assets/docs/article/getting-start-tdd/csharp/index.md +83 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/01-todo-list-and-first-test.md +87 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/02-fake-it-and-triangulation.md +95 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/03-obvious-implementation-and-refactoring.md +109 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/04-version-control-and-conventional-commits.md +96 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/05-package-management-and-static-analysis.md +88 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/06-task-runner-and-ci-cd.md +71 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/07-structs-and-protocols.md +110 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/08-pattern-matching-and-guards.md +108 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/09-module-design-and-behaviours.md +104 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/10-higher-order-functions-and-pipeline.md +178 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/11-stream-and-lazy-evaluation.md +142 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/12-error-handling-and-with.md +145 -0
- package/lib/assets/docs/article/getting-start-tdd/elixir/index.md +35 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter01.md +202 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter02.md +246 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter03.md +218 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter04.md +179 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter05.md +267 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter06.md +190 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter07.md +161 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter08.md +175 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter09.md +222 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter10.md +189 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter11.md +212 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter12.md +215 -0
- package/lib/assets/docs/article/getting-start-tdd/fsharp/index.md +71 -0
- package/lib/assets/docs/article/getting-start-tdd/go/01-todo-list-and-first-test.md +213 -0
- package/lib/assets/docs/article/getting-start-tdd/go/02-fake-it-and-triangulation.md +302 -0
- package/lib/assets/docs/article/getting-start-tdd/go/03-obvious-implementation-and-refactoring.md +339 -0
- package/lib/assets/docs/article/getting-start-tdd/go/04-version-control-and-conventional-commits.md +112 -0
- package/lib/assets/docs/article/getting-start-tdd/go/05-package-management-and-static-analysis.md +272 -0
- package/lib/assets/docs/article/getting-start-tdd/go/06-task-runner-and-ci-cd.md +233 -0
- package/lib/assets/docs/article/getting-start-tdd/go/07-encapsulation-and-polymorphism.md +394 -0
- package/lib/assets/docs/article/getting-start-tdd/go/08-design-patterns.md +422 -0
- package/lib/assets/docs/article/getting-start-tdd/go/09-solid-principles-and-module-design.md +400 -0
- package/lib/assets/docs/article/getting-start-tdd/go/10-higher-order-functions-and-composition.md +226 -0
- package/lib/assets/docs/article/getting-start-tdd/go/11-immutable-data-and-pipeline.md +296 -0
- package/lib/assets/docs/article/getting-start-tdd/go/12-error-handling-and-type-safety.md +411 -0
- package/lib/assets/docs/article/getting-start-tdd/go/index.md +83 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/01-todo-list-and-first-test.md +279 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/02-fake-it-and-triangulation.md +337 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/03-obvious-implementation-and-refactoring.md +257 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/04-version-control-and-conventional-commits.md +182 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/05-package-management-and-static-analysis.md +313 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/06-task-runner-and-ci-cd.md +309 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/07-algebraic-data-types-and-type-classes.md +412 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/08-pattern-matching-and-guards.md +390 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/09-module-design-and-smart-constructors.md +461 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/10-higher-order-functions-and-currying.md +434 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/11-function-composition-and-point-free.md +392 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/12-monad-and-error-handling.md +631 -0
- package/lib/assets/docs/article/getting-start-tdd/haskell/index.md +49 -0
- package/lib/assets/docs/article/getting-start-tdd/index.md +93 -0
- package/lib/assets/docs/article/getting-start-tdd/integration/01-language-overview.md +375 -0
- package/lib/assets/docs/article/getting-start-tdd/integration/02-test-framework-comparison.md +349 -0
- package/lib/assets/docs/article/getting-start-tdd/integration/03-tdd-pattern-comparison.md +445 -0
- package/lib/assets/docs/article/getting-start-tdd/integration/04-type-system-comparison.md +405 -0
- package/lib/assets/docs/article/getting-start-tdd/integration/05-dev-environment-comparison.md +330 -0
- package/lib/assets/docs/article/getting-start-tdd/integration/06-learning-roadmap.md +274 -0
- package/lib/assets/docs/article/getting-start-tdd/integration/index.md +69 -0
- package/lib/assets/docs/article/getting-start-tdd/java/01-todo-list-and-first-test.md +234 -0
- package/lib/assets/docs/article/getting-start-tdd/java/02-fake-it-and-triangulation.md +261 -0
- package/lib/assets/docs/article/getting-start-tdd/java/03-obvious-implementation-and-refactoring.md +185 -0
- package/lib/assets/docs/article/getting-start-tdd/java/04-version-control-and-conventional-commits.md +115 -0
- package/lib/assets/docs/article/getting-start-tdd/java/05-package-management-and-static-analysis.md +382 -0
- package/lib/assets/docs/article/getting-start-tdd/java/06-task-runner-and-ci-cd.md +272 -0
- package/lib/assets/docs/article/getting-start-tdd/java/07-encapsulation-and-polymorphism.md +626 -0
- package/lib/assets/docs/article/getting-start-tdd/java/08-design-patterns.md +393 -0
- package/lib/assets/docs/article/getting-start-tdd/java/09-solid-principles-and-module-design.md +310 -0
- package/lib/assets/docs/article/getting-start-tdd/java/10-higher-order-functions-and-composition.md +188 -0
- package/lib/assets/docs/article/getting-start-tdd/java/11-immutable-data-and-pipeline.md +167 -0
- package/lib/assets/docs/article/getting-start-tdd/java/12-error-handling-and-type-safety.md +205 -0
- package/lib/assets/docs/article/getting-start-tdd/java/index.md +61 -0
- package/lib/assets/docs/article/getting-start-tdd/node/01-todo-list-and-first-test.md +244 -0
- package/lib/assets/docs/article/getting-start-tdd/node/02-fake-it-and-triangulation.md +262 -0
- package/lib/assets/docs/article/getting-start-tdd/node/03-obvious-implementation-and-refactoring.md +169 -0
- package/lib/assets/docs/article/getting-start-tdd/node/04-version-control-and-conventional-commits.md +112 -0
- package/lib/assets/docs/article/getting-start-tdd/node/05-package-management-and-static-analysis.md +314 -0
- package/lib/assets/docs/article/getting-start-tdd/node/06-task-runner-and-ci-cd.md +235 -0
- package/lib/assets/docs/article/getting-start-tdd/node/07-encapsulation-and-polymorphism.md +327 -0
- package/lib/assets/docs/article/getting-start-tdd/node/08-design-patterns.md +322 -0
- package/lib/assets/docs/article/getting-start-tdd/node/09-solid-principles-and-module-design.md +285 -0
- package/lib/assets/docs/article/getting-start-tdd/node/10-higher-order-functions-and-composition.md +199 -0
- package/lib/assets/docs/article/getting-start-tdd/node/11-immutable-data-and-pipeline.md +207 -0
- package/lib/assets/docs/article/getting-start-tdd/node/12-error-handling-and-type-safety.md +295 -0
- package/lib/assets/docs/article/getting-start-tdd/node/index.md +56 -0
- package/lib/assets/docs/article/getting-start-tdd/php/01-todo-list-and-first-test.md +259 -0
- package/lib/assets/docs/article/getting-start-tdd/php/02-fake-it-and-triangulation.md +200 -0
- package/lib/assets/docs/article/getting-start-tdd/php/03-obvious-implementation-and-refactoring.md +248 -0
- package/lib/assets/docs/article/getting-start-tdd/php/04-version-control-and-conventional-commits.md +141 -0
- package/lib/assets/docs/article/getting-start-tdd/php/05-package-management-and-static-analysis.md +410 -0
- package/lib/assets/docs/article/getting-start-tdd/php/06-task-runner-and-ci-cd.md +321 -0
- package/lib/assets/docs/article/getting-start-tdd/php/07-encapsulation-and-polymorphism.md +372 -0
- package/lib/assets/docs/article/getting-start-tdd/php/08-design-patterns.md +453 -0
- package/lib/assets/docs/article/getting-start-tdd/php/09-solid-principles-and-module-design.md +460 -0
- package/lib/assets/docs/article/getting-start-tdd/php/10-higher-order-functions-and-composition.md +182 -0
- package/lib/assets/docs/article/getting-start-tdd/php/11-immutable-data-and-pipeline.md +266 -0
- package/lib/assets/docs/article/getting-start-tdd/php/12-error-handling-and-type-safety.md +308 -0
- package/lib/assets/docs/article/getting-start-tdd/php/index.md +84 -0
- package/lib/assets/docs/article/getting-start-tdd/python/01-todo-list-and-first-test.md +201 -0
- package/lib/assets/docs/article/getting-start-tdd/python/02-fake-it-and-triangulation.md +247 -0
- package/lib/assets/docs/article/getting-start-tdd/python/03-obvious-implementation-and-refactoring.md +199 -0
- package/lib/assets/docs/article/getting-start-tdd/python/04-version-control-and-conventional-commits.md +87 -0
- package/lib/assets/docs/article/getting-start-tdd/python/05-package-management-and-static-analysis.md +274 -0
- package/lib/assets/docs/article/getting-start-tdd/python/06-task-runner-and-ci-cd.md +190 -0
- package/lib/assets/docs/article/getting-start-tdd/python/07-encapsulation-and-polymorphism.md +208 -0
- package/lib/assets/docs/article/getting-start-tdd/python/08-design-patterns.md +172 -0
- package/lib/assets/docs/article/getting-start-tdd/python/09-solid-principles-and-module-design.md +130 -0
- package/lib/assets/docs/article/getting-start-tdd/python/10-higher-order-functions-and-composition.md +122 -0
- package/lib/assets/docs/article/getting-start-tdd/python/11-immutable-data-and-pipeline.md +116 -0
- package/lib/assets/docs/article/getting-start-tdd/python/12-error-handling-and-type-safety.md +126 -0
- package/lib/assets/docs/article/getting-start-tdd/python/index.md +55 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/01-todo-list-and-first-test.md +231 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/02-fake-it-and-triangulation.md +238 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/03-obvious-implementation-and-refactoring.md +228 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/04-version-control-and-conventional-commits.md +112 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/05-package-management-and-static-analysis.md +287 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/06-task-runner-and-ci-cd.md +248 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/07-encapsulation-and-polymorphism.md +279 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/08-design-patterns.md +329 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/09-solid-principles-and-module-design.md +196 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/10-higher-order-functions-and-composition.md +175 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/11-immutable-data-and-pipeline.md +233 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/12-error-handling-and-type-safety.md +398 -0
- package/lib/assets/docs/article/getting-start-tdd/ruby/index.md +83 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/01-todo-list-and-first-test.md +211 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/02-fake-it-and-triangulation.md +264 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/03-obvious-implementation-and-refactoring.md +233 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/04-version-control-and-conventional-commits.md +92 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/05-package-management-and-static-analysis.md +212 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/06-task-runner-and-ci-cd.md +164 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/07-encapsulation-and-polymorphism.md +142 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/08-design-patterns.md +145 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/09-solid-principles-and-module-design.md +110 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/10-higher-order-functions-and-composition.md +94 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/11-immutable-data-and-pipeline.md +105 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/12-error-handling-and-type-safety.md +112 -0
- package/lib/assets/docs/article/getting-start-tdd/rust/index.md +83 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/01-todo-list-and-first-test.md +111 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/02-fake-it-and-triangulation.md +107 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/03-obvious-implementation-and-refactoring.md +99 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/04-version-control-and-conventional-commits.md +123 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/05-package-management-and-static-analysis.md +196 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/06-task-runner-and-ci-cd.md +186 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/07-case-classes-and-traits.md +139 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/08-pattern-matching-and-sealed-traits.md +106 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/09-packages-and-module-design.md +75 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/10-higher-order-functions-and-composition.md +104 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/11-collections-and-lazy-evaluation.md +94 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/12-error-handling-and-type-safety.md +92 -0
- package/lib/assets/docs/article/getting-start-tdd/scala/index.md +65 -0
- package/lib/assets/docs/article/grokking-concurrency/all/index.md +404 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-1-ch02-sequential.md +554 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-2-ch04-05-threads.md +469 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-3-ch06-multitasking.md +520 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-4-ch07-parallel-patterns.md +420 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-5-ch08-09-synchronization.md +510 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-6-ch10-11-nonblocking-io.md +435 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-7-ch12-async.md +465 -0
- package/lib/assets/docs/article/grokking-concurrency/all/part-8-ch13-mapreduce.md +377 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/index.md +116 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-1.md +108 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-2.md +101 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-3.md +122 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-4.md +123 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-5.md +118 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-6.md +89 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-7.md +100 -0
- package/lib/assets/docs/article/grokking-concurrency/clojure/part-8.md +120 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/index.md +101 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-1.md +97 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-2.md +123 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-3.md +101 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-4.md +112 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-5.md +99 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-6.md +61 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-7.md +84 -0
- package/lib/assets/docs/article/grokking-concurrency/csharp/part-8.md +92 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/index.md +65 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-1.md +80 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-2.md +103 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-3.md +94 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-4.md +110 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-5.md +104 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-6.md +93 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-7.md +121 -0
- package/lib/assets/docs/article/grokking-concurrency/fsharp/part-8.md +107 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/index.md +248 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-1.md +96 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-2.md +96 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-3.md +91 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-4.md +106 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-5.md +99 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-6.md +95 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-7.md +111 -0
- package/lib/assets/docs/article/grokking-concurrency/haskell/part-8.md +118 -0
- package/lib/assets/docs/article/grokking-concurrency/index.md +66 -0
- package/lib/assets/docs/article/grokking-concurrency/java/index.md +102 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-1.md +308 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-2.md +334 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-3.md +221 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-4.md +213 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-5.md +112 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-6.md +69 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-7.md +101 -0
- package/lib/assets/docs/article/grokking-concurrency/java/part-8.md +101 -0
- package/lib/assets/docs/article/grokking-concurrency/python/index.md +313 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-1.md +239 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-2.md +418 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-3.md +227 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-4.md +299 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-5.md +315 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-6.md +297 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-7.md +314 -0
- package/lib/assets/docs/article/grokking-concurrency/python/part-8.md +360 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/index.md +270 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-1.md +108 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-2.md +120 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-3.md +126 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-4.md +175 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-5.md +158 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-6.md +94 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-7.md +133 -0
- package/lib/assets/docs/article/grokking-concurrency/rust/part-8.md +155 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/index.md +69 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-1.md +78 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-2.md +112 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-3.md +93 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-4.md +110 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-5.md +119 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-6.md +83 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-7.md +131 -0
- package/lib/assets/docs/article/grokking-concurrency/scala/part-8.md +129 -0
- package/lib/assets/docs/article/grokkingfp/all/index.md +368 -0
- package/lib/assets/docs/article/grokkingfp/all/part-1-ch01-fp-introduction.md +530 -0
- package/lib/assets/docs/article/grokkingfp/all/part-1-ch02-pure-functions.md +923 -0
- package/lib/assets/docs/article/grokkingfp/all/part-2-ch03-immutable-data.md +1122 -0
- package/lib/assets/docs/article/grokkingfp/all/part-2-ch04-higher-order-functions.md +1104 -0
- package/lib/assets/docs/article/grokkingfp/all/part-2-ch05-flatmap.md +1026 -0
- package/lib/assets/docs/article/grokkingfp/all/part-3-ch06-option.md +777 -0
- package/lib/assets/docs/article/grokkingfp/all/part-3-ch07-either-adt.md +871 -0
- package/lib/assets/docs/article/grokkingfp/all/part-4-ch08-io-monad.md +972 -0
- package/lib/assets/docs/article/grokkingfp/all/part-4-ch09-streams.md +926 -0
- package/lib/assets/docs/article/grokkingfp/all/part-5-ch10-concurrency.md +870 -0
- package/lib/assets/docs/article/grokkingfp/all/part-6-ch11-application.md +715 -0
- package/lib/assets/docs/article/grokkingfp/all/part-6-ch12-testing.md +626 -0
- package/lib/assets/docs/article/grokkingfp/all/writing-plan.md +696 -0
- package/lib/assets/docs/article/grokkingfp/clojure/index.md +276 -0
- package/lib/assets/docs/article/grokkingfp/clojure/part-1.md +667 -0
- package/lib/assets/docs/article/grokkingfp/clojure/part-2.md +643 -0
- package/lib/assets/docs/article/grokkingfp/clojure/part-3.md +620 -0
- package/lib/assets/docs/article/grokkingfp/clojure/part-4.md +697 -0
- package/lib/assets/docs/article/grokkingfp/clojure/part-5.md +751 -0
- package/lib/assets/docs/article/grokkingfp/clojure/part-6.md +721 -0
- package/lib/assets/docs/article/grokkingfp/csharp/index.md +246 -0
- package/lib/assets/docs/article/grokkingfp/csharp/part-1.md +811 -0
- package/lib/assets/docs/article/grokkingfp/csharp/part-2.md +971 -0
- package/lib/assets/docs/article/grokkingfp/csharp/part-3.md +981 -0
- package/lib/assets/docs/article/grokkingfp/csharp/part-4.md +949 -0
- package/lib/assets/docs/article/grokkingfp/csharp/part-5.md +947 -0
- package/lib/assets/docs/article/grokkingfp/csharp/part-6.md +739 -0
- package/lib/assets/docs/article/grokkingfp/elixir/index.md +203 -0
- package/lib/assets/docs/article/grokkingfp/elixir/part-1.md +710 -0
- package/lib/assets/docs/article/grokkingfp/elixir/part-2.md +838 -0
- package/lib/assets/docs/article/grokkingfp/elixir/part-3.md +985 -0
- package/lib/assets/docs/article/grokkingfp/elixir/part-4.md +974 -0
- package/lib/assets/docs/article/grokkingfp/elixir/part-5.md +1284 -0
- package/lib/assets/docs/article/grokkingfp/elixir/part-6.md +1047 -0
- package/lib/assets/docs/article/grokkingfp/fsharp/index.md +210 -0
- package/lib/assets/docs/article/grokkingfp/fsharp/part-1.md +714 -0
- package/lib/assets/docs/article/grokkingfp/fsharp/part-2.md +961 -0
- package/lib/assets/docs/article/grokkingfp/fsharp/part-3.md +972 -0
- package/lib/assets/docs/article/grokkingfp/fsharp/part-4.md +832 -0
- package/lib/assets/docs/article/grokkingfp/fsharp/part-5.md +911 -0
- package/lib/assets/docs/article/grokkingfp/fsharp/part-6.md +920 -0
- package/lib/assets/docs/article/grokkingfp/haskell/index.md +234 -0
- package/lib/assets/docs/article/grokkingfp/haskell/part-1.md +591 -0
- package/lib/assets/docs/article/grokkingfp/haskell/part-2.md +866 -0
- package/lib/assets/docs/article/grokkingfp/haskell/part-3.md +915 -0
- package/lib/assets/docs/article/grokkingfp/haskell/part-4.md +876 -0
- package/lib/assets/docs/article/grokkingfp/haskell/part-5.md +845 -0
- package/lib/assets/docs/article/grokkingfp/haskell/part-6.md +842 -0
- package/lib/assets/docs/article/grokkingfp/index.md +143 -0
- package/lib/assets/docs/article/grokkingfp/java/index.md +211 -0
- package/lib/assets/docs/article/grokkingfp/java/part-1.md +646 -0
- package/lib/assets/docs/article/grokkingfp/java/part-2.md +667 -0
- package/lib/assets/docs/article/grokkingfp/java/part-3.md +672 -0
- package/lib/assets/docs/article/grokkingfp/java/part-4.md +771 -0
- package/lib/assets/docs/article/grokkingfp/java/part-5.md +959 -0
- package/lib/assets/docs/article/grokkingfp/java/part-6.md +1324 -0
- package/lib/assets/docs/article/grokkingfp/python/index.md +258 -0
- package/lib/assets/docs/article/grokkingfp/python/part-1.md +437 -0
- package/lib/assets/docs/article/grokkingfp/python/part-2.md +958 -0
- package/lib/assets/docs/article/grokkingfp/python/part-3.md +1004 -0
- package/lib/assets/docs/article/grokkingfp/python/part-4.md +765 -0
- package/lib/assets/docs/article/grokkingfp/python/part-5.md +747 -0
- package/lib/assets/docs/article/grokkingfp/python/part-6.md +861 -0
- package/lib/assets/docs/article/grokkingfp/ruby/index.md +330 -0
- package/lib/assets/docs/article/grokkingfp/ruby/part-1.md +753 -0
- package/lib/assets/docs/article/grokkingfp/ruby/part-2.md +938 -0
- package/lib/assets/docs/article/grokkingfp/ruby/part-3.md +946 -0
- package/lib/assets/docs/article/grokkingfp/ruby/part-4.md +921 -0
- package/lib/assets/docs/article/grokkingfp/ruby/part-5.md +908 -0
- package/lib/assets/docs/article/grokkingfp/ruby/part-6.md +1410 -0
- package/lib/assets/docs/article/grokkingfp/rust/index.md +242 -0
- package/lib/assets/docs/article/grokkingfp/rust/part-1.md +634 -0
- package/lib/assets/docs/article/grokkingfp/rust/part-2.md +1060 -0
- package/lib/assets/docs/article/grokkingfp/rust/part-3.md +994 -0
- package/lib/assets/docs/article/grokkingfp/rust/part-4.md +571 -0
- package/lib/assets/docs/article/grokkingfp/rust/part-5.md +705 -0
- package/lib/assets/docs/article/grokkingfp/rust/part-6.md +508 -0
- package/lib/assets/docs/article/grokkingfp/scala/index.md +171 -0
- package/lib/assets/docs/article/grokkingfp/scala/part-1.md +541 -0
- package/lib/assets/docs/article/grokkingfp/scala/part-2.md +946 -0
- package/lib/assets/docs/article/grokkingfp/scala/part-3.md +917 -0
- package/lib/assets/docs/article/grokkingfp/scala/part-4.md +742 -0
- package/lib/assets/docs/article/grokkingfp/scala/part-5.md +722 -0
- package/lib/assets/docs/article/grokkingfp/scala/part-6.md +865 -0
- package/lib/assets/docs/article/grokkingfp/typescript/index.md +273 -0
- package/lib/assets/docs/article/grokkingfp/typescript/part-1.md +559 -0
- package/lib/assets/docs/article/grokkingfp/typescript/part-2.md +1129 -0
- package/lib/assets/docs/article/grokkingfp/typescript/part-3.md +842 -0
- package/lib/assets/docs/article/grokkingfp/typescript/part-4.md +1085 -0
- package/lib/assets/docs/article/grokkingfp/typescript/part-5.md +717 -0
- package/lib/assets/docs/article/grokkingfp/typescript/part-6.md +980 -0
- package/lib/assets/docs/article/index.md +36 -0
- package/lib/assets/docs/design/index.md +39 -27
- package/lib/assets/docs/development/index.md +11 -1
- package/lib/assets/docs/index.md +33 -103
- package/lib/assets/docs/operation/index.md +16 -6
- package/lib/assets/docs/reference/index.md +5 -4
- package/lib/assets/docs/requirements/index.md +13 -6
- package/lib/assets/docs/review/index.md +5 -0
- package/lib/assets/docs/strategy/index.md +15 -0
- package/lib/assets/docs/template/index.md +9 -5
- package/lib/assets/mkdocs.yml +33 -19
- package/package.json +1 -1
- package/lib/assets/docs/analysis/index.md +0 -8
- /package/lib/assets/docs/{analysis → strategy}/slide/.gitkeep +0 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# 第 8 章: デザインパターンの適用
|
|
2
|
+
|
|
3
|
+
## 8.1 はじめに
|
|
4
|
+
|
|
5
|
+
前章ではカプセル化とポリモーフィズムを使って `switch` 文を排除し、タイプ別のクラス階層を構築しました。この章では、さらに **デザインパターン** を適用してコードの品質を高めていきます。
|
|
6
|
+
|
|
7
|
+
扱うパターンは以下の 5 つです。
|
|
8
|
+
|
|
9
|
+
| パターン | 目的 |
|
|
10
|
+
|---------|------|
|
|
11
|
+
| Value Object(値オブジェクト) | プリミティブ型を意味のあるオブジェクトに置換 |
|
|
12
|
+
| First-Class Collection(ファーストクラスコレクション) | コレクションをドメインオブジェクトでラップ |
|
|
13
|
+
| Factory Method(ファクトリメソッド) | オブジェクト生成ロジックを一箇所に集約 |
|
|
14
|
+
| Command(コマンド) | 操作をオブジェクトとしてカプセル化 |
|
|
15
|
+
| Null Object(ヌルオブジェクト) | null の代わりにデフォルト動作を提供 |
|
|
16
|
+
|
|
17
|
+
## 8.2 Value Object(値オブジェクト)
|
|
18
|
+
|
|
19
|
+
### 問題: プリミティブ型への執着
|
|
20
|
+
|
|
21
|
+
現在、`generate` メソッドは `String` を返しています。しかし FizzBuzz の結果には「元の数値」と「変換後の文字列」の 2 つの情報があります。`String` だけでは元の数値が失われてしまいます。
|
|
22
|
+
|
|
23
|
+
### 解決: FizzBuzzValue
|
|
24
|
+
|
|
25
|
+
数値と変換結果をペアにした **値オブジェクト** を作成します。
|
|
26
|
+
|
|
27
|
+
```java
|
|
28
|
+
import java.util.Objects;
|
|
29
|
+
|
|
30
|
+
public class FizzBuzzValue {
|
|
31
|
+
private final int number;
|
|
32
|
+
private final String value;
|
|
33
|
+
|
|
34
|
+
public FizzBuzzValue(int number, String value) {
|
|
35
|
+
this.number = number;
|
|
36
|
+
this.value = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public int getNumber() {
|
|
40
|
+
return number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public String getValue() {
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@Override
|
|
48
|
+
public String toString() {
|
|
49
|
+
return number + ":" + value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@Override
|
|
53
|
+
public boolean equals(Object obj) {
|
|
54
|
+
if (this == obj) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
if (obj == null || getClass() != obj.getClass()) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
FizzBuzzValue that = (FizzBuzzValue) obj;
|
|
61
|
+
return number == that.number
|
|
62
|
+
&& Objects.equals(value, that.value);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Override
|
|
66
|
+
public int hashCode() {
|
|
67
|
+
return Objects.hash(number, value);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Value Object の特徴
|
|
73
|
+
|
|
74
|
+
| 特徴 | 実装 |
|
|
75
|
+
|------|------|
|
|
76
|
+
| 不変(Immutable) | `final` フィールド、setter なし |
|
|
77
|
+
| 等価性(Equality) | `equals` / `hashCode` をオーバーライド |
|
|
78
|
+
| 自己記述的 | `toString` で意味のある表現 |
|
|
79
|
+
|
|
80
|
+
### FizzBuzzType の戻り値を変更
|
|
81
|
+
|
|
82
|
+
各タイプクラスの `generate` メソッドが `FizzBuzzValue` を返すように変更します。
|
|
83
|
+
|
|
84
|
+
```java
|
|
85
|
+
public abstract class FizzBuzzType {
|
|
86
|
+
// ...
|
|
87
|
+
public abstract FizzBuzzValue generate(int number);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public class FizzBuzzType01 extends FizzBuzzType {
|
|
91
|
+
@Override
|
|
92
|
+
public FizzBuzzValue generate(int number) {
|
|
93
|
+
if (isFizzBuzz(number)) {
|
|
94
|
+
return new FizzBuzzValue(number, "FizzBuzz");
|
|
95
|
+
}
|
|
96
|
+
if (isFizz(number)) {
|
|
97
|
+
return new FizzBuzzValue(number, "Fizz");
|
|
98
|
+
}
|
|
99
|
+
if (isBuzz(number)) {
|
|
100
|
+
return new FizzBuzzValue(number, "Buzz");
|
|
101
|
+
}
|
|
102
|
+
return new FizzBuzzValue(number, String.valueOf(number));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 8.3 First-Class Collection(ファーストクラスコレクション)
|
|
108
|
+
|
|
109
|
+
### 問題: 生の List
|
|
110
|
+
|
|
111
|
+
`generateList` は `List<String>` を返していますが、これではリストに対する操作(追加、検索など)がどこでも自由にできてしまいます。
|
|
112
|
+
|
|
113
|
+
### 解決: FizzBuzzList
|
|
114
|
+
|
|
115
|
+
コレクションを専用クラスでラップし、ドメインに必要な操作だけを公開します。
|
|
116
|
+
|
|
117
|
+
```java
|
|
118
|
+
import java.util.ArrayList;
|
|
119
|
+
import java.util.List;
|
|
120
|
+
import java.util.Objects;
|
|
121
|
+
|
|
122
|
+
public class FizzBuzzList {
|
|
123
|
+
private final List<FizzBuzzValue> values;
|
|
124
|
+
|
|
125
|
+
public FizzBuzzList(List<FizzBuzzValue> values) {
|
|
126
|
+
this.values = new ArrayList<>(values);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public List<FizzBuzzValue> getValues() {
|
|
130
|
+
return new ArrayList<>(values);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public FizzBuzzValue get(int index) {
|
|
134
|
+
return values.get(index);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public int size() {
|
|
138
|
+
return values.size();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public FizzBuzzList add(List<FizzBuzzValue> newValues) {
|
|
142
|
+
List<FizzBuzzValue> combined = new ArrayList<>(values);
|
|
143
|
+
combined.addAll(newValues);
|
|
144
|
+
return new FizzBuzzList(combined);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@Override
|
|
148
|
+
public String toString() {
|
|
149
|
+
return values.toString();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@Override
|
|
153
|
+
public boolean equals(Object obj) {
|
|
154
|
+
if (this == obj) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
if (obj == null || getClass() != obj.getClass()) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
FizzBuzzList that = (FizzBuzzList) obj;
|
|
161
|
+
return Objects.equals(values, that.values);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@Override
|
|
165
|
+
public int hashCode() {
|
|
166
|
+
return Objects.hash(values);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### First-Class Collection の利点
|
|
172
|
+
|
|
173
|
+
- **防御的コピー**: コンストラクタと getter で `new ArrayList<>()` を使い、外部からの変更を防ぐ
|
|
174
|
+
- **不変操作**: `add` メソッドは新しい `FizzBuzzList` を返す(元のリストは変更しない)
|
|
175
|
+
- **ドメインロジックの集約**: リストに関する操作がこのクラスに集まる
|
|
176
|
+
|
|
177
|
+
## 8.4 Factory Method(ファクトリメソッド)
|
|
178
|
+
|
|
179
|
+
### 問題: 生成ロジックの分散
|
|
180
|
+
|
|
181
|
+
現在、`FizzBuzz` クラスの `createType` メソッドでタイプコードから `FizzBuzzType` を生成しています。しかし、タイプ生成のロジックは `FizzBuzzType` 自身が知るべき責務です。
|
|
182
|
+
|
|
183
|
+
### 解決: 静的ファクトリメソッド
|
|
184
|
+
|
|
185
|
+
`FizzBuzzType` に `create` メソッドを追加します。
|
|
186
|
+
|
|
187
|
+
```java
|
|
188
|
+
public abstract class FizzBuzzType {
|
|
189
|
+
// ...
|
|
190
|
+
|
|
191
|
+
public static FizzBuzzType create(int type) {
|
|
192
|
+
switch (type) {
|
|
193
|
+
case 1:
|
|
194
|
+
return new FizzBuzzType01();
|
|
195
|
+
case 2:
|
|
196
|
+
return new FizzBuzzType02();
|
|
197
|
+
case 3:
|
|
198
|
+
return new FizzBuzzType03();
|
|
199
|
+
default:
|
|
200
|
+
throw new IllegalArgumentException(
|
|
201
|
+
"該当するタイプは存在しません");
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`FizzBuzz` クラスは `FizzBuzzType.create()` を呼ぶだけになります。
|
|
208
|
+
|
|
209
|
+
```java
|
|
210
|
+
public FizzBuzz(int typeCode) {
|
|
211
|
+
this.type = FizzBuzzType.create(typeCode);
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## 8.5 Command パターン
|
|
216
|
+
|
|
217
|
+
### 問題: 操作の種類
|
|
218
|
+
|
|
219
|
+
FizzBuzz には「1 つの数値を変換する」操作と「リストを生成する」操作があります。これらの操作を **オブジェクト** として扱うことで、柔軟に切り替えられるようにします。
|
|
220
|
+
|
|
221
|
+
### 解決: FizzBuzzCommand
|
|
222
|
+
|
|
223
|
+
```java
|
|
224
|
+
import java.util.List;
|
|
225
|
+
|
|
226
|
+
public interface FizzBuzzCommand {
|
|
227
|
+
FizzBuzzValue execute(int number);
|
|
228
|
+
FizzBuzzList executeList(int count);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### 単一値コマンド
|
|
233
|
+
|
|
234
|
+
```java
|
|
235
|
+
public class FizzBuzzValueCommand implements FizzBuzzCommand {
|
|
236
|
+
private final FizzBuzzType type;
|
|
237
|
+
|
|
238
|
+
public FizzBuzzValueCommand(FizzBuzzType type) {
|
|
239
|
+
this.type = type;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
@Override
|
|
243
|
+
public FizzBuzzValue execute(int number) {
|
|
244
|
+
return type.generate(number);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@Override
|
|
248
|
+
public FizzBuzzList executeList(int count) {
|
|
249
|
+
throw new UnsupportedOperationException();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### リスト生成コマンド
|
|
255
|
+
|
|
256
|
+
```java
|
|
257
|
+
import java.util.ArrayList;
|
|
258
|
+
import java.util.List;
|
|
259
|
+
|
|
260
|
+
public class FizzBuzzListCommand implements FizzBuzzCommand {
|
|
261
|
+
private final FizzBuzzType type;
|
|
262
|
+
|
|
263
|
+
public FizzBuzzListCommand(FizzBuzzType type) {
|
|
264
|
+
this.type = type;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
@Override
|
|
268
|
+
public FizzBuzzValue execute(int number) {
|
|
269
|
+
throw new UnsupportedOperationException();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@Override
|
|
273
|
+
public FizzBuzzList executeList(int count) {
|
|
274
|
+
List<FizzBuzzValue> values = new ArrayList<>();
|
|
275
|
+
for (int i = 1; i <= count; i++) {
|
|
276
|
+
values.add(type.generate(i));
|
|
277
|
+
}
|
|
278
|
+
return new FizzBuzzList(values);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Command パターンの利点
|
|
284
|
+
|
|
285
|
+
- **操作のカプセル化**: 実行する操作をオブジェクトとして渡せる
|
|
286
|
+
- **柔軟な組み合わせ**: タイプとコマンドを自由に組み合わせ可能
|
|
287
|
+
- **責務の分離**: 「何を変換するか」(Type)と「どう実行するか」(Command)が分離
|
|
288
|
+
|
|
289
|
+
## 8.6 Null Object パターン
|
|
290
|
+
|
|
291
|
+
### 問題: 不正なタイプの処理
|
|
292
|
+
|
|
293
|
+
現在、不正なタイプコードを指定すると `IllegalArgumentException` がスローされます。例外を投げる代わりに、**安全なデフォルト動作** を提供するアプローチもあります。
|
|
294
|
+
|
|
295
|
+
### 解決: FizzBuzzTypeNotDefined
|
|
296
|
+
|
|
297
|
+
```java
|
|
298
|
+
public class FizzBuzzTypeNotDefined extends FizzBuzzType {
|
|
299
|
+
@Override
|
|
300
|
+
public FizzBuzzValue generate(int number) {
|
|
301
|
+
return new FizzBuzzValue(number, String.valueOf(number));
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`create` メソッドで例外の代わりに `FizzBuzzTypeNotDefined` を返すこともできます。
|
|
307
|
+
|
|
308
|
+
```java
|
|
309
|
+
public static FizzBuzzType create(int type) {
|
|
310
|
+
switch (type) {
|
|
311
|
+
case 1:
|
|
312
|
+
return new FizzBuzzType01();
|
|
313
|
+
case 2:
|
|
314
|
+
return new FizzBuzzType02();
|
|
315
|
+
case 3:
|
|
316
|
+
return new FizzBuzzType03();
|
|
317
|
+
default:
|
|
318
|
+
return new FizzBuzzTypeNotDefined();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
> **注**: 本プロジェクトでは不正なタイプを早期に検出するため、例外スローを維持します。Null Object パターンは「例外よりも安全なデフォルト動作が適切な場合」に使用します。
|
|
324
|
+
|
|
325
|
+
## 8.7 リファクタリング後のクラス構造
|
|
326
|
+
|
|
327
|
+
```plantuml
|
|
328
|
+
@startuml
|
|
329
|
+
title FizzBuzz クラス構造(第 8 章完了時点)
|
|
330
|
+
|
|
331
|
+
abstract class FizzBuzzType {
|
|
332
|
+
+ {abstract} generate(number : int) : FizzBuzzValue
|
|
333
|
+
+ {static} create(type : int) : FizzBuzzType
|
|
334
|
+
# isFizz(number : int) : boolean
|
|
335
|
+
# isBuzz(number : int) : boolean
|
|
336
|
+
# isFizzBuzz(number : int) : boolean
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
class FizzBuzzType01 extends FizzBuzzType
|
|
340
|
+
class FizzBuzzType02 extends FizzBuzzType
|
|
341
|
+
class FizzBuzzType03 extends FizzBuzzType
|
|
342
|
+
|
|
343
|
+
class FizzBuzzValue {
|
|
344
|
+
- number : int
|
|
345
|
+
- value : String
|
|
346
|
+
+ getNumber() : int
|
|
347
|
+
+ getValue() : String
|
|
348
|
+
+ equals(obj : Object) : boolean
|
|
349
|
+
+ hashCode() : int
|
|
350
|
+
+ toString() : String
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
class FizzBuzzList {
|
|
354
|
+
- values : List<FizzBuzzValue>
|
|
355
|
+
+ get(index : int) : FizzBuzzValue
|
|
356
|
+
+ size() : int
|
|
357
|
+
+ add(newValues : List) : FizzBuzzList
|
|
358
|
+
+ getValues() : List<FizzBuzzValue>
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
interface FizzBuzzCommand {
|
|
362
|
+
+ execute(number : int) : FizzBuzzValue
|
|
363
|
+
+ executeList(count : int) : FizzBuzzList
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
class FizzBuzzValueCommand implements FizzBuzzCommand
|
|
367
|
+
class FizzBuzzListCommand implements FizzBuzzCommand
|
|
368
|
+
|
|
369
|
+
FizzBuzzType ..> FizzBuzzValue : 生成
|
|
370
|
+
FizzBuzzList o-- FizzBuzzValue
|
|
371
|
+
FizzBuzzValueCommand --> FizzBuzzType
|
|
372
|
+
FizzBuzzListCommand --> FizzBuzzType
|
|
373
|
+
|
|
374
|
+
@enduml
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## 8.8 まとめ
|
|
378
|
+
|
|
379
|
+
この章では 5 つのデザインパターンを適用しました。
|
|
380
|
+
|
|
381
|
+
| パターン | クラス | 効果 |
|
|
382
|
+
|---------|--------|------|
|
|
383
|
+
| Value Object | `FizzBuzzValue` | プリミティブ型への執着を排除 |
|
|
384
|
+
| First-Class Collection | `FizzBuzzList` | コレクション操作をドメインに集約 |
|
|
385
|
+
| Factory Method | `FizzBuzzType.create()` | 生成ロジックを一箇所に集約 |
|
|
386
|
+
| Command | `FizzBuzzCommand` 階層 | 操作をオブジェクトとしてカプセル化 |
|
|
387
|
+
| Null Object | `FizzBuzzTypeNotDefined` | null/例外の代わりに安全なデフォルト |
|
|
388
|
+
|
|
389
|
+
### リファクタリングの原則
|
|
390
|
+
|
|
391
|
+
> **プリミティブ型への執着**(Primitive Obsession)を避け、ドメインの概念をオブジェクトで表現する。
|
|
392
|
+
|
|
393
|
+
次の第 9 章では、SOLID 原則に基づいてモジュール設計を行い、パッケージ構造を整理します。
|
package/lib/assets/docs/article/getting-start-tdd/java/09-solid-principles-and-module-design.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# 第 9 章: SOLID 原則とモジュール設計
|
|
2
|
+
|
|
3
|
+
## 9.1 はじめに
|
|
4
|
+
|
|
5
|
+
前章までで、FizzBuzz のコードはデザインパターンを適用して大きく改善されました。しかし、すべてのクラスが `tdd.fizzbuzz` という 1 つのパッケージに詰め込まれています。
|
|
6
|
+
|
|
7
|
+
この章では、**SOLID 原則** を確認しながら、クラスを適切なパッケージに分割する **モジュール設計** を行います。
|
|
8
|
+
|
|
9
|
+
## 9.2 SOLID 原則の確認
|
|
10
|
+
|
|
11
|
+
FizzBuzz のコードが SOLID 原則にどの程度準拠しているか確認しましょう。
|
|
12
|
+
|
|
13
|
+
### 単一責任原則(SRP: Single Responsibility Principle)
|
|
14
|
+
|
|
15
|
+
> クラスを変更する理由は 1 つだけであるべき。
|
|
16
|
+
|
|
17
|
+
| クラス | 責務 | 変更理由 | SRP 準拠 |
|
|
18
|
+
|--------|------|---------|---------|
|
|
19
|
+
| `FizzBuzzType01` | タイプ 1 の変換ルール | タイプ 1 のルール変更時 | OK |
|
|
20
|
+
| `FizzBuzzType02` | タイプ 2 の変換ルール | タイプ 2 のルール変更時 | OK |
|
|
21
|
+
| `FizzBuzzType03` | タイプ 3 の変換ルール | タイプ 3 のルール変更時 | OK |
|
|
22
|
+
| `FizzBuzzValue` | 値の保持と等価性 | 値の表現が変わるとき | OK |
|
|
23
|
+
| `FizzBuzzList` | コレクション操作 | コレクション操作が変わるとき | OK |
|
|
24
|
+
| `FizzBuzzValueCommand` | 単一値変換の実行 | 実行方法が変わるとき | OK |
|
|
25
|
+
| `FizzBuzzListCommand` | リスト生成の実行 | 実行方法が変わるとき | OK |
|
|
26
|
+
|
|
27
|
+
ポリモーフィズムとデザインパターンの適用により、各クラスが単一の責務を持つようになっています。
|
|
28
|
+
|
|
29
|
+
### 開放閉鎖原則(OCP: Open-Closed Principle)
|
|
30
|
+
|
|
31
|
+
> 拡張に対して開いていて、修正に対して閉じているべき。
|
|
32
|
+
|
|
33
|
+
新しいタイプ(例: タイプ 4)を追加する場合を考えてみましょう。
|
|
34
|
+
|
|
35
|
+
```java
|
|
36
|
+
// タイプ 4 を追加するのに必要な変更
|
|
37
|
+
// 1. 新しいクラスを追加(既存コードの修正なし)
|
|
38
|
+
public class FizzBuzzType04 extends FizzBuzzType {
|
|
39
|
+
@Override
|
|
40
|
+
public FizzBuzzValue generate(int number) {
|
|
41
|
+
// タイプ 4 のルール
|
|
42
|
+
return new FizzBuzzValue(number, String.valueOf(number));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 2. ファクトリメソッドに 1 行追加(最小限の修正)
|
|
47
|
+
case 4: return new FizzBuzzType04();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`FizzBuzzType` 階層は拡張に対して開いています。新しいタイプを追加しても、既存のタイプクラスや `FizzBuzzCommand` を修正する必要はありません。
|
|
51
|
+
|
|
52
|
+
### 依存性逆転原則(DIP: Dependency Inversion Principle)
|
|
53
|
+
|
|
54
|
+
> 上位モジュールは下位モジュールに依存すべきではない。どちらも抽象に依存すべき。
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
FizzBuzz → FizzBuzzType(抽象)← FizzBuzzType01, 02, 03
|
|
58
|
+
FizzBuzzCommand(抽象)← FizzBuzzValueCommand, FizzBuzzListCommand
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`FizzBuzz` クラスは具体的な `FizzBuzzType01` ではなく、抽象的な `FizzBuzzType` に依存しています。
|
|
62
|
+
|
|
63
|
+
## 9.3 パッケージ設計
|
|
64
|
+
|
|
65
|
+
### 現在の問題
|
|
66
|
+
|
|
67
|
+
すべてのクラスが `tdd.fizzbuzz` に入っています。
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
tdd.fizzbuzz/
|
|
71
|
+
├── FizzBuzz.java
|
|
72
|
+
├── FizzBuzzType.java
|
|
73
|
+
├── FizzBuzzType01.java
|
|
74
|
+
├── FizzBuzzType02.java
|
|
75
|
+
├── FizzBuzzType03.java
|
|
76
|
+
├── FizzBuzzValue.java
|
|
77
|
+
├── FizzBuzzList.java
|
|
78
|
+
├── FizzBuzzCommand.java
|
|
79
|
+
├── FizzBuzzValueCommand.java
|
|
80
|
+
├── FizzBuzzListCommand.java
|
|
81
|
+
└── Main.java
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
クラスが増えるにつれて、どのクラスがどの責務を持つかが分かりにくくなります。
|
|
85
|
+
|
|
86
|
+
### パッケージ分割
|
|
87
|
+
|
|
88
|
+
責務に基づいてパッケージを分割します。
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
tdd/
|
|
92
|
+
├── App.java # エントリポイント
|
|
93
|
+
└── fizzbuzz/
|
|
94
|
+
├── domain/
|
|
95
|
+
│ ├── type/
|
|
96
|
+
│ │ ├── FizzBuzzType.java # 抽象タイプ + Factory
|
|
97
|
+
│ │ ├── FizzBuzzType01.java # タイプ 1
|
|
98
|
+
│ │ ├── FizzBuzzType02.java # タイプ 2
|
|
99
|
+
│ │ └── FizzBuzzType03.java # タイプ 3
|
|
100
|
+
│ └── model/
|
|
101
|
+
│ ├── FizzBuzzValue.java # 値オブジェクト
|
|
102
|
+
│ └── FizzBuzzList.java # コレクション
|
|
103
|
+
└── application/
|
|
104
|
+
├── FizzBuzzCommand.java # コマンドインターフェース
|
|
105
|
+
├── FizzBuzzValueCommand.java # 単一値コマンド
|
|
106
|
+
└── FizzBuzzListCommand.java # リストコマンド
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### パッケージの責務
|
|
110
|
+
|
|
111
|
+
| パッケージ | 責務 | 含まれるクラス |
|
|
112
|
+
|-----------|------|--------------|
|
|
113
|
+
| `tdd.fizzbuzz.domain.type` | 変換ルール(ビジネスロジック) | `FizzBuzzType` 階層 |
|
|
114
|
+
| `tdd.fizzbuzz.domain.model` | ドメインモデル(値・コレクション) | `FizzBuzzValue`, `FizzBuzzList` |
|
|
115
|
+
| `tdd.fizzbuzz.application` | アプリケーション層(操作の実行) | `FizzBuzzCommand` 階層 |
|
|
116
|
+
|
|
117
|
+
### 依存関係
|
|
118
|
+
|
|
119
|
+
```plantuml
|
|
120
|
+
@startuml
|
|
121
|
+
title パッケージ依存関係
|
|
122
|
+
|
|
123
|
+
package "tdd" {
|
|
124
|
+
class App
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
package "tdd.fizzbuzz.application" {
|
|
128
|
+
interface FizzBuzzCommand
|
|
129
|
+
class FizzBuzzValueCommand
|
|
130
|
+
class FizzBuzzListCommand
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
package "tdd.fizzbuzz.domain.type" {
|
|
134
|
+
abstract class FizzBuzzType
|
|
135
|
+
class FizzBuzzType01
|
|
136
|
+
class FizzBuzzType02
|
|
137
|
+
class FizzBuzzType03
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
package "tdd.fizzbuzz.domain.model" {
|
|
141
|
+
class FizzBuzzValue
|
|
142
|
+
class FizzBuzzList
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
App --> FizzBuzzCommand
|
|
146
|
+
App --> FizzBuzzType
|
|
147
|
+
|
|
148
|
+
FizzBuzzValueCommand --> FizzBuzzType
|
|
149
|
+
FizzBuzzListCommand --> FizzBuzzType
|
|
150
|
+
FizzBuzzListCommand --> FizzBuzzList
|
|
151
|
+
|
|
152
|
+
FizzBuzzType ..> FizzBuzzValue : 生成
|
|
153
|
+
FizzBuzzList o-- FizzBuzzValue
|
|
154
|
+
|
|
155
|
+
@enduml
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`application` パッケージは `domain` に依存しますが、`domain` は `application` に依存しません。これにより、ビジネスロジックがアプリケーション層から独立して変更・テストできます。
|
|
159
|
+
|
|
160
|
+
## 9.4 エントリポイントの更新
|
|
161
|
+
|
|
162
|
+
パッケージ分割後の `App.java` です。
|
|
163
|
+
|
|
164
|
+
```java
|
|
165
|
+
package tdd;
|
|
166
|
+
|
|
167
|
+
import tdd.fizzbuzz.application.FizzBuzzListCommand;
|
|
168
|
+
import tdd.fizzbuzz.application.FizzBuzzValueCommand;
|
|
169
|
+
import tdd.fizzbuzz.domain.model.FizzBuzzList;
|
|
170
|
+
import tdd.fizzbuzz.domain.model.FizzBuzzValue;
|
|
171
|
+
import tdd.fizzbuzz.domain.type.FizzBuzzType;
|
|
172
|
+
|
|
173
|
+
public class App {
|
|
174
|
+
private static final int MAX_NUMBER = 100;
|
|
175
|
+
|
|
176
|
+
public static void main(String[] args) {
|
|
177
|
+
FizzBuzzType type = FizzBuzzType.create(1);
|
|
178
|
+
|
|
179
|
+
// 単一値の取得
|
|
180
|
+
FizzBuzzValueCommand valueCommand
|
|
181
|
+
= new FizzBuzzValueCommand(type);
|
|
182
|
+
FizzBuzzValue value = valueCommand.execute(15);
|
|
183
|
+
System.out.println(value);
|
|
184
|
+
|
|
185
|
+
// リストの生成
|
|
186
|
+
FizzBuzzListCommand listCommand
|
|
187
|
+
= new FizzBuzzListCommand(type);
|
|
188
|
+
FizzBuzzList list = listCommand.executeList(MAX_NUMBER);
|
|
189
|
+
for (FizzBuzzValue item : list.getValues()) {
|
|
190
|
+
System.out.println(item.getValue());
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## 9.5 テストの更新
|
|
197
|
+
|
|
198
|
+
テストもパッケージ構造に合わせて再配置します。
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
src/test/java/tdd/fizzbuzz/
|
|
202
|
+
├── domain/
|
|
203
|
+
│ ├── type/
|
|
204
|
+
│ │ └── FizzBuzzTypeTest.java # タイプ別テスト
|
|
205
|
+
│ └── model/
|
|
206
|
+
│ ├── FizzBuzzValueTest.java # 値オブジェクトテスト
|
|
207
|
+
│ └── FizzBuzzListTest.java # コレクションテスト
|
|
208
|
+
└── application/
|
|
209
|
+
└── FizzBuzzCommandTest.java # コマンドテスト
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### FizzBuzzTypeTest(タイプ別テスト)
|
|
213
|
+
|
|
214
|
+
```java
|
|
215
|
+
package tdd.fizzbuzz.domain.type;
|
|
216
|
+
|
|
217
|
+
import org.junit.jupiter.api.Nested;
|
|
218
|
+
import org.junit.jupiter.api.Test;
|
|
219
|
+
|
|
220
|
+
import static org.junit.jupiter.api.Assertions.*;
|
|
221
|
+
|
|
222
|
+
class FizzBuzzTypeTest {
|
|
223
|
+
|
|
224
|
+
@Nested
|
|
225
|
+
class タイプ1の場合 {
|
|
226
|
+
private final FizzBuzzType type = FizzBuzzType.create(1);
|
|
227
|
+
|
|
228
|
+
@Test
|
|
229
|
+
void 三と五の倍数でFizzBuzzを返す() {
|
|
230
|
+
assertEquals("FizzBuzz", type.generate(15).getValue());
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@Test
|
|
234
|
+
void 三の倍数でFizzを返す() {
|
|
235
|
+
assertEquals("Fizz", type.generate(3).getValue());
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@Test
|
|
239
|
+
void 五の倍数でBuzzを返す() {
|
|
240
|
+
assertEquals("Buzz", type.generate(5).getValue());
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@Test
|
|
244
|
+
void その他は数値を返す() {
|
|
245
|
+
assertEquals("1", type.generate(1).getValue());
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@Nested
|
|
250
|
+
class タイプ2の場合 {
|
|
251
|
+
private final FizzBuzzType type = FizzBuzzType.create(2);
|
|
252
|
+
|
|
253
|
+
@Test
|
|
254
|
+
void 常に数値を返す() {
|
|
255
|
+
assertEquals("3", type.generate(3).getValue());
|
|
256
|
+
assertEquals("5", type.generate(5).getValue());
|
|
257
|
+
assertEquals("15", type.generate(15).getValue());
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@Nested
|
|
262
|
+
class タイプ3の場合 {
|
|
263
|
+
private final FizzBuzzType type = FizzBuzzType.create(3);
|
|
264
|
+
|
|
265
|
+
@Test
|
|
266
|
+
void 十五の倍数のみFizzBuzzを返す() {
|
|
267
|
+
assertEquals("FizzBuzz", type.generate(15).getValue());
|
|
268
|
+
assertEquals("3", type.generate(3).getValue());
|
|
269
|
+
assertEquals("5", type.generate(5).getValue());
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@Nested
|
|
274
|
+
class 不正なタイプの場合 {
|
|
275
|
+
@Test
|
|
276
|
+
void 例外をスローする() {
|
|
277
|
+
assertThrows(IllegalArgumentException.class,
|
|
278
|
+
() -> FizzBuzzType.create(4));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## 9.6 まとめ
|
|
285
|
+
|
|
286
|
+
この章では SOLID 原則を確認しながらモジュール設計を行いました。
|
|
287
|
+
|
|
288
|
+
| 概念 | 適用 |
|
|
289
|
+
|------|------|
|
|
290
|
+
| 単一責任原則(SRP) | 各クラスが 1 つの責務を持つ |
|
|
291
|
+
| 開放閉鎖原則(OCP) | 新タイプ追加で既存コード変更不要 |
|
|
292
|
+
| 依存性逆転原則(DIP) | 抽象への依存で結合度を低減 |
|
|
293
|
+
| パッケージ分割 | `domain`(ビジネスロジック)と `application`(操作)の分離 |
|
|
294
|
+
|
|
295
|
+
### 第 3 部の振り返り
|
|
296
|
+
|
|
297
|
+
第 3 部(第 7〜9 章)を通じて、手続き的な FizzBuzz をオブジェクト指向設計に変換しました。
|
|
298
|
+
|
|
299
|
+
| 章 | テーマ | 学んだこと |
|
|
300
|
+
|----|--------|-----------
|
|
301
|
+
| 7 | カプセル化とポリモーフィズム | `private` / `final`、Strategy パターン、抽象クラス |
|
|
302
|
+
| 8 | デザインパターンの適用 | Value Object、First-Class Collection、Command、Factory Method |
|
|
303
|
+
| 9 | SOLID 原則とモジュール設計 | SRP / OCP / DIP、パッケージ分割、ドメインモデル |
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
Before: 1 つのクラスに全ロジック(手続き型)
|
|
307
|
+
After: 責務ごとにパッケージ分割された OOP 設計
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
次の第 4 部では、Java の関数型プログラミング機能(Stream API、Optional、Lambda)を使って、さらにコードを発展させます。
|