@k2works/claude-code-booster 3.0.0 → 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 -106
- 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/strategy/index.md +11 -4
- package/lib/assets/docs/template/index.md +9 -5
- package/lib/assets/mkdocs.yml +29 -17
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# 第 5 章: パッケージ管理と静的解析
|
|
2
|
+
|
|
3
|
+
## 5.1 はじめに
|
|
4
|
+
|
|
5
|
+
この章では、Elixir の依存管理とコード品質チェックを扱います。`Mix`、`Hex`、`Credo`、`mix format`、複雑度チェックを組み合わせ、TDD の継続速度と品質を両立します。
|
|
6
|
+
|
|
7
|
+
## 5.2 Mix による依存管理
|
|
8
|
+
|
|
9
|
+
Elixir の依存関係は `mix.exs` の `deps/0` で定義します。
|
|
10
|
+
|
|
11
|
+
```elixir
|
|
12
|
+
# apps/elixir/mix.exs
|
|
13
|
+
|
|
14
|
+
defp deps do
|
|
15
|
+
[
|
|
16
|
+
{:credo, "~> 1.7", only: [:dev, :test], runtime: false}
|
|
17
|
+
]
|
|
18
|
+
end
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
依存追加後は `mix deps.get` で取得します。
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cd apps/elixir
|
|
25
|
+
mix deps.get
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`only: [:dev, :test]` を使うと、開発時だけ必要なツール依存を本番実行から分離できます。
|
|
29
|
+
|
|
30
|
+
## 5.3 Hex パッケージマネージャ
|
|
31
|
+
|
|
32
|
+
`Hex` は Elixir の公式パッケージレジストリです。`mix deps.get` は `Hex` から依存を解決し、`mix.lock` にバージョンを固定します。
|
|
33
|
+
|
|
34
|
+
日常的に使う操作は次のとおりです。
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
mix deps.get # 依存取得
|
|
38
|
+
mix deps.update all # 依存更新
|
|
39
|
+
mix deps.tree # 依存ツリー確認
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
チーム開発では `mix.lock` をコミットし、依存の再現性を確保します。
|
|
43
|
+
|
|
44
|
+
## 5.4 Credo による静的解析
|
|
45
|
+
|
|
46
|
+
`Credo` は Elixir の静的解析ツールです。本プロジェクトでは厳格モードを使います。
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
mix credo --strict
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`--strict` は警告を増やし、早い段階で設計上の問題や可読性低下を検出できます。`apps/elixir/Makefile` でも `lint` タスクとして定義されています。
|
|
53
|
+
|
|
54
|
+
## 5.5 mix format と .formatter.exs
|
|
55
|
+
|
|
56
|
+
コードフォーマットは `mix format` で統一します。
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
mix format
|
|
60
|
+
mix format --check-formatted
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`apps/elixir/.formatter.exs` では対象ファイルを次のように設定しています。
|
|
64
|
+
|
|
65
|
+
```elixir
|
|
66
|
+
[
|
|
67
|
+
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
|
68
|
+
]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
CI では `--check-formatted` を使い、未整形コードの混入を防ぎます。
|
|
72
|
+
|
|
73
|
+
## 5.6 コード複雑度チェック
|
|
74
|
+
|
|
75
|
+
本プロジェクトでは `scripts/complexity.sh` で循環複雑度を簡易計測します。
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
bash scripts/complexity.sh --threshold 10 lib
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- `--threshold 10`: 閾値を 10 に設定
|
|
82
|
+
- `lib`: チェック対象ディレクトリ
|
|
83
|
+
|
|
84
|
+
このチェックを `make complexity` や CI に組み込むことで、関数の肥大化を継続的に抑制できます。
|
|
85
|
+
|
|
86
|
+
## 5.7 まとめ
|
|
87
|
+
|
|
88
|
+
この章では、`mix.exs` の `deps` を起点にした依存管理、`Hex` によるパッケージ解決、`Credo` と `mix format` による静的品質担保、`scripts/complexity.sh` による複雑度管理を確認しました。次章では、これらを `Makefile` と CI/CD に統合します。
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# 第 6 章: タスクランナーと CI/CD
|
|
2
|
+
|
|
3
|
+
## 6.1 はじめに
|
|
4
|
+
|
|
5
|
+
この章では、ローカル開発と CI を同じ実行基盤でそろえる方法を扱います。Nix で環境差分を吸収し、`Makefile` と GitHub Actions で品質チェックを自動化します。
|
|
6
|
+
|
|
7
|
+
## 6.2 Nix 開発環境による環境管理
|
|
8
|
+
|
|
9
|
+
本プロジェクトの Elixir 開発環境は Nix で提供されています。次のコマンドで同一ツールチェーンに入れます。
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
nix develop .#elixir
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
この方式により、OS 差分やローカルの手動セットアップ差分を最小化できます。CI でも同じ `nix develop .#elixir` を使うため、ローカル再現性が高くなります。
|
|
16
|
+
|
|
17
|
+
## 6.3 Makefile でのタスク管理
|
|
18
|
+
|
|
19
|
+
`apps/elixir/Makefile` には主要タスクが定義されています。
|
|
20
|
+
|
|
21
|
+
- `make test`: `mix test`
|
|
22
|
+
- `make fmt`: `mix format`
|
|
23
|
+
- `make fmt-check`: `mix format --check-formatted`
|
|
24
|
+
- `make lint`: `mix credo --strict`
|
|
25
|
+
- `make complexity`: `bash scripts/complexity.sh --threshold 10 lib`
|
|
26
|
+
- `make check`: `fmt-check` + `lint` + `complexity` + `test`
|
|
27
|
+
|
|
28
|
+
開発中は `make check` を最終ゲートにすると、レビュー前の品質をそろえやすくなります。
|
|
29
|
+
|
|
30
|
+
## 6.4 mix の監視実行と高速テスト
|
|
31
|
+
|
|
32
|
+
Elixir ではファイル更新検知に Linux 固有の `inotify-tools` は不要です。継続実行したい場合は監視実行を利用します。
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
mix test --watch
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
また、変更影響のあるテストだけを優先して回すには `--stale` が有効です。
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
mix test --stale
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- `--watch`: 保存ごとに再実行
|
|
45
|
+
- `--stale`: 変更があったモジュールに関連するテスト中心で実行
|
|
46
|
+
|
|
47
|
+
日常開発は `mix test --stale`、節目では `mix test` や `make check` を回す運用が実践的です。
|
|
48
|
+
|
|
49
|
+
## 6.5 GitHub Actions での Nix ベース CI/CD
|
|
50
|
+
|
|
51
|
+
Elixir 用 CI は最初から Nix ベースで構築されています。`.github/workflows/elixir-ci.yml` では次の流れを実行します。
|
|
52
|
+
|
|
53
|
+
1. `actions/checkout@v4`
|
|
54
|
+
2. `cachix/install-nix-action@v30` で Nix を導入
|
|
55
|
+
3. `nix develop .#elixir --command ...` で依存取得・Format・Lint・複雑度・テストを実行
|
|
56
|
+
|
|
57
|
+
例:
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
- name: Install Nix
|
|
61
|
+
uses: cachix/install-nix-action@v30
|
|
62
|
+
|
|
63
|
+
- name: Run tests
|
|
64
|
+
run: nix develop .#elixir --command bash -c "cd apps/elixir && mix test"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
重要なのは、ローカルと CI が同じ `nix develop` を起点にしている点です。これにより「ローカルでは通るが CI で失敗する」を減らせます。
|
|
68
|
+
|
|
69
|
+
## 6.6 まとめ
|
|
70
|
+
|
|
71
|
+
この章では、`nix develop .#elixir` による環境統一、`Makefile` によるタスク標準化、`mix test --watch` / `mix test --stale` の使い分け、GitHub Actions の Nix ベース CI を確認しました。これで TDD の反復を壊さない自動化基盤が整います。
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# 第 7 章: 構造体とプロトコルによるポリモーフィズム
|
|
2
|
+
|
|
3
|
+
## 7.1 はじめに
|
|
4
|
+
|
|
5
|
+
この章では、`defstruct` と `defprotocol` を使って、Elixir で型ごとに振る舞いを切り替える方法を学びます。FizzBuzz の値オブジェクトを導入し、`Type01`、`Type02`、`Type03` が同じインターフェース `generate/1` を実装する形でポリモーフィズムを実現します。
|
|
6
|
+
|
|
7
|
+
## 7.2 defstruct で値オブジェクトを定義する
|
|
8
|
+
|
|
9
|
+
FizzBuzz の入力値を表す値オブジェクト `FizzBuzz.Model.Value` を定義します。`@enforce_keys` で必須フィールドを宣言すると、不完全な構造体生成を防げます。
|
|
10
|
+
|
|
11
|
+
```elixir
|
|
12
|
+
defmodule FizzBuzz.Model.Value do
|
|
13
|
+
@enforce_keys [:number]
|
|
14
|
+
defstruct [:number]
|
|
15
|
+
|
|
16
|
+
@type t :: %__MODULE__{
|
|
17
|
+
number: pos_integer()
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`@enforce_keys [:number]` により、`%FizzBuzz.Model.Value{}` のような生成は実行時エラーになり、`number` の設定漏れを早期に検出できます。
|
|
23
|
+
|
|
24
|
+
## 7.3 defprotocol で共通インターフェースを定義する
|
|
25
|
+
|
|
26
|
+
次に、生成処理の共通契約として `Generatable` プロトコルを定義します。
|
|
27
|
+
|
|
28
|
+
```elixir
|
|
29
|
+
defprotocol FizzBuzz.Generatable do
|
|
30
|
+
@spec generate(t()) :: String.t()
|
|
31
|
+
def generate(value)
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
プロトコルは「どの型であっても `generate/1` を呼べる」という抽象化を提供します。実際の処理は各構造体の `defimpl` で分岐します。
|
|
36
|
+
|
|
37
|
+
## 7.4 defimpl で Type01 / Type02 / Type03 を実装する
|
|
38
|
+
|
|
39
|
+
`Type01`、`Type02`、`Type03` は、それぞれ通常数値、3 の倍数、5 の倍数を表す構造体とします。
|
|
40
|
+
|
|
41
|
+
```elixir
|
|
42
|
+
defmodule FizzBuzz.Model.Type01 do
|
|
43
|
+
@enforce_keys [:value]
|
|
44
|
+
defstruct [:value]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
defmodule FizzBuzz.Model.Type02 do
|
|
48
|
+
@enforce_keys [:value]
|
|
49
|
+
defstruct [:value]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
defmodule FizzBuzz.Model.Type03 do
|
|
53
|
+
@enforce_keys [:value]
|
|
54
|
+
defstruct [:value]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
defimpl FizzBuzz.Generatable, for: FizzBuzz.Model.Type01 do
|
|
58
|
+
def generate(%FizzBuzz.Model.Type01{value: value}), do: Integer.to_string(value.number)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
defimpl FizzBuzz.Generatable, for: FizzBuzz.Model.Type02 do
|
|
62
|
+
def generate(%FizzBuzz.Model.Type02{}), do: "Fizz"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
defimpl FizzBuzz.Generatable, for: FizzBuzz.Model.Type03 do
|
|
66
|
+
def generate(%FizzBuzz.Model.Type03{}), do: "Buzz"
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
この設計では、呼び出し側は具体型を意識せず、`FizzBuzz.Generatable.generate/1` だけを呼べばよくなります。
|
|
71
|
+
|
|
72
|
+
## 7.5 ExUnit でプロトコル実装を検証する
|
|
73
|
+
|
|
74
|
+
プロトコルの振る舞いは ExUnit で確認できます。
|
|
75
|
+
|
|
76
|
+
```elixir
|
|
77
|
+
defmodule FizzBuzz.GeneratableTest do
|
|
78
|
+
use ExUnit.Case, async: true
|
|
79
|
+
|
|
80
|
+
alias FizzBuzz.Generatable
|
|
81
|
+
alias FizzBuzz.Model.{Type01, Type02, Type03, Value}
|
|
82
|
+
|
|
83
|
+
test "Type01 は数値文字列を返す" do
|
|
84
|
+
value = %Value{number: 1}
|
|
85
|
+
assert Generatable.generate(%Type01{value: value}) == "1"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
test "Type02 は Fizz を返す" do
|
|
89
|
+
value = %Value{number: 3}
|
|
90
|
+
assert Generatable.generate(%Type02{value: value}) == "Fizz"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
test "Type03 は Buzz を返す" do
|
|
94
|
+
value = %Value{number: 5}
|
|
95
|
+
assert Generatable.generate(%Type03{value: value}) == "Buzz"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
test "Value は number が必須" do
|
|
99
|
+
assert_raise ArgumentError, fn ->
|
|
100
|
+
struct!(Value, %{})
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`struct!/2` を使うと、`@enforce_keys` の違反をテストで明示的に確認できます。
|
|
107
|
+
|
|
108
|
+
## 7.6 まとめ
|
|
109
|
+
|
|
110
|
+
この章では、`defstruct` と `@enforce_keys` で値オブジェクトを定義し、`defprotocol` / `defimpl` で型ごとに `generate/1` を実装しました。Elixir では継承ではなく、プロトコルでポリモーフィズムを組み立てるのが実践的です。
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# 第 8 章: パターンマッチとガード節
|
|
2
|
+
|
|
3
|
+
## 8.1 はじめに
|
|
4
|
+
|
|
5
|
+
この章では、Elixir の分岐を読みやすく保つために、関数頭部のパターンマッチ、`when` ガード節、`case` と `cond` の使い分けを整理します。あわせて、タグ付きタプル `{:ok, value}` / `{:error, reason}` による結果表現も確認します。
|
|
6
|
+
|
|
7
|
+
## 8.2 関数頭部でのパターンマッチ
|
|
8
|
+
|
|
9
|
+
Elixir では値ごとの分岐を関数定義に直接書けます。
|
|
10
|
+
|
|
11
|
+
```elixir
|
|
12
|
+
defmodule FizzBuzz.Factory do
|
|
13
|
+
alias FizzBuzz.Model.{Type01, Type02, Type03, Value}
|
|
14
|
+
|
|
15
|
+
def create(1), do: %Type01{value: %Value{number: 1}}
|
|
16
|
+
def create(2), do: %Type01{value: %Value{number: 2}}
|
|
17
|
+
def create(3), do: %Type02{value: %Value{number: 3}}
|
|
18
|
+
def create(5), do: %Type03{value: %Value{number: 5}}
|
|
19
|
+
def create(_), do: :unsupported
|
|
20
|
+
end
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`def create(1)`、`def create(2)`、`def create(_)` のように書くと、`if` より宣言的で見通しがよくなります。
|
|
24
|
+
|
|
25
|
+
## 8.3 ガード節で入力条件を制約する
|
|
26
|
+
|
|
27
|
+
パターンだけで不足する条件は `when` を使います。
|
|
28
|
+
|
|
29
|
+
```elixir
|
|
30
|
+
defmodule FizzBuzz.Validator do
|
|
31
|
+
def validate(number) when is_integer(number) and number > 0, do: {:ok, number}
|
|
32
|
+
def validate(number) when is_integer(number), do: {:error, :non_positive}
|
|
33
|
+
def validate(_), do: {:error, :not_integer}
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`when is_integer(number) and number > 0` により、正常系の条件を関数シグネチャ近くで明示できます。
|
|
38
|
+
|
|
39
|
+
## 8.4 case 式と cond 式の使い分け
|
|
40
|
+
|
|
41
|
+
`case` は「値の形」を分岐するときに向いており、`cond` は「複数の真偽条件」を評価するときに向いています。
|
|
42
|
+
|
|
43
|
+
```elixir
|
|
44
|
+
defmodule FizzBuzz.Renderer do
|
|
45
|
+
def from_result(result) do
|
|
46
|
+
case result do
|
|
47
|
+
{:ok, value} -> "ok: #{value}"
|
|
48
|
+
{:error, reason} -> "error: #{reason}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def classify(number) do
|
|
53
|
+
cond do
|
|
54
|
+
rem(number, 15) == 0 -> :fizz_buzz
|
|
55
|
+
rem(number, 3) == 0 -> :fizz
|
|
56
|
+
rem(number, 5) == 0 -> :buzz
|
|
57
|
+
true -> :number
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- `case`: `{:ok, value}` のようなタグ付きデータを分解する。
|
|
64
|
+
- `cond`: `rem/2` の結果など条件式を上から順に判定する。
|
|
65
|
+
|
|
66
|
+
## 8.5 ExUnit で分岐をテストする
|
|
67
|
+
|
|
68
|
+
分岐ロジックは仕様が崩れやすいため、タグ付きタプルまで含めてテストします。
|
|
69
|
+
|
|
70
|
+
```elixir
|
|
71
|
+
defmodule FizzBuzz.PatternMatchingTest do
|
|
72
|
+
use ExUnit.Case, async: true
|
|
73
|
+
|
|
74
|
+
alias FizzBuzz.Factory
|
|
75
|
+
alias FizzBuzz.Renderer
|
|
76
|
+
alias FizzBuzz.Validator
|
|
77
|
+
alias FizzBuzz.Model.Type02
|
|
78
|
+
|
|
79
|
+
test "create/1 は 3 を Type02 として生成する" do
|
|
80
|
+
assert %Type02{} = Factory.create(3)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
test "validate/1 は正の整数を {:ok, value} で返す" do
|
|
84
|
+
assert Validator.validate(10) == {:ok, 10}
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
test "validate/1 は不正な入力を {:error, reason} で返す" do
|
|
88
|
+
assert Validator.validate(0) == {:error, :non_positive}
|
|
89
|
+
assert Validator.validate("10") == {:error, :not_integer}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
test "from_result/1 はタグ付きタプルを文字列化する" do
|
|
93
|
+
assert Renderer.from_result({:ok, "Fizz"}) == "ok: Fizz"
|
|
94
|
+
assert Renderer.from_result({:error, :not_integer}) == "error: not_integer"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
test "classify/1 は cond で優先順位どおりに判定する" do
|
|
98
|
+
assert Renderer.classify(15) == :fizz_buzz
|
|
99
|
+
assert Renderer.classify(6) == :fizz
|
|
100
|
+
assert Renderer.classify(10) == :buzz
|
|
101
|
+
assert Renderer.classify(7) == :number
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 8.6 まとめ
|
|
107
|
+
|
|
108
|
+
この章では、関数頭部のパターンマッチ、`when` ガード節、`case` と `cond` の使い分け、タグ付きタプルによる結果表現を確認しました。これらを組み合わせると、分岐が増えても読みやすさと安全性を維持できます。
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# 第 9 章: モジュール設計とビヘイビア
|
|
2
|
+
|
|
3
|
+
## 9.1 はじめに
|
|
4
|
+
|
|
5
|
+
この章では、モジュールの責務分割を保ちながら拡張しやすい構成を作るために、モジュールの入れ子、`@behaviour` / `@callback`、`alias` を使った設計を扱います。FizzBuzz のコマンド層を例に、共通インターフェースを実装する形へ整理します。
|
|
6
|
+
|
|
7
|
+
## 9.2 モジュールの入れ子で責務を表現する
|
|
8
|
+
|
|
9
|
+
Elixir はファイル階層とは独立して、名前空間で責務を整理できます。たとえば `FizzBuzz.Command.ValueCommand` は「単一値を扱うコマンド」を明確に示します。
|
|
10
|
+
|
|
11
|
+
```elixir
|
|
12
|
+
defmodule FizzBuzz.Command.ValueCommand do
|
|
13
|
+
def run(number), do: Integer.to_string(number)
|
|
14
|
+
end
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`FizzBuzz.Command` 配下に `ValueCommand` と `ListCommand` を置くと、同じ関心事のモジュール群を把握しやすくなります。
|
|
18
|
+
|
|
19
|
+
## 9.3 @behaviour と @callback でインターフェースを定義する
|
|
20
|
+
|
|
21
|
+
まずはコマンド共通の契約を `FizzBuzz.Command` ビヘイビアとして定義します。
|
|
22
|
+
|
|
23
|
+
```elixir
|
|
24
|
+
defmodule FizzBuzz.Command do
|
|
25
|
+
@callback run(input :: term()) :: {:ok, term()} | {:error, atom()}
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
この `@callback` により、実装モジュールは `run/1` を提供する必要があります。未実装の場合、コンパイル時に警告が出るため、設計の抜け漏れを防げます。
|
|
30
|
+
|
|
31
|
+
## 9.4 ValueCommand と ListCommand でビヘイビアを実装する
|
|
32
|
+
|
|
33
|
+
`@behaviour FizzBuzz.Command` を指定し、`run/1` を実装します。`alias` を使ってモジュール参照を簡略化します。
|
|
34
|
+
|
|
35
|
+
```elixir
|
|
36
|
+
defmodule FizzBuzz.Command.ValueCommand do
|
|
37
|
+
@behaviour FizzBuzz.Command
|
|
38
|
+
|
|
39
|
+
alias FizzBuzz.FizzBuzzService
|
|
40
|
+
|
|
41
|
+
@impl true
|
|
42
|
+
def run(number) when is_integer(number) and number > 0 do
|
|
43
|
+
{:ok, FizzBuzzService.generate(number)}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
@impl true
|
|
47
|
+
def run(_), do: {:error, :invalid_number}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
defmodule FizzBuzz.Command.ListCommand do
|
|
51
|
+
@behaviour FizzBuzz.Command
|
|
52
|
+
|
|
53
|
+
alias FizzBuzz.FizzBuzzService
|
|
54
|
+
|
|
55
|
+
@impl true
|
|
56
|
+
def run(limit) when is_integer(limit) and limit > 0 do
|
|
57
|
+
values =
|
|
58
|
+
1..limit
|
|
59
|
+
|> Enum.map(&FizzBuzzService.generate/1)
|
|
60
|
+
|
|
61
|
+
{:ok, values}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@impl true
|
|
65
|
+
def run(_), do: {:error, :invalid_limit}
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`alias FizzBuzz.FizzBuzzService` を使うことで、`FizzBuzz.FizzBuzzService.generate/1` を `FizzBuzzService.generate/1` と短く書けます。
|
|
70
|
+
|
|
71
|
+
## 9.5 ExUnit でビヘイビア実装を検証する
|
|
72
|
+
|
|
73
|
+
各コマンドが同じ契約で動くことを ExUnit で確認します。
|
|
74
|
+
|
|
75
|
+
```elixir
|
|
76
|
+
defmodule FizzBuzz.CommandTest do
|
|
77
|
+
use ExUnit.Case, async: true
|
|
78
|
+
|
|
79
|
+
alias FizzBuzz.Command.{ListCommand, ValueCommand}
|
|
80
|
+
|
|
81
|
+
test "ValueCommand は単一値を処理する" do
|
|
82
|
+
assert ValueCommand.run(3) == {:ok, "Fizz"}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
test "ValueCommand は不正値でエラーを返す" do
|
|
86
|
+
assert ValueCommand.run(0) == {:error, :invalid_number}
|
|
87
|
+
assert ValueCommand.run("3") == {:error, :invalid_number}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
test "ListCommand は 1..limit の結果一覧を返す" do
|
|
91
|
+
assert ListCommand.run(5) == {:ok, ["1", "2", "Fizz", "4", "Buzz"]}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
test "ListCommand は不正値でエラーを返す" do
|
|
95
|
+
assert ListCommand.run(-1) == {:error, :invalid_limit}
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`ValueCommand` と `ListCommand` は入出力対象が異なっても、同じ `run/1` 契約を守るため、呼び出し側の扱いを統一できます。
|
|
101
|
+
|
|
102
|
+
## 9.6 まとめ
|
|
103
|
+
|
|
104
|
+
この章では、`FizzBuzz.Command.ValueCommand` のようなモジュール入れ子で責務を整理し、`@behaviour` / `@callback` で契約を固定し、`alias` で記述を簡潔にする方法を確認しました。ビヘイビア中心の設計により、機能追加時も既存コードへの影響を局所化できます。
|
package/lib/assets/docs/article/getting-start-tdd/elixir/10-higher-order-functions-and-pipeline.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# 第 10 章: 高階関数とパイプライン演算子
|
|
2
|
+
|
|
3
|
+
## 10.1 はじめに
|
|
4
|
+
|
|
5
|
+
この章では、Elixir の高階関数を使って、データ変換を宣言的に記述する方法を学びます。`Enum.map`、`Enum.filter`、`Enum.reduce`、無名関数、`|>` パイプライン演算子を組み合わせ、FizzBuzz の実装を拡張します。
|
|
6
|
+
|
|
7
|
+
## 10.2 高階関数の基本: Enum.map / Enum.filter / Enum.reduce
|
|
8
|
+
|
|
9
|
+
高階関数は、関数を引数として受け取る関数です。Elixir では `Enum` モジュールが代表例です。
|
|
10
|
+
|
|
11
|
+
```elixir
|
|
12
|
+
defmodule FizzBuzz.Functional do
|
|
13
|
+
def generate(number) when rem(number, 15) == 0, do: "FizzBuzz"
|
|
14
|
+
def generate(number) when rem(number, 3) == 0, do: "Fizz"
|
|
15
|
+
def generate(number) when rem(number, 5) == 0, do: "Buzz"
|
|
16
|
+
def generate(number), do: Integer.to_string(number)
|
|
17
|
+
|
|
18
|
+
def generate_list(limit) do
|
|
19
|
+
1..limit
|
|
20
|
+
|> Enum.map(&generate/1)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def count_fizzbuzz(limit) do
|
|
24
|
+
1..limit
|
|
25
|
+
|> Enum.map(&generate/1)
|
|
26
|
+
|> Enum.filter(&(&1 in ["Fizz", "Buzz", "FizzBuzz"]))
|
|
27
|
+
|> Enum.count()
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def summary(limit) do
|
|
31
|
+
1..limit
|
|
32
|
+
|> Enum.map(&generate/1)
|
|
33
|
+
|> Enum.reduce(%{fizz: 0, buzz: 0, fizzbuzz: 0, number: 0}, fn value, acc ->
|
|
34
|
+
case value do
|
|
35
|
+
"Fizz" -> %{acc | fizz: acc.fizz + 1}
|
|
36
|
+
"Buzz" -> %{acc | buzz: acc.buzz + 1}
|
|
37
|
+
"FizzBuzz" -> %{acc | fizzbuzz: acc.fizzbuzz + 1}
|
|
38
|
+
_ -> %{acc | number: acc.number + 1}
|
|
39
|
+
end
|
|
40
|
+
end)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 10.3 無名関数: fn と & キャプチャ演算子
|
|
46
|
+
|
|
47
|
+
Elixir には 2 つの無名関数の書き方があります。
|
|
48
|
+
|
|
49
|
+
```elixir
|
|
50
|
+
defmodule FizzBuzz.Anonymous do
|
|
51
|
+
def multiply_all(numbers, factor) do
|
|
52
|
+
Enum.map(numbers, fn n -> n * factor end)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def square_all(numbers) do
|
|
56
|
+
Enum.map(numbers, &(&1 * &1))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def stringify(numbers) do
|
|
60
|
+
Enum.map(numbers, &Integer.to_string/1)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- `fn n -> ... end` は複雑なロジックに向いています。
|
|
66
|
+
- `&(&1 * &1)` のようなキャプチャ演算子は短く書けます。
|
|
67
|
+
|
|
68
|
+
## 10.4 パイプライン演算子 |> で関数チェーンを書く
|
|
69
|
+
|
|
70
|
+
`|>` は左側の値を右側関数の第 1 引数に渡します。処理の流れを上から下に読めるため、可読性が上がります。
|
|
71
|
+
|
|
72
|
+
```elixir
|
|
73
|
+
defmodule FizzBuzz.Pipeline do
|
|
74
|
+
alias FizzBuzz.Functional
|
|
75
|
+
|
|
76
|
+
def report(limit) do
|
|
77
|
+
1..limit
|
|
78
|
+
|> Enum.map(&Functional.generate/1)
|
|
79
|
+
|> Enum.filter(&(&1 != "FizzBuzz"))
|
|
80
|
+
|> Enum.join(",")
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 10.5 generate_with/2 でカスタムルール関数を受け取る
|
|
86
|
+
|
|
87
|
+
高階関数を使うと、ルールを外部から注入できます。`generate_with/2` は「数値」と「ルール関数」を受け取ります。
|
|
88
|
+
|
|
89
|
+
```elixir
|
|
90
|
+
defmodule FizzBuzz.CustomRule do
|
|
91
|
+
def generate_with(number, rule_fn) when is_function(rule_fn, 1) do
|
|
92
|
+
case rule_fn.(number) do
|
|
93
|
+
nil -> Integer.to_string(number)
|
|
94
|
+
value -> value
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def generate_with(number, rule_fns) when is_list(rule_fns) do
|
|
99
|
+
result =
|
|
100
|
+
Enum.reduce_while(rule_fns, nil, fn rule_fn, _acc ->
|
|
101
|
+
case rule_fn.(number) do
|
|
102
|
+
nil -> {:cont, nil}
|
|
103
|
+
value -> {:halt, value}
|
|
104
|
+
end
|
|
105
|
+
end)
|
|
106
|
+
|
|
107
|
+
result || Integer.to_string(number)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 10.6 transform/2 と filter/2 で汎用化する
|
|
113
|
+
|
|
114
|
+
FizzBuzz 専用処理を汎用関数に切り出すと、再利用しやすくなります。
|
|
115
|
+
|
|
116
|
+
```elixir
|
|
117
|
+
defmodule FizzBuzz.Collection do
|
|
118
|
+
def transform(values, mapper) when is_function(mapper, 1) do
|
|
119
|
+
Enum.map(values, mapper)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def filter(values, predicate) when is_function(predicate, 1) do
|
|
123
|
+
Enum.filter(values, predicate)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 10.7 ExUnit で高階関数を検証する
|
|
129
|
+
|
|
130
|
+
```elixir
|
|
131
|
+
defmodule FizzBuzz.HigherOrderFunctionsTest do
|
|
132
|
+
use ExUnit.Case, async: true
|
|
133
|
+
|
|
134
|
+
alias FizzBuzz.{Collection, CustomRule, Functional}
|
|
135
|
+
|
|
136
|
+
test "Enum.map で FizzBuzz の一覧を生成できる" do
|
|
137
|
+
assert Functional.generate_list(5) == ["1", "2", "Fizz", "4", "Buzz"]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
test "Enum.filter と Enum.count で Fizz/Buzz 系だけ数えられる" do
|
|
141
|
+
assert Functional.count_fizzbuzz(15) == 7
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
test "Enum.reduce で種別ごとの集計ができる" do
|
|
145
|
+
assert Functional.summary(15) == %{fizz: 4, buzz: 2, fizzbuzz: 1, number: 8}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
test "generate_with/2 は単一ルール関数を受け取れる" do
|
|
149
|
+
even_rule = fn n -> if rem(n, 2) == 0, do: "Even", else: nil end
|
|
150
|
+
|
|
151
|
+
assert CustomRule.generate_with(4, even_rule) == "Even"
|
|
152
|
+
assert CustomRule.generate_with(3, even_rule) == "3"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
test "generate_with/2 はルール関数リストを順に適用する" do
|
|
156
|
+
rules = [
|
|
157
|
+
fn n -> if rem(n, 7) == 0, do: "Pop", else: nil end,
|
|
158
|
+
fn n -> if rem(n, 3) == 0, do: "Fizz", else: nil end
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
assert CustomRule.generate_with(14, rules) == "Pop"
|
|
162
|
+
assert CustomRule.generate_with(9, rules) == "Fizz"
|
|
163
|
+
assert CustomRule.generate_with(2, rules) == "2"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
test "transform/2 と filter/2 を組み合わせて再利用できる" do
|
|
167
|
+
values = 1..6 |> Enum.to_list()
|
|
168
|
+
|
|
169
|
+
assert values
|
|
170
|
+
|> Collection.transform(&(&1 * 10))
|
|
171
|
+
|> Collection.filter(&(&1 > 30)) == [40, 50, 60]
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## 10.8 まとめ
|
|
177
|
+
|
|
178
|
+
この章では、高階関数、無名関数、`|>` パイプライン演算子を使って処理を小さな関数へ分解し、合成する方法を確認しました。`generate_with/2`、`transform/2`、`filter/2` のように関数を受け取る設計により、仕様変更に強い実装を作れます。
|