@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.
Files changed (527) hide show
  1. package/lib/assets/docs/article/functional-desgin-ppp/all/01-immutability-and-data-transformation.md +475 -0
  2. package/lib/assets/docs/article/functional-desgin-ppp/all/02-function-composition.md +519 -0
  3. package/lib/assets/docs/article/functional-desgin-ppp/all/03-polymorphism.md +537 -0
  4. package/lib/assets/docs/article/functional-desgin-ppp/all/04-data-validation.md +300 -0
  5. package/lib/assets/docs/article/functional-desgin-ppp/all/05-property-based-testing.md +320 -0
  6. package/lib/assets/docs/article/functional-desgin-ppp/all/06-tdd-and-functional.md +498 -0
  7. package/lib/assets/docs/article/functional-desgin-ppp/all/07-composite-pattern.md +298 -0
  8. package/lib/assets/docs/article/functional-desgin-ppp/all/08-decorator-pattern.md +291 -0
  9. package/lib/assets/docs/article/functional-desgin-ppp/all/09-adapter-pattern.md +336 -0
  10. package/lib/assets/docs/article/functional-desgin-ppp/all/10-strategy-pattern.md +303 -0
  11. package/lib/assets/docs/article/functional-desgin-ppp/all/11-command-pattern.md +286 -0
  12. package/lib/assets/docs/article/functional-desgin-ppp/all/12-visitor-pattern.md +322 -0
  13. package/lib/assets/docs/article/functional-desgin-ppp/all/13-abstract-factory-pattern.md +319 -0
  14. package/lib/assets/docs/article/functional-desgin-ppp/all/14-abstract-server-pattern.md +365 -0
  15. package/lib/assets/docs/article/functional-desgin-ppp/all/15-gossiping-bus-drivers.md +156 -0
  16. package/lib/assets/docs/article/functional-desgin-ppp/all/16-payroll-system.md +178 -0
  17. package/lib/assets/docs/article/functional-desgin-ppp/all/17-video-rental-system.md +312 -0
  18. package/lib/assets/docs/article/functional-desgin-ppp/all/18-concurrency-system.md +287 -0
  19. package/lib/assets/docs/article/functional-desgin-ppp/all/19-wa-tor-simulation.md +286 -0
  20. package/lib/assets/docs/article/functional-desgin-ppp/all/20-pattern-interactions.md +274 -0
  21. package/lib/assets/docs/article/functional-desgin-ppp/all/21-best-practices.md +294 -0
  22. package/lib/assets/docs/article/functional-desgin-ppp/all/22-oo-to-fp-migration.md +337 -0
  23. package/lib/assets/docs/article/functional-desgin-ppp/all/index.md +388 -0
  24. package/lib/assets/docs/article/functional-desgin-ppp/clojure/01-immutability-and-data-transformation.md +271 -0
  25. package/lib/assets/docs/article/functional-desgin-ppp/clojure/02-function-composition.md +380 -0
  26. package/lib/assets/docs/article/functional-desgin-ppp/clojure/03-polymorphism.md +384 -0
  27. package/lib/assets/docs/article/functional-desgin-ppp/clojure/04-clojure-spec.md +350 -0
  28. package/lib/assets/docs/article/functional-desgin-ppp/clojure/05-property-based-testing.md +352 -0
  29. package/lib/assets/docs/article/functional-desgin-ppp/clojure/06-tdd-in-functional.md +383 -0
  30. package/lib/assets/docs/article/functional-desgin-ppp/clojure/07-composite-pattern.md +529 -0
  31. package/lib/assets/docs/article/functional-desgin-ppp/clojure/08-decorator-pattern.md +395 -0
  32. package/lib/assets/docs/article/functional-desgin-ppp/clojure/09-adapter-pattern.md +399 -0
  33. package/lib/assets/docs/article/functional-desgin-ppp/clojure/10-strategy-pattern.md +485 -0
  34. package/lib/assets/docs/article/functional-desgin-ppp/clojure/11-command-pattern.md +566 -0
  35. package/lib/assets/docs/article/functional-desgin-ppp/clojure/12-visitor-pattern.md +567 -0
  36. package/lib/assets/docs/article/functional-desgin-ppp/clojure/13-abstract-factory-pattern.md +475 -0
  37. package/lib/assets/docs/article/functional-desgin-ppp/clojure/14-abstract-server-pattern.md +462 -0
  38. package/lib/assets/docs/article/functional-desgin-ppp/clojure/15-gossiping-bus-drivers.md +323 -0
  39. package/lib/assets/docs/article/functional-desgin-ppp/clojure/16-payroll-system.md +401 -0
  40. package/lib/assets/docs/article/functional-desgin-ppp/clojure/17-video-rental-system.md +450 -0
  41. package/lib/assets/docs/article/functional-desgin-ppp/clojure/18-concurrency-system.md +475 -0
  42. package/lib/assets/docs/article/functional-desgin-ppp/clojure/19-wator-simulation.md +739 -0
  43. package/lib/assets/docs/article/functional-desgin-ppp/clojure/20-pattern-interactions.md +562 -0
  44. package/lib/assets/docs/article/functional-desgin-ppp/clojure/21-best-practices.md +506 -0
  45. package/lib/assets/docs/article/functional-desgin-ppp/clojure/22-oo-to-fp-migration.md +526 -0
  46. package/lib/assets/docs/article/functional-desgin-ppp/clojure/index.md +197 -0
  47. package/lib/assets/docs/article/functional-desgin-ppp/elixir/01-immutability-and-data-transformation.md +381 -0
  48. package/lib/assets/docs/article/functional-desgin-ppp/elixir/02-function-composition.md +374 -0
  49. package/lib/assets/docs/article/functional-desgin-ppp/elixir/03-polymorphism.md +375 -0
  50. package/lib/assets/docs/article/functional-desgin-ppp/elixir/04-data-validation.md +195 -0
  51. package/lib/assets/docs/article/functional-desgin-ppp/elixir/05-property-based-testing.md +268 -0
  52. package/lib/assets/docs/article/functional-desgin-ppp/elixir/06-tdd-and-fp.md +294 -0
  53. package/lib/assets/docs/article/functional-desgin-ppp/elixir/07-effects-and-pure-functions.md +164 -0
  54. package/lib/assets/docs/article/functional-desgin-ppp/elixir/08-error-handling-strategies.md +168 -0
  55. package/lib/assets/docs/article/functional-desgin-ppp/elixir/09-io-and-external-systems.md +254 -0
  56. package/lib/assets/docs/article/functional-desgin-ppp/elixir/10-concurrency-patterns.md +269 -0
  57. package/lib/assets/docs/article/functional-desgin-ppp/elixir/11-command-pattern.md +148 -0
  58. package/lib/assets/docs/article/functional-desgin-ppp/elixir/12-visitor-pattern.md +176 -0
  59. package/lib/assets/docs/article/functional-desgin-ppp/elixir/13-abstract-factory-pattern.md +604 -0
  60. package/lib/assets/docs/article/functional-desgin-ppp/elixir/14-abstract-server-pattern.md +729 -0
  61. package/lib/assets/docs/article/functional-desgin-ppp/elixir/15-gossiping-bus-drivers.md +291 -0
  62. package/lib/assets/docs/article/functional-desgin-ppp/elixir/16-payroll-system.md +420 -0
  63. package/lib/assets/docs/article/functional-desgin-ppp/elixir/17-video-rental-system.md +319 -0
  64. package/lib/assets/docs/article/functional-desgin-ppp/elixir/18-concurrency-system.md +466 -0
  65. package/lib/assets/docs/article/functional-desgin-ppp/elixir/19-wator-simulation.md +523 -0
  66. package/lib/assets/docs/article/functional-desgin-ppp/elixir/20-pattern-interactions.md +287 -0
  67. package/lib/assets/docs/article/functional-desgin-ppp/elixir/21-best-practices.md +340 -0
  68. package/lib/assets/docs/article/functional-desgin-ppp/elixir/22-oo-to-fp-migration.md +395 -0
  69. package/lib/assets/docs/article/functional-desgin-ppp/elixir/index.md +204 -0
  70. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/01-immutability-and-data-transformation.md +382 -0
  71. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/02-function-composition.md +452 -0
  72. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/03-polymorphism.md +495 -0
  73. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/04-data-validation.md +416 -0
  74. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/05-property-based-testing.md +382 -0
  75. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/06-tdd-functional.md +687 -0
  76. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/07-composite-pattern.md +442 -0
  77. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/08-decorator-pattern.md +479 -0
  78. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/09-adapter-pattern.md +479 -0
  79. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/10-strategy-pattern.md +427 -0
  80. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/11-command-pattern.md +428 -0
  81. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/12-visitor-pattern.md +339 -0
  82. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/13-abstract-factory-pattern.md +309 -0
  83. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/14-abstract-server-pattern.md +596 -0
  84. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/15-gossiping-bus-drivers.md +353 -0
  85. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/16-payroll-system.md +350 -0
  86. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/17-video-rental-system.md +412 -0
  87. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/18-concurrency-system.md +367 -0
  88. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/19-wator-simulation.md +401 -0
  89. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/20-pattern-interactions.md +291 -0
  90. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/21-best-practices.md +320 -0
  91. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/22-oo-to-fp-migration.md +322 -0
  92. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/index.md +230 -0
  93. package/lib/assets/docs/article/functional-desgin-ppp/haskell/01-immutability-and-data-transformation.md +298 -0
  94. package/lib/assets/docs/article/functional-desgin-ppp/haskell/02-function-composition.md +304 -0
  95. package/lib/assets/docs/article/functional-desgin-ppp/haskell/03-polymorphism.md +362 -0
  96. package/lib/assets/docs/article/functional-desgin-ppp/haskell/04-data-validation.md +257 -0
  97. package/lib/assets/docs/article/functional-desgin-ppp/haskell/05-property-based-testing.md +254 -0
  98. package/lib/assets/docs/article/functional-desgin-ppp/haskell/06-tdd-functional.md +283 -0
  99. package/lib/assets/docs/article/functional-desgin-ppp/haskell/07-composite-pattern.md +395 -0
  100. package/lib/assets/docs/article/functional-desgin-ppp/haskell/08-decorator-pattern.md +319 -0
  101. package/lib/assets/docs/article/functional-desgin-ppp/haskell/09-adapter-pattern.md +382 -0
  102. package/lib/assets/docs/article/functional-desgin-ppp/haskell/10-strategy-pattern.md +287 -0
  103. package/lib/assets/docs/article/functional-desgin-ppp/haskell/11-command-pattern.md +303 -0
  104. package/lib/assets/docs/article/functional-desgin-ppp/haskell/12-visitor-pattern.md +326 -0
  105. package/lib/assets/docs/article/functional-desgin-ppp/haskell/13-abstract-factory-pattern.md +332 -0
  106. package/lib/assets/docs/article/functional-desgin-ppp/haskell/14-abstract-server-pattern.md +379 -0
  107. package/lib/assets/docs/article/functional-desgin-ppp/haskell/15-gossiping-bus-drivers.md +175 -0
  108. package/lib/assets/docs/article/functional-desgin-ppp/haskell/16-payroll-system.md +219 -0
  109. package/lib/assets/docs/article/functional-desgin-ppp/haskell/17-video-rental-system.md +244 -0
  110. package/lib/assets/docs/article/functional-desgin-ppp/haskell/18-concurrency-system.md +363 -0
  111. package/lib/assets/docs/article/functional-desgin-ppp/haskell/19-wator-simulation.md +438 -0
  112. package/lib/assets/docs/article/functional-desgin-ppp/haskell/20-pattern-interactions.md +323 -0
  113. package/lib/assets/docs/article/functional-desgin-ppp/haskell/21-best-practices.md +403 -0
  114. package/lib/assets/docs/article/functional-desgin-ppp/haskell/22-oo-to-fp-migration.md +469 -0
  115. package/lib/assets/docs/article/functional-desgin-ppp/haskell/index.md +174 -0
  116. package/lib/assets/docs/article/functional-desgin-ppp/index.md +90 -0
  117. package/lib/assets/docs/article/functional-desgin-ppp/rust/01-immutability-and-data-transformation.md +448 -0
  118. package/lib/assets/docs/article/functional-desgin-ppp/rust/02-function-composition.md +463 -0
  119. package/lib/assets/docs/article/functional-desgin-ppp/rust/03-polymorphism.md +425 -0
  120. package/lib/assets/docs/article/functional-desgin-ppp/rust/04-data-validation.md +273 -0
  121. package/lib/assets/docs/article/functional-desgin-ppp/rust/05-property-based-testing.md +247 -0
  122. package/lib/assets/docs/article/functional-desgin-ppp/rust/06-tdd-and-functional.md +841 -0
  123. package/lib/assets/docs/article/functional-desgin-ppp/rust/07-composite-pattern.md +384 -0
  124. package/lib/assets/docs/article/functional-desgin-ppp/rust/08-decorator-pattern.md +383 -0
  125. package/lib/assets/docs/article/functional-desgin-ppp/rust/09-adapter-pattern.md +339 -0
  126. package/lib/assets/docs/article/functional-desgin-ppp/rust/10-strategy-pattern.md +331 -0
  127. package/lib/assets/docs/article/functional-desgin-ppp/rust/11-command-pattern.md +356 -0
  128. package/lib/assets/docs/article/functional-desgin-ppp/rust/12-visitor-pattern.md +379 -0
  129. package/lib/assets/docs/article/functional-desgin-ppp/rust/13-abstract-factory-pattern.md +361 -0
  130. package/lib/assets/docs/article/functional-desgin-ppp/rust/14-abstract-server-pattern.md +392 -0
  131. package/lib/assets/docs/article/functional-desgin-ppp/rust/15-gossiping-bus-drivers.md +300 -0
  132. package/lib/assets/docs/article/functional-desgin-ppp/rust/16-payroll-system.md +297 -0
  133. package/lib/assets/docs/article/functional-desgin-ppp/rust/17-video-rental-system.md +304 -0
  134. package/lib/assets/docs/article/functional-desgin-ppp/rust/18-concurrency-system.md +315 -0
  135. package/lib/assets/docs/article/functional-desgin-ppp/rust/19-wator-simulation.md +311 -0
  136. package/lib/assets/docs/article/functional-desgin-ppp/rust/20-pattern-interactions.md +304 -0
  137. package/lib/assets/docs/article/functional-desgin-ppp/rust/21-best-practices.md +336 -0
  138. package/lib/assets/docs/article/functional-desgin-ppp/rust/22-oo-to-fp-migration.md +349 -0
  139. package/lib/assets/docs/article/functional-desgin-ppp/rust/index.md +199 -0
  140. package/lib/assets/docs/article/functional-desgin-ppp/scala/01-immutability-and-data-transformation.md +326 -0
  141. package/lib/assets/docs/article/functional-desgin-ppp/scala/02-function-composition.md +348 -0
  142. package/lib/assets/docs/article/functional-desgin-ppp/scala/03-polymorphism.md +357 -0
  143. package/lib/assets/docs/article/functional-desgin-ppp/scala/04-data-validation.md +364 -0
  144. package/lib/assets/docs/article/functional-desgin-ppp/scala/05-property-based-testing.md +515 -0
  145. package/lib/assets/docs/article/functional-desgin-ppp/scala/06-tdd-functional.md +557 -0
  146. package/lib/assets/docs/article/functional-desgin-ppp/scala/07-composite-pattern.md +363 -0
  147. package/lib/assets/docs/article/functional-desgin-ppp/scala/08-decorator-pattern.md +327 -0
  148. package/lib/assets/docs/article/functional-desgin-ppp/scala/09-adapter-pattern.md +517 -0
  149. package/lib/assets/docs/article/functional-desgin-ppp/scala/10-strategy-pattern.md +441 -0
  150. package/lib/assets/docs/article/functional-desgin-ppp/scala/11-command-pattern.md +407 -0
  151. package/lib/assets/docs/article/functional-desgin-ppp/scala/12-visitor-pattern.md +379 -0
  152. package/lib/assets/docs/article/functional-desgin-ppp/scala/13-abstract-factory-pattern.md +398 -0
  153. package/lib/assets/docs/article/functional-desgin-ppp/scala/14-abstract-server-pattern.md +476 -0
  154. package/lib/assets/docs/article/functional-desgin-ppp/scala/15-gossiping-bus-drivers.md +389 -0
  155. package/lib/assets/docs/article/functional-desgin-ppp/scala/16-payroll-system.md +342 -0
  156. package/lib/assets/docs/article/functional-desgin-ppp/scala/17-video-rental-system.md +324 -0
  157. package/lib/assets/docs/article/functional-desgin-ppp/scala/18-concurrency-system.md +730 -0
  158. package/lib/assets/docs/article/functional-desgin-ppp/scala/19-wator-simulation.md +624 -0
  159. package/lib/assets/docs/article/functional-desgin-ppp/scala/20-pattern-interactions.md +512 -0
  160. package/lib/assets/docs/article/functional-desgin-ppp/scala/21-best-practices.md +427 -0
  161. package/lib/assets/docs/article/functional-desgin-ppp/scala/22-oo-to-fp-migration.md +682 -0
  162. package/lib/assets/docs/article/functional-desgin-ppp/scala/index.md +199 -0
  163. package/lib/assets/docs/article/getting-start-tdd/clojure/01-todo-list-and-first-test.md +166 -0
  164. package/lib/assets/docs/article/getting-start-tdd/clojure/02-fake-it-and-triangulation.md +162 -0
  165. package/lib/assets/docs/article/getting-start-tdd/clojure/03-obvious-implementation-and-refactoring.md +135 -0
  166. package/lib/assets/docs/article/getting-start-tdd/clojure/04-version-control-and-conventional-commits.md +88 -0
  167. package/lib/assets/docs/article/getting-start-tdd/clojure/05-package-management-and-static-analysis.md +299 -0
  168. package/lib/assets/docs/article/getting-start-tdd/clojure/06-task-runner-and-ci-cd.md +241 -0
  169. package/lib/assets/docs/article/getting-start-tdd/clojure/07-protocols-and-records.md +131 -0
  170. package/lib/assets/docs/article/getting-start-tdd/clojure/08-multimethods-and-design-patterns.md +130 -0
  171. package/lib/assets/docs/article/getting-start-tdd/clojure/09-namespaces-and-module-design.md +127 -0
  172. package/lib/assets/docs/article/getting-start-tdd/clojure/10-higher-order-functions-and-composition.md +114 -0
  173. package/lib/assets/docs/article/getting-start-tdd/clojure/11-persistent-data-and-pipeline.md +138 -0
  174. package/lib/assets/docs/article/getting-start-tdd/clojure/12-error-handling-and-spec.md +161 -0
  175. package/lib/assets/docs/article/getting-start-tdd/clojure/index.md +65 -0
  176. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter01.md +232 -0
  177. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter02.md +244 -0
  178. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter03.md +202 -0
  179. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter04.md +92 -0
  180. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter05.md +256 -0
  181. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter06.md +195 -0
  182. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter07.md +214 -0
  183. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter08.md +249 -0
  184. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter09.md +174 -0
  185. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter10.md +166 -0
  186. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter11.md +192 -0
  187. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter12.md +211 -0
  188. package/lib/assets/docs/article/getting-start-tdd/csharp/index.md +83 -0
  189. package/lib/assets/docs/article/getting-start-tdd/elixir/01-todo-list-and-first-test.md +87 -0
  190. package/lib/assets/docs/article/getting-start-tdd/elixir/02-fake-it-and-triangulation.md +95 -0
  191. package/lib/assets/docs/article/getting-start-tdd/elixir/03-obvious-implementation-and-refactoring.md +109 -0
  192. package/lib/assets/docs/article/getting-start-tdd/elixir/04-version-control-and-conventional-commits.md +96 -0
  193. package/lib/assets/docs/article/getting-start-tdd/elixir/05-package-management-and-static-analysis.md +88 -0
  194. package/lib/assets/docs/article/getting-start-tdd/elixir/06-task-runner-and-ci-cd.md +71 -0
  195. package/lib/assets/docs/article/getting-start-tdd/elixir/07-structs-and-protocols.md +110 -0
  196. package/lib/assets/docs/article/getting-start-tdd/elixir/08-pattern-matching-and-guards.md +108 -0
  197. package/lib/assets/docs/article/getting-start-tdd/elixir/09-module-design-and-behaviours.md +104 -0
  198. package/lib/assets/docs/article/getting-start-tdd/elixir/10-higher-order-functions-and-pipeline.md +178 -0
  199. package/lib/assets/docs/article/getting-start-tdd/elixir/11-stream-and-lazy-evaluation.md +142 -0
  200. package/lib/assets/docs/article/getting-start-tdd/elixir/12-error-handling-and-with.md +145 -0
  201. package/lib/assets/docs/article/getting-start-tdd/elixir/index.md +35 -0
  202. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter01.md +202 -0
  203. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter02.md +246 -0
  204. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter03.md +218 -0
  205. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter04.md +179 -0
  206. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter05.md +267 -0
  207. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter06.md +190 -0
  208. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter07.md +161 -0
  209. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter08.md +175 -0
  210. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter09.md +222 -0
  211. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter10.md +189 -0
  212. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter11.md +212 -0
  213. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter12.md +215 -0
  214. package/lib/assets/docs/article/getting-start-tdd/fsharp/index.md +71 -0
  215. package/lib/assets/docs/article/getting-start-tdd/go/01-todo-list-and-first-test.md +213 -0
  216. package/lib/assets/docs/article/getting-start-tdd/go/02-fake-it-and-triangulation.md +302 -0
  217. package/lib/assets/docs/article/getting-start-tdd/go/03-obvious-implementation-and-refactoring.md +339 -0
  218. package/lib/assets/docs/article/getting-start-tdd/go/04-version-control-and-conventional-commits.md +112 -0
  219. package/lib/assets/docs/article/getting-start-tdd/go/05-package-management-and-static-analysis.md +272 -0
  220. package/lib/assets/docs/article/getting-start-tdd/go/06-task-runner-and-ci-cd.md +233 -0
  221. package/lib/assets/docs/article/getting-start-tdd/go/07-encapsulation-and-polymorphism.md +394 -0
  222. package/lib/assets/docs/article/getting-start-tdd/go/08-design-patterns.md +422 -0
  223. package/lib/assets/docs/article/getting-start-tdd/go/09-solid-principles-and-module-design.md +400 -0
  224. package/lib/assets/docs/article/getting-start-tdd/go/10-higher-order-functions-and-composition.md +226 -0
  225. package/lib/assets/docs/article/getting-start-tdd/go/11-immutable-data-and-pipeline.md +296 -0
  226. package/lib/assets/docs/article/getting-start-tdd/go/12-error-handling-and-type-safety.md +411 -0
  227. package/lib/assets/docs/article/getting-start-tdd/go/index.md +83 -0
  228. package/lib/assets/docs/article/getting-start-tdd/haskell/01-todo-list-and-first-test.md +279 -0
  229. package/lib/assets/docs/article/getting-start-tdd/haskell/02-fake-it-and-triangulation.md +337 -0
  230. package/lib/assets/docs/article/getting-start-tdd/haskell/03-obvious-implementation-and-refactoring.md +257 -0
  231. package/lib/assets/docs/article/getting-start-tdd/haskell/04-version-control-and-conventional-commits.md +182 -0
  232. package/lib/assets/docs/article/getting-start-tdd/haskell/05-package-management-and-static-analysis.md +313 -0
  233. package/lib/assets/docs/article/getting-start-tdd/haskell/06-task-runner-and-ci-cd.md +309 -0
  234. package/lib/assets/docs/article/getting-start-tdd/haskell/07-algebraic-data-types-and-type-classes.md +412 -0
  235. package/lib/assets/docs/article/getting-start-tdd/haskell/08-pattern-matching-and-guards.md +390 -0
  236. package/lib/assets/docs/article/getting-start-tdd/haskell/09-module-design-and-smart-constructors.md +461 -0
  237. package/lib/assets/docs/article/getting-start-tdd/haskell/10-higher-order-functions-and-currying.md +434 -0
  238. package/lib/assets/docs/article/getting-start-tdd/haskell/11-function-composition-and-point-free.md +392 -0
  239. package/lib/assets/docs/article/getting-start-tdd/haskell/12-monad-and-error-handling.md +631 -0
  240. package/lib/assets/docs/article/getting-start-tdd/haskell/index.md +49 -0
  241. package/lib/assets/docs/article/getting-start-tdd/index.md +93 -0
  242. package/lib/assets/docs/article/getting-start-tdd/integration/01-language-overview.md +375 -0
  243. package/lib/assets/docs/article/getting-start-tdd/integration/02-test-framework-comparison.md +349 -0
  244. package/lib/assets/docs/article/getting-start-tdd/integration/03-tdd-pattern-comparison.md +445 -0
  245. package/lib/assets/docs/article/getting-start-tdd/integration/04-type-system-comparison.md +405 -0
  246. package/lib/assets/docs/article/getting-start-tdd/integration/05-dev-environment-comparison.md +330 -0
  247. package/lib/assets/docs/article/getting-start-tdd/integration/06-learning-roadmap.md +274 -0
  248. package/lib/assets/docs/article/getting-start-tdd/integration/index.md +69 -0
  249. package/lib/assets/docs/article/getting-start-tdd/java/01-todo-list-and-first-test.md +234 -0
  250. package/lib/assets/docs/article/getting-start-tdd/java/02-fake-it-and-triangulation.md +261 -0
  251. package/lib/assets/docs/article/getting-start-tdd/java/03-obvious-implementation-and-refactoring.md +185 -0
  252. package/lib/assets/docs/article/getting-start-tdd/java/04-version-control-and-conventional-commits.md +115 -0
  253. package/lib/assets/docs/article/getting-start-tdd/java/05-package-management-and-static-analysis.md +382 -0
  254. package/lib/assets/docs/article/getting-start-tdd/java/06-task-runner-and-ci-cd.md +272 -0
  255. package/lib/assets/docs/article/getting-start-tdd/java/07-encapsulation-and-polymorphism.md +626 -0
  256. package/lib/assets/docs/article/getting-start-tdd/java/08-design-patterns.md +393 -0
  257. package/lib/assets/docs/article/getting-start-tdd/java/09-solid-principles-and-module-design.md +310 -0
  258. package/lib/assets/docs/article/getting-start-tdd/java/10-higher-order-functions-and-composition.md +188 -0
  259. package/lib/assets/docs/article/getting-start-tdd/java/11-immutable-data-and-pipeline.md +167 -0
  260. package/lib/assets/docs/article/getting-start-tdd/java/12-error-handling-and-type-safety.md +205 -0
  261. package/lib/assets/docs/article/getting-start-tdd/java/index.md +61 -0
  262. package/lib/assets/docs/article/getting-start-tdd/node/01-todo-list-and-first-test.md +244 -0
  263. package/lib/assets/docs/article/getting-start-tdd/node/02-fake-it-and-triangulation.md +262 -0
  264. package/lib/assets/docs/article/getting-start-tdd/node/03-obvious-implementation-and-refactoring.md +169 -0
  265. package/lib/assets/docs/article/getting-start-tdd/node/04-version-control-and-conventional-commits.md +112 -0
  266. package/lib/assets/docs/article/getting-start-tdd/node/05-package-management-and-static-analysis.md +314 -0
  267. package/lib/assets/docs/article/getting-start-tdd/node/06-task-runner-and-ci-cd.md +235 -0
  268. package/lib/assets/docs/article/getting-start-tdd/node/07-encapsulation-and-polymorphism.md +327 -0
  269. package/lib/assets/docs/article/getting-start-tdd/node/08-design-patterns.md +322 -0
  270. package/lib/assets/docs/article/getting-start-tdd/node/09-solid-principles-and-module-design.md +285 -0
  271. package/lib/assets/docs/article/getting-start-tdd/node/10-higher-order-functions-and-composition.md +199 -0
  272. package/lib/assets/docs/article/getting-start-tdd/node/11-immutable-data-and-pipeline.md +207 -0
  273. package/lib/assets/docs/article/getting-start-tdd/node/12-error-handling-and-type-safety.md +295 -0
  274. package/lib/assets/docs/article/getting-start-tdd/node/index.md +56 -0
  275. package/lib/assets/docs/article/getting-start-tdd/php/01-todo-list-and-first-test.md +259 -0
  276. package/lib/assets/docs/article/getting-start-tdd/php/02-fake-it-and-triangulation.md +200 -0
  277. package/lib/assets/docs/article/getting-start-tdd/php/03-obvious-implementation-and-refactoring.md +248 -0
  278. package/lib/assets/docs/article/getting-start-tdd/php/04-version-control-and-conventional-commits.md +141 -0
  279. package/lib/assets/docs/article/getting-start-tdd/php/05-package-management-and-static-analysis.md +410 -0
  280. package/lib/assets/docs/article/getting-start-tdd/php/06-task-runner-and-ci-cd.md +321 -0
  281. package/lib/assets/docs/article/getting-start-tdd/php/07-encapsulation-and-polymorphism.md +372 -0
  282. package/lib/assets/docs/article/getting-start-tdd/php/08-design-patterns.md +453 -0
  283. package/lib/assets/docs/article/getting-start-tdd/php/09-solid-principles-and-module-design.md +460 -0
  284. package/lib/assets/docs/article/getting-start-tdd/php/10-higher-order-functions-and-composition.md +182 -0
  285. package/lib/assets/docs/article/getting-start-tdd/php/11-immutable-data-and-pipeline.md +266 -0
  286. package/lib/assets/docs/article/getting-start-tdd/php/12-error-handling-and-type-safety.md +308 -0
  287. package/lib/assets/docs/article/getting-start-tdd/php/index.md +84 -0
  288. package/lib/assets/docs/article/getting-start-tdd/python/01-todo-list-and-first-test.md +201 -0
  289. package/lib/assets/docs/article/getting-start-tdd/python/02-fake-it-and-triangulation.md +247 -0
  290. package/lib/assets/docs/article/getting-start-tdd/python/03-obvious-implementation-and-refactoring.md +199 -0
  291. package/lib/assets/docs/article/getting-start-tdd/python/04-version-control-and-conventional-commits.md +87 -0
  292. package/lib/assets/docs/article/getting-start-tdd/python/05-package-management-and-static-analysis.md +274 -0
  293. package/lib/assets/docs/article/getting-start-tdd/python/06-task-runner-and-ci-cd.md +190 -0
  294. package/lib/assets/docs/article/getting-start-tdd/python/07-encapsulation-and-polymorphism.md +208 -0
  295. package/lib/assets/docs/article/getting-start-tdd/python/08-design-patterns.md +172 -0
  296. package/lib/assets/docs/article/getting-start-tdd/python/09-solid-principles-and-module-design.md +130 -0
  297. package/lib/assets/docs/article/getting-start-tdd/python/10-higher-order-functions-and-composition.md +122 -0
  298. package/lib/assets/docs/article/getting-start-tdd/python/11-immutable-data-and-pipeline.md +116 -0
  299. package/lib/assets/docs/article/getting-start-tdd/python/12-error-handling-and-type-safety.md +126 -0
  300. package/lib/assets/docs/article/getting-start-tdd/python/index.md +55 -0
  301. package/lib/assets/docs/article/getting-start-tdd/ruby/01-todo-list-and-first-test.md +231 -0
  302. package/lib/assets/docs/article/getting-start-tdd/ruby/02-fake-it-and-triangulation.md +238 -0
  303. package/lib/assets/docs/article/getting-start-tdd/ruby/03-obvious-implementation-and-refactoring.md +228 -0
  304. package/lib/assets/docs/article/getting-start-tdd/ruby/04-version-control-and-conventional-commits.md +112 -0
  305. package/lib/assets/docs/article/getting-start-tdd/ruby/05-package-management-and-static-analysis.md +287 -0
  306. package/lib/assets/docs/article/getting-start-tdd/ruby/06-task-runner-and-ci-cd.md +248 -0
  307. package/lib/assets/docs/article/getting-start-tdd/ruby/07-encapsulation-and-polymorphism.md +279 -0
  308. package/lib/assets/docs/article/getting-start-tdd/ruby/08-design-patterns.md +329 -0
  309. package/lib/assets/docs/article/getting-start-tdd/ruby/09-solid-principles-and-module-design.md +196 -0
  310. package/lib/assets/docs/article/getting-start-tdd/ruby/10-higher-order-functions-and-composition.md +175 -0
  311. package/lib/assets/docs/article/getting-start-tdd/ruby/11-immutable-data-and-pipeline.md +233 -0
  312. package/lib/assets/docs/article/getting-start-tdd/ruby/12-error-handling-and-type-safety.md +398 -0
  313. package/lib/assets/docs/article/getting-start-tdd/ruby/index.md +83 -0
  314. package/lib/assets/docs/article/getting-start-tdd/rust/01-todo-list-and-first-test.md +211 -0
  315. package/lib/assets/docs/article/getting-start-tdd/rust/02-fake-it-and-triangulation.md +264 -0
  316. package/lib/assets/docs/article/getting-start-tdd/rust/03-obvious-implementation-and-refactoring.md +233 -0
  317. package/lib/assets/docs/article/getting-start-tdd/rust/04-version-control-and-conventional-commits.md +92 -0
  318. package/lib/assets/docs/article/getting-start-tdd/rust/05-package-management-and-static-analysis.md +212 -0
  319. package/lib/assets/docs/article/getting-start-tdd/rust/06-task-runner-and-ci-cd.md +164 -0
  320. package/lib/assets/docs/article/getting-start-tdd/rust/07-encapsulation-and-polymorphism.md +142 -0
  321. package/lib/assets/docs/article/getting-start-tdd/rust/08-design-patterns.md +145 -0
  322. package/lib/assets/docs/article/getting-start-tdd/rust/09-solid-principles-and-module-design.md +110 -0
  323. package/lib/assets/docs/article/getting-start-tdd/rust/10-higher-order-functions-and-composition.md +94 -0
  324. package/lib/assets/docs/article/getting-start-tdd/rust/11-immutable-data-and-pipeline.md +105 -0
  325. package/lib/assets/docs/article/getting-start-tdd/rust/12-error-handling-and-type-safety.md +112 -0
  326. package/lib/assets/docs/article/getting-start-tdd/rust/index.md +83 -0
  327. package/lib/assets/docs/article/getting-start-tdd/scala/01-todo-list-and-first-test.md +111 -0
  328. package/lib/assets/docs/article/getting-start-tdd/scala/02-fake-it-and-triangulation.md +107 -0
  329. package/lib/assets/docs/article/getting-start-tdd/scala/03-obvious-implementation-and-refactoring.md +99 -0
  330. package/lib/assets/docs/article/getting-start-tdd/scala/04-version-control-and-conventional-commits.md +123 -0
  331. package/lib/assets/docs/article/getting-start-tdd/scala/05-package-management-and-static-analysis.md +196 -0
  332. package/lib/assets/docs/article/getting-start-tdd/scala/06-task-runner-and-ci-cd.md +186 -0
  333. package/lib/assets/docs/article/getting-start-tdd/scala/07-case-classes-and-traits.md +139 -0
  334. package/lib/assets/docs/article/getting-start-tdd/scala/08-pattern-matching-and-sealed-traits.md +106 -0
  335. package/lib/assets/docs/article/getting-start-tdd/scala/09-packages-and-module-design.md +75 -0
  336. package/lib/assets/docs/article/getting-start-tdd/scala/10-higher-order-functions-and-composition.md +104 -0
  337. package/lib/assets/docs/article/getting-start-tdd/scala/11-collections-and-lazy-evaluation.md +94 -0
  338. package/lib/assets/docs/article/getting-start-tdd/scala/12-error-handling-and-type-safety.md +92 -0
  339. package/lib/assets/docs/article/getting-start-tdd/scala/index.md +65 -0
  340. package/lib/assets/docs/article/grokking-concurrency/all/index.md +404 -0
  341. package/lib/assets/docs/article/grokking-concurrency/all/part-1-ch02-sequential.md +554 -0
  342. package/lib/assets/docs/article/grokking-concurrency/all/part-2-ch04-05-threads.md +469 -0
  343. package/lib/assets/docs/article/grokking-concurrency/all/part-3-ch06-multitasking.md +520 -0
  344. package/lib/assets/docs/article/grokking-concurrency/all/part-4-ch07-parallel-patterns.md +420 -0
  345. package/lib/assets/docs/article/grokking-concurrency/all/part-5-ch08-09-synchronization.md +510 -0
  346. package/lib/assets/docs/article/grokking-concurrency/all/part-6-ch10-11-nonblocking-io.md +435 -0
  347. package/lib/assets/docs/article/grokking-concurrency/all/part-7-ch12-async.md +465 -0
  348. package/lib/assets/docs/article/grokking-concurrency/all/part-8-ch13-mapreduce.md +377 -0
  349. package/lib/assets/docs/article/grokking-concurrency/clojure/index.md +116 -0
  350. package/lib/assets/docs/article/grokking-concurrency/clojure/part-1.md +108 -0
  351. package/lib/assets/docs/article/grokking-concurrency/clojure/part-2.md +101 -0
  352. package/lib/assets/docs/article/grokking-concurrency/clojure/part-3.md +122 -0
  353. package/lib/assets/docs/article/grokking-concurrency/clojure/part-4.md +123 -0
  354. package/lib/assets/docs/article/grokking-concurrency/clojure/part-5.md +118 -0
  355. package/lib/assets/docs/article/grokking-concurrency/clojure/part-6.md +89 -0
  356. package/lib/assets/docs/article/grokking-concurrency/clojure/part-7.md +100 -0
  357. package/lib/assets/docs/article/grokking-concurrency/clojure/part-8.md +120 -0
  358. package/lib/assets/docs/article/grokking-concurrency/csharp/index.md +101 -0
  359. package/lib/assets/docs/article/grokking-concurrency/csharp/part-1.md +97 -0
  360. package/lib/assets/docs/article/grokking-concurrency/csharp/part-2.md +123 -0
  361. package/lib/assets/docs/article/grokking-concurrency/csharp/part-3.md +101 -0
  362. package/lib/assets/docs/article/grokking-concurrency/csharp/part-4.md +112 -0
  363. package/lib/assets/docs/article/grokking-concurrency/csharp/part-5.md +99 -0
  364. package/lib/assets/docs/article/grokking-concurrency/csharp/part-6.md +61 -0
  365. package/lib/assets/docs/article/grokking-concurrency/csharp/part-7.md +84 -0
  366. package/lib/assets/docs/article/grokking-concurrency/csharp/part-8.md +92 -0
  367. package/lib/assets/docs/article/grokking-concurrency/fsharp/index.md +65 -0
  368. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-1.md +80 -0
  369. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-2.md +103 -0
  370. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-3.md +94 -0
  371. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-4.md +110 -0
  372. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-5.md +104 -0
  373. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-6.md +93 -0
  374. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-7.md +121 -0
  375. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-8.md +107 -0
  376. package/lib/assets/docs/article/grokking-concurrency/haskell/index.md +248 -0
  377. package/lib/assets/docs/article/grokking-concurrency/haskell/part-1.md +96 -0
  378. package/lib/assets/docs/article/grokking-concurrency/haskell/part-2.md +96 -0
  379. package/lib/assets/docs/article/grokking-concurrency/haskell/part-3.md +91 -0
  380. package/lib/assets/docs/article/grokking-concurrency/haskell/part-4.md +106 -0
  381. package/lib/assets/docs/article/grokking-concurrency/haskell/part-5.md +99 -0
  382. package/lib/assets/docs/article/grokking-concurrency/haskell/part-6.md +95 -0
  383. package/lib/assets/docs/article/grokking-concurrency/haskell/part-7.md +111 -0
  384. package/lib/assets/docs/article/grokking-concurrency/haskell/part-8.md +118 -0
  385. package/lib/assets/docs/article/grokking-concurrency/index.md +66 -0
  386. package/lib/assets/docs/article/grokking-concurrency/java/index.md +102 -0
  387. package/lib/assets/docs/article/grokking-concurrency/java/part-1.md +308 -0
  388. package/lib/assets/docs/article/grokking-concurrency/java/part-2.md +334 -0
  389. package/lib/assets/docs/article/grokking-concurrency/java/part-3.md +221 -0
  390. package/lib/assets/docs/article/grokking-concurrency/java/part-4.md +213 -0
  391. package/lib/assets/docs/article/grokking-concurrency/java/part-5.md +112 -0
  392. package/lib/assets/docs/article/grokking-concurrency/java/part-6.md +69 -0
  393. package/lib/assets/docs/article/grokking-concurrency/java/part-7.md +101 -0
  394. package/lib/assets/docs/article/grokking-concurrency/java/part-8.md +101 -0
  395. package/lib/assets/docs/article/grokking-concurrency/python/index.md +313 -0
  396. package/lib/assets/docs/article/grokking-concurrency/python/part-1.md +239 -0
  397. package/lib/assets/docs/article/grokking-concurrency/python/part-2.md +418 -0
  398. package/lib/assets/docs/article/grokking-concurrency/python/part-3.md +227 -0
  399. package/lib/assets/docs/article/grokking-concurrency/python/part-4.md +299 -0
  400. package/lib/assets/docs/article/grokking-concurrency/python/part-5.md +315 -0
  401. package/lib/assets/docs/article/grokking-concurrency/python/part-6.md +297 -0
  402. package/lib/assets/docs/article/grokking-concurrency/python/part-7.md +314 -0
  403. package/lib/assets/docs/article/grokking-concurrency/python/part-8.md +360 -0
  404. package/lib/assets/docs/article/grokking-concurrency/rust/index.md +270 -0
  405. package/lib/assets/docs/article/grokking-concurrency/rust/part-1.md +108 -0
  406. package/lib/assets/docs/article/grokking-concurrency/rust/part-2.md +120 -0
  407. package/lib/assets/docs/article/grokking-concurrency/rust/part-3.md +126 -0
  408. package/lib/assets/docs/article/grokking-concurrency/rust/part-4.md +175 -0
  409. package/lib/assets/docs/article/grokking-concurrency/rust/part-5.md +158 -0
  410. package/lib/assets/docs/article/grokking-concurrency/rust/part-6.md +94 -0
  411. package/lib/assets/docs/article/grokking-concurrency/rust/part-7.md +133 -0
  412. package/lib/assets/docs/article/grokking-concurrency/rust/part-8.md +155 -0
  413. package/lib/assets/docs/article/grokking-concurrency/scala/index.md +69 -0
  414. package/lib/assets/docs/article/grokking-concurrency/scala/part-1.md +78 -0
  415. package/lib/assets/docs/article/grokking-concurrency/scala/part-2.md +112 -0
  416. package/lib/assets/docs/article/grokking-concurrency/scala/part-3.md +93 -0
  417. package/lib/assets/docs/article/grokking-concurrency/scala/part-4.md +110 -0
  418. package/lib/assets/docs/article/grokking-concurrency/scala/part-5.md +119 -0
  419. package/lib/assets/docs/article/grokking-concurrency/scala/part-6.md +83 -0
  420. package/lib/assets/docs/article/grokking-concurrency/scala/part-7.md +131 -0
  421. package/lib/assets/docs/article/grokking-concurrency/scala/part-8.md +129 -0
  422. package/lib/assets/docs/article/grokkingfp/all/index.md +368 -0
  423. package/lib/assets/docs/article/grokkingfp/all/part-1-ch01-fp-introduction.md +530 -0
  424. package/lib/assets/docs/article/grokkingfp/all/part-1-ch02-pure-functions.md +923 -0
  425. package/lib/assets/docs/article/grokkingfp/all/part-2-ch03-immutable-data.md +1122 -0
  426. package/lib/assets/docs/article/grokkingfp/all/part-2-ch04-higher-order-functions.md +1104 -0
  427. package/lib/assets/docs/article/grokkingfp/all/part-2-ch05-flatmap.md +1026 -0
  428. package/lib/assets/docs/article/grokkingfp/all/part-3-ch06-option.md +777 -0
  429. package/lib/assets/docs/article/grokkingfp/all/part-3-ch07-either-adt.md +871 -0
  430. package/lib/assets/docs/article/grokkingfp/all/part-4-ch08-io-monad.md +972 -0
  431. package/lib/assets/docs/article/grokkingfp/all/part-4-ch09-streams.md +926 -0
  432. package/lib/assets/docs/article/grokkingfp/all/part-5-ch10-concurrency.md +870 -0
  433. package/lib/assets/docs/article/grokkingfp/all/part-6-ch11-application.md +715 -0
  434. package/lib/assets/docs/article/grokkingfp/all/part-6-ch12-testing.md +626 -0
  435. package/lib/assets/docs/article/grokkingfp/all/writing-plan.md +696 -0
  436. package/lib/assets/docs/article/grokkingfp/clojure/index.md +276 -0
  437. package/lib/assets/docs/article/grokkingfp/clojure/part-1.md +667 -0
  438. package/lib/assets/docs/article/grokkingfp/clojure/part-2.md +643 -0
  439. package/lib/assets/docs/article/grokkingfp/clojure/part-3.md +620 -0
  440. package/lib/assets/docs/article/grokkingfp/clojure/part-4.md +697 -0
  441. package/lib/assets/docs/article/grokkingfp/clojure/part-5.md +751 -0
  442. package/lib/assets/docs/article/grokkingfp/clojure/part-6.md +721 -0
  443. package/lib/assets/docs/article/grokkingfp/csharp/index.md +246 -0
  444. package/lib/assets/docs/article/grokkingfp/csharp/part-1.md +811 -0
  445. package/lib/assets/docs/article/grokkingfp/csharp/part-2.md +971 -0
  446. package/lib/assets/docs/article/grokkingfp/csharp/part-3.md +981 -0
  447. package/lib/assets/docs/article/grokkingfp/csharp/part-4.md +949 -0
  448. package/lib/assets/docs/article/grokkingfp/csharp/part-5.md +947 -0
  449. package/lib/assets/docs/article/grokkingfp/csharp/part-6.md +739 -0
  450. package/lib/assets/docs/article/grokkingfp/elixir/index.md +203 -0
  451. package/lib/assets/docs/article/grokkingfp/elixir/part-1.md +710 -0
  452. package/lib/assets/docs/article/grokkingfp/elixir/part-2.md +838 -0
  453. package/lib/assets/docs/article/grokkingfp/elixir/part-3.md +985 -0
  454. package/lib/assets/docs/article/grokkingfp/elixir/part-4.md +974 -0
  455. package/lib/assets/docs/article/grokkingfp/elixir/part-5.md +1284 -0
  456. package/lib/assets/docs/article/grokkingfp/elixir/part-6.md +1047 -0
  457. package/lib/assets/docs/article/grokkingfp/fsharp/index.md +210 -0
  458. package/lib/assets/docs/article/grokkingfp/fsharp/part-1.md +714 -0
  459. package/lib/assets/docs/article/grokkingfp/fsharp/part-2.md +961 -0
  460. package/lib/assets/docs/article/grokkingfp/fsharp/part-3.md +972 -0
  461. package/lib/assets/docs/article/grokkingfp/fsharp/part-4.md +832 -0
  462. package/lib/assets/docs/article/grokkingfp/fsharp/part-5.md +911 -0
  463. package/lib/assets/docs/article/grokkingfp/fsharp/part-6.md +920 -0
  464. package/lib/assets/docs/article/grokkingfp/haskell/index.md +234 -0
  465. package/lib/assets/docs/article/grokkingfp/haskell/part-1.md +591 -0
  466. package/lib/assets/docs/article/grokkingfp/haskell/part-2.md +866 -0
  467. package/lib/assets/docs/article/grokkingfp/haskell/part-3.md +915 -0
  468. package/lib/assets/docs/article/grokkingfp/haskell/part-4.md +876 -0
  469. package/lib/assets/docs/article/grokkingfp/haskell/part-5.md +845 -0
  470. package/lib/assets/docs/article/grokkingfp/haskell/part-6.md +842 -0
  471. package/lib/assets/docs/article/grokkingfp/index.md +143 -0
  472. package/lib/assets/docs/article/grokkingfp/java/index.md +211 -0
  473. package/lib/assets/docs/article/grokkingfp/java/part-1.md +646 -0
  474. package/lib/assets/docs/article/grokkingfp/java/part-2.md +667 -0
  475. package/lib/assets/docs/article/grokkingfp/java/part-3.md +672 -0
  476. package/lib/assets/docs/article/grokkingfp/java/part-4.md +771 -0
  477. package/lib/assets/docs/article/grokkingfp/java/part-5.md +959 -0
  478. package/lib/assets/docs/article/grokkingfp/java/part-6.md +1324 -0
  479. package/lib/assets/docs/article/grokkingfp/python/index.md +258 -0
  480. package/lib/assets/docs/article/grokkingfp/python/part-1.md +437 -0
  481. package/lib/assets/docs/article/grokkingfp/python/part-2.md +958 -0
  482. package/lib/assets/docs/article/grokkingfp/python/part-3.md +1004 -0
  483. package/lib/assets/docs/article/grokkingfp/python/part-4.md +765 -0
  484. package/lib/assets/docs/article/grokkingfp/python/part-5.md +747 -0
  485. package/lib/assets/docs/article/grokkingfp/python/part-6.md +861 -0
  486. package/lib/assets/docs/article/grokkingfp/ruby/index.md +330 -0
  487. package/lib/assets/docs/article/grokkingfp/ruby/part-1.md +753 -0
  488. package/lib/assets/docs/article/grokkingfp/ruby/part-2.md +938 -0
  489. package/lib/assets/docs/article/grokkingfp/ruby/part-3.md +946 -0
  490. package/lib/assets/docs/article/grokkingfp/ruby/part-4.md +921 -0
  491. package/lib/assets/docs/article/grokkingfp/ruby/part-5.md +908 -0
  492. package/lib/assets/docs/article/grokkingfp/ruby/part-6.md +1410 -0
  493. package/lib/assets/docs/article/grokkingfp/rust/index.md +242 -0
  494. package/lib/assets/docs/article/grokkingfp/rust/part-1.md +634 -0
  495. package/lib/assets/docs/article/grokkingfp/rust/part-2.md +1060 -0
  496. package/lib/assets/docs/article/grokkingfp/rust/part-3.md +994 -0
  497. package/lib/assets/docs/article/grokkingfp/rust/part-4.md +571 -0
  498. package/lib/assets/docs/article/grokkingfp/rust/part-5.md +705 -0
  499. package/lib/assets/docs/article/grokkingfp/rust/part-6.md +508 -0
  500. package/lib/assets/docs/article/grokkingfp/scala/index.md +171 -0
  501. package/lib/assets/docs/article/grokkingfp/scala/part-1.md +541 -0
  502. package/lib/assets/docs/article/grokkingfp/scala/part-2.md +946 -0
  503. package/lib/assets/docs/article/grokkingfp/scala/part-3.md +917 -0
  504. package/lib/assets/docs/article/grokkingfp/scala/part-4.md +742 -0
  505. package/lib/assets/docs/article/grokkingfp/scala/part-5.md +722 -0
  506. package/lib/assets/docs/article/grokkingfp/scala/part-6.md +865 -0
  507. package/lib/assets/docs/article/grokkingfp/typescript/index.md +273 -0
  508. package/lib/assets/docs/article/grokkingfp/typescript/part-1.md +559 -0
  509. package/lib/assets/docs/article/grokkingfp/typescript/part-2.md +1129 -0
  510. package/lib/assets/docs/article/grokkingfp/typescript/part-3.md +842 -0
  511. package/lib/assets/docs/article/grokkingfp/typescript/part-4.md +1085 -0
  512. package/lib/assets/docs/article/grokkingfp/typescript/part-5.md +717 -0
  513. package/lib/assets/docs/article/grokkingfp/typescript/part-6.md +980 -0
  514. package/lib/assets/docs/article/index.md +36 -0
  515. package/lib/assets/docs/design/index.md +39 -27
  516. package/lib/assets/docs/development/index.md +11 -1
  517. package/lib/assets/docs/index.md +33 -103
  518. package/lib/assets/docs/operation/index.md +16 -6
  519. package/lib/assets/docs/reference/index.md +5 -4
  520. package/lib/assets/docs/requirements/index.md +13 -6
  521. package/lib/assets/docs/review/index.md +5 -0
  522. package/lib/assets/docs/strategy/index.md +15 -0
  523. package/lib/assets/docs/template/index.md +9 -5
  524. package/lib/assets/mkdocs.yml +33 -19
  525. package/package.json +1 -1
  526. package/lib/assets/docs/analysis/index.md +0 -8
  527. /package/lib/assets/docs/{analysis → strategy}/slide/.gitkeep +0 -0
@@ -0,0 +1,268 @@
1
+ # Chapter 05: プロパティベーステスト
2
+
3
+ Elixir における StreamData を使ったプロパティベーステストについて学びます。
4
+
5
+ ## 概要
6
+
7
+ 従来の例示ベーステストでは、特定の入力に対する期待される出力を手動で指定します。
8
+ プロパティベーステストでは、**すべての入力に対して成り立つべき性質(プロパティ)**を
9
+ 定義し、ランダムに生成された多数の入力でその性質を検証します。
10
+
11
+ ## 主なトピック
12
+
13
+ 1. **ジェネレータの基本**
14
+ 2. **プロパティの定義**
15
+ 3. **収縮(シュリンキング)**
16
+ 4. **カスタムジェネレータ**
17
+ 5. **ドメイン固有のプロパティ**
18
+
19
+ ## StreamData ライブラリ
20
+
21
+ Elixir でプロパティベーステストを行うには、`stream_data` ライブラリを使用します。
22
+
23
+ ```elixir
24
+ # mix.exs
25
+ defp deps do
26
+ [
27
+ {:stream_data, "~> 1.0", only: :test}
28
+ ]
29
+ end
30
+ ```
31
+
32
+ ## プロパティの種類
33
+
34
+ ### 冪等性(Idempotency)
35
+
36
+ 同じ操作を複数回適用しても結果が変わらない性質。
37
+
38
+ ```elixir
39
+ property "sort は冪等" do
40
+ check all list <- list_of(integer()) do
41
+ assert Enum.sort(Enum.sort(list)) == Enum.sort(list)
42
+ end
43
+ end
44
+ ```
45
+
46
+ ### ラウンドトリップ(Round-trip)
47
+
48
+ エンコード・デコードで元の値に戻る性質。
49
+
50
+ ```elixir
51
+ property "encode/decode はラウンドトリップ" do
52
+ check all n <- integer() do
53
+ encoded = encode(n)
54
+ {:ok, decoded} = decode(encoded)
55
+ assert decoded == n
56
+ end
57
+ end
58
+ ```
59
+
60
+ ### 不変条件(Invariant)
61
+
62
+ 操作の前後で保存される性質。
63
+
64
+ ```elixir
65
+ property "reverse は長さを保存する" do
66
+ check all list <- list_of(term()) do
67
+ assert length(Enum.reverse(list)) == length(list)
68
+ end
69
+ end
70
+ ```
71
+
72
+ ### 反転(Inverse)
73
+
74
+ ある操作とその逆操作。
75
+
76
+ ```elixir
77
+ property "reverse の reverse は元に戻る" do
78
+ check all list <- list_of(integer()) do
79
+ assert Enum.reverse(Enum.reverse(list)) == list
80
+ end
81
+ end
82
+ ```
83
+
84
+ ## 基本的なジェネレータ
85
+
86
+ ```elixir
87
+ use ExUnitProperties
88
+
89
+ # 整数
90
+ integer() # 任意の整数
91
+ positive_integer() # 正の整数
92
+ non_negative_integer() # 0 以上の整数
93
+ integer(1..100) # 範囲付き整数
94
+
95
+ # 文字列
96
+ string(:alphanumeric)
97
+ string(:printable, min_length: 1, max_length: 10)
98
+
99
+ # リスト
100
+ list_of(integer())
101
+ list_of(integer(), min_length: 1, max_length: 5)
102
+
103
+ # マップ
104
+ map_of(atom(:alphanumeric), integer())
105
+
106
+ # その他
107
+ boolean()
108
+ binary()
109
+ term()
110
+ member_of(["a", "b", "c"])
111
+ ```
112
+
113
+ ## カスタムジェネレータ
114
+
115
+ ```elixir
116
+ # メールアドレスのカスタムジェネレータ
117
+ defp email_generator do
118
+ gen all local <- string(:alphanumeric, min_length: 1, max_length: 10),
119
+ domain <- string(:alphanumeric, min_length: 1, max_length: 10),
120
+ tld <- member_of(["com", "org", "net", "io"]) do
121
+ "#{local}@#{domain}.#{tld}"
122
+ end
123
+ end
124
+
125
+ property "生成されたメールは有効" do
126
+ check all email <- email_generator() do
127
+ assert String.contains?(email, "@")
128
+ assert String.contains?(email, ".")
129
+ end
130
+ end
131
+ ```
132
+
133
+ ## 実装例
134
+
135
+ ### 数学関数のプロパティ
136
+
137
+ ```elixir
138
+ defmodule Chapter05 do
139
+ @doc """
140
+ 絶対値を返す。
141
+
142
+ ## プロパティ
143
+ - 結果は常に非負
144
+ - 冪等性: abs(abs(x)) == abs(x)
145
+ - 偶関数: abs(-x) == abs(x)
146
+ """
147
+ def absolute(n) when n < 0, do: -n
148
+ def absolute(n), do: n
149
+ end
150
+ ```
151
+
152
+ ```elixir
153
+ describe "absolute/1 のプロパティ" do
154
+ property "結果は常に非負" do
155
+ check all n <- integer() do
156
+ assert Chapter05.absolute(n) >= 0
157
+ end
158
+ end
159
+
160
+ property "冪等性" do
161
+ check all n <- integer() do
162
+ assert Chapter05.absolute(Chapter05.absolute(n)) == Chapter05.absolute(n)
163
+ end
164
+ end
165
+
166
+ property "偶関数" do
167
+ check all n <- integer() do
168
+ assert Chapter05.absolute(-n) == Chapter05.absolute(n)
169
+ end
170
+ end
171
+ end
172
+ ```
173
+
174
+ ### ドメインモデルのプロパティ
175
+
176
+ ```elixir
177
+ defmodule Money do
178
+ defstruct [:amount, :currency]
179
+
180
+ def new(amount, currency), do: %__MODULE__{amount: amount, currency: currency}
181
+
182
+ def add(%{currency: c} = m1, %{currency: c} = m2) do
183
+ {:ok, new(m1.amount + m2.amount, c)}
184
+ end
185
+ def add(_, _), do: {:error, "Currency mismatch"}
186
+
187
+ def zero(currency), do: new(0, currency)
188
+ end
189
+ ```
190
+
191
+ ```elixir
192
+ describe "Money のモノイド則" do
193
+ defp money_generator(currency) do
194
+ gen all amount <- integer() do
195
+ Money.new(amount, currency)
196
+ end
197
+ end
198
+
199
+ property "結合律" do
200
+ check all a <- money_generator("JPY"),
201
+ b <- money_generator("JPY"),
202
+ c <- money_generator("JPY") do
203
+ {:ok, ab} = Money.add(a, b)
204
+ {:ok, ab_c} = Money.add(ab, c)
205
+ {:ok, bc} = Money.add(b, c)
206
+ {:ok, a_bc} = Money.add(a, bc)
207
+ assert ab_c == a_bc
208
+ end
209
+ end
210
+
211
+ property "単位元" do
212
+ check all m <- money_generator("JPY") do
213
+ zero = Money.zero("JPY")
214
+ {:ok, result} = Money.add(m, zero)
215
+ assert result == m
216
+ end
217
+ end
218
+
219
+ property "可換律" do
220
+ check all a <- money_generator("JPY"),
221
+ b <- money_generator("JPY") do
222
+ {:ok, ab} = Money.add(a, b)
223
+ {:ok, ba} = Money.add(b, a)
224
+ assert ab == ba
225
+ end
226
+ end
227
+ end
228
+ ```
229
+
230
+ ## 収縮(シュリンキング)
231
+
232
+ テストが失敗した場合、StreamData は失敗を引き起こす最小の入力を見つけようとします。
233
+
234
+ ```elixir
235
+ # 故意に失敗するテスト(デモ用)
236
+ property "リストの合計は100未満" do
237
+ check all list <- list_of(positive_integer(), min_length: 1) do
238
+ assert Enum.sum(list) < 100
239
+ end
240
+ end
241
+
242
+ # 出力例:
243
+ # Failed with generated values (after 5 successful runs):
244
+ # * list <- [100]
245
+ #
246
+ # 収縮により、最小の反例 [100] が見つかる
247
+ ```
248
+
249
+ ## テストのベストプラクティス
250
+
251
+ 1. **明確なプロパティを定義する** - 何を検証するか明確に
252
+ 2. **ジェネレータを適切に制約する** - 無効な入力を生成しない
253
+ 3. **カスタムジェネレータを活用する** - ドメイン固有の値を生成
254
+ 4. **収縮を理解する** - 最小の反例を活用
255
+ 5. **例示テストと併用する** - 両方のアプローチを使う
256
+
257
+ ## まとめ
258
+
259
+ - **プロパティベーステスト**で多くのケースを自動検証
260
+ - **StreamData**で Elixir のプロパティテストを実現
261
+ - **カスタムジェネレータ**でドメイン固有のテストデータを生成
262
+ - **収縮**で最小の失敗ケースを特定
263
+ - **例示テストと併用**で堅牢なテストスイートを構築
264
+
265
+ ## 関連リソース
266
+
267
+ - [StreamData ドキュメント](https://hexdocs.pm/stream_data/)
268
+ - [Property-based testing with PropEr, Erlang, and Elixir](https://pragprog.com/titles/fhproper/property-based-testing-with-proper-erlang-and-elixir/)
@@ -0,0 +1,294 @@
1
+ # Chapter 06: TDD と関数型プログラミング
2
+
3
+ Elixir におけるテスト駆動開発(TDD)と関数型プログラミングの融合について学びます。
4
+
5
+ ## 概要
6
+
7
+ テスト駆動開発(TDD)は、テストを先に書いてから実装するソフトウェア開発手法です。
8
+ 関数型プログラミングの純粋関数と不変データは、TDD と非常に相性が良いです。
9
+
10
+ ## 主なトピック
11
+
12
+ 1. **TDD の基本サイクル(Red-Green-Refactor)**
13
+ 2. **テスタブルな設計**
14
+ 3. **純粋関数とテスト容易性**
15
+ 4. **モックとスタブの代替手法**
16
+ 5. **Outside-In TDD**
17
+ 6. **Parameterized Tests**
18
+
19
+ ## TDD の基本サイクル
20
+
21
+ ### Red-Green-Refactor
22
+
23
+ 1. **Red**: 失敗するテストを書く
24
+ 2. **Green**: テストを通す最小限の実装
25
+ 3. **Refactor**: コードを整理(テストは通ったまま)
26
+
27
+ ### FizzBuzz の例
28
+
29
+ ```elixir
30
+ # Step 1: Red - 失敗するテストを書く
31
+ test "通常の数値は文字列として返す" do
32
+ assert FizzBuzz.convert(1) == "1"
33
+ end
34
+
35
+ # Step 2: Green - 最小限の実装
36
+ def convert(n), do: Integer.to_string(n)
37
+
38
+ # Step 3: 次のテストを追加
39
+ test "3の倍数は 'Fizz' を返す" do
40
+ assert FizzBuzz.convert(3) == "Fizz"
41
+ end
42
+
43
+ # 実装を拡張
44
+ def convert(n) when rem(n, 3) == 0, do: "Fizz"
45
+ def convert(n), do: Integer.to_string(n)
46
+
47
+ # 以下同様に 5の倍数、15の倍数を追加...
48
+ ```
49
+
50
+ ## テスタブルな設計
51
+
52
+ ### 依存性の注入
53
+
54
+ 外部依存を関数として注入することで、テスト時にスタブを使用できます。
55
+
56
+ ```elixir
57
+ defmodule PricingService do
58
+ @doc """
59
+ 割引率を取得する関数を注入することで、
60
+ 外部サービスをモック可能にする。
61
+ """
62
+ def calculate_price(product_id, base_price, discount_fetcher) do
63
+ discount = discount_fetcher.(product_id)
64
+ base_price * (1.0 - discount)
65
+ end
66
+ end
67
+
68
+ # テストでの使用
69
+ test "割引率を適用して価格を計算する" do
70
+ # スタブ:常に10%割引を返す
71
+ discount_fetcher = fn _product_id -> 0.10 end
72
+
73
+ assert PricingService.calculate_price("PROD001", 1000, discount_fetcher) == 900.0
74
+ end
75
+
76
+ # 本番での使用
77
+ def production_discount_fetcher(product_id) do
78
+ DiscountAPI.fetch(product_id)
79
+ end
80
+
81
+ PricingService.calculate_price("PROD001", 1000, &production_discount_fetcher/1)
82
+ ```
83
+
84
+ ## 純粋関数によるビジネスロジック
85
+
86
+ ビジネスロジックを純粋関数として実装することで、テストが容易になります。
87
+
88
+ ```elixir
89
+ defmodule OrderProcessor do
90
+ @doc "注文の小計を計算する(純粋関数)"
91
+ def calculate_subtotal(items) do
92
+ items
93
+ |> Enum.map(fn {_name, qty, price} -> qty * price end)
94
+ |> Enum.sum()
95
+ end
96
+
97
+ @doc "顧客タイプに応じた割引率を返す(純粋関数)"
98
+ def discount_rate(:regular), do: 0.0
99
+ def discount_rate(:premium), do: 0.05
100
+ def discount_rate(:vip), do: 0.10
101
+
102
+ @doc "税額を計算する(純粋関数)"
103
+ def calculate_tax(amount, tax_rate), do: amount * tax_rate
104
+
105
+ @doc "注文を処理する(純粋関数の組み合わせ)"
106
+ def process_order(%{items: items, customer_type: customer_type}, tax_rate) do
107
+ subtotal = calculate_subtotal(items)
108
+ discount_amount = subtotal * discount_rate(customer_type)
109
+ discounted = subtotal - discount_amount
110
+ tax_amount = calculate_tax(discounted, tax_rate)
111
+ total = discounted + tax_amount
112
+
113
+ %{
114
+ subtotal: subtotal,
115
+ discount: discount_amount,
116
+ tax: tax_amount,
117
+ total: total
118
+ }
119
+ end
120
+ end
121
+ ```
122
+
123
+ テストは各純粋関数を独立してテストできます。
124
+
125
+ ```elixir
126
+ describe "OrderProcessor" do
127
+ test "calculate_subtotal" do
128
+ items = [{"Item1", 2, 100.0}, {"Item2", 3, 50.0}]
129
+ assert OrderProcessor.calculate_subtotal(items) == 350.0
130
+ end
131
+
132
+ test "discount_rate" do
133
+ assert OrderProcessor.discount_rate(:regular) == 0.0
134
+ assert OrderProcessor.discount_rate(:premium) == 0.05
135
+ assert OrderProcessor.discount_rate(:vip) == 0.10
136
+ end
137
+
138
+ test "process_order for VIP customer" do
139
+ order = %{items: [{"Item", 1, 1000.0}], customer_type: :vip}
140
+ result = OrderProcessor.process_order(order, 0.10)
141
+
142
+ assert result.subtotal == 1000.0
143
+ assert result.discount == 100.0
144
+ assert result.tax == 90.0
145
+ assert result.total == 990.0
146
+ end
147
+ end
148
+ ```
149
+
150
+ ## 状態遷移のテスト
151
+
152
+ 状態遷移を純粋関数としてモデル化します。
153
+
154
+ ```elixir
155
+ defmodule OrderState do
156
+ def new(id, items) do
157
+ %{id: id, state: :pending, items: items, history: [:pending]}
158
+ end
159
+
160
+ def confirm(%{state: :pending} = order) do
161
+ {:ok, %{order | state: :confirmed, history: [:confirmed | order.history]}}
162
+ end
163
+ def confirm(_), do: {:error, "Cannot confirm"}
164
+
165
+ def ship(%{state: :confirmed} = order) do
166
+ {:ok, %{order | state: :shipped, history: [:shipped | order.history]}}
167
+ end
168
+ def ship(_), do: {:error, "Cannot ship"}
169
+
170
+ # ... 他の遷移
171
+ end
172
+ ```
173
+
174
+ ```elixir
175
+ describe "OrderState 状態遷移" do
176
+ test "正常な状態遷移" do
177
+ order = OrderState.new("ORD001", [])
178
+
179
+ {:ok, order} = OrderState.confirm(order)
180
+ assert order.state == :confirmed
181
+
182
+ {:ok, order} = OrderState.ship(order)
183
+ assert order.state == :shipped
184
+ end
185
+
186
+ test "不正な状態遷移はエラー" do
187
+ order = OrderState.new("ORD001", [])
188
+ # pending から直接 ship はできない
189
+ assert {:error, _} = OrderState.ship(order)
190
+ end
191
+ end
192
+ ```
193
+
194
+ ## テストデータビルダーパターン
195
+
196
+ テストデータを柔軟に構築するパターンです。
197
+
198
+ ```elixir
199
+ defmodule UserBuilder do
200
+ def build do
201
+ %{
202
+ name: "Test User",
203
+ email: "test@example.com",
204
+ age: 25,
205
+ role: :user,
206
+ active: true
207
+ }
208
+ end
209
+
210
+ def build(overrides) do
211
+ build() |> Map.merge(Map.new(overrides))
212
+ end
213
+
214
+ def admin, do: build(role: :admin)
215
+ def inactive, do: build(active: false)
216
+
217
+ def build_list(count) do
218
+ Enum.map(1..count, fn i ->
219
+ build(name: "User #{i}", email: "user#{i}@example.com")
220
+ end)
221
+ end
222
+ end
223
+ ```
224
+
225
+ ```elixir
226
+ test "管理者のみがアクセス可能" do
227
+ admin = UserBuilder.admin()
228
+ user = UserBuilder.build()
229
+
230
+ assert authorize(admin, :admin_panel) == :ok
231
+ assert authorize(user, :admin_panel) == :error
232
+ end
233
+ ```
234
+
235
+ ## パラメタライズドテスト
236
+
237
+ 同じテストロジックを複数の入力で実行します。
238
+
239
+ ```elixir
240
+ describe "FizzBuzz パラメタライズドテスト" do
241
+ for {input, expected} <- [
242
+ {1, "1"},
243
+ {2, "2"},
244
+ {3, "Fizz"},
245
+ {5, "Buzz"},
246
+ {15, "FizzBuzz"}
247
+ ] do
248
+ test "FizzBuzz.convert(#{input}) == #{expected}" do
249
+ assert FizzBuzz.convert(unquote(input)) == unquote(expected)
250
+ end
251
+ end
252
+ end
253
+ ```
254
+
255
+ ## Result 型を使ったエラーハンドリング
256
+
257
+ ```elixir
258
+ defmodule Calculator do
259
+ def divide(_, b) when b == 0 or b == 0.0 do
260
+ {:error, "Division by zero"}
261
+ end
262
+ def divide(a, b), do: {:ok, a / b}
263
+
264
+ def chain(n), do: {:ok, n}
265
+
266
+ def then_divide({:ok, a}, b), do: divide(a, b)
267
+ def then_divide(error, _), do: error
268
+ end
269
+ ```
270
+
271
+ ```elixir
272
+ test "エラーはチェインを通じて伝播する" do
273
+ result =
274
+ Calculator.chain(10)
275
+ |> Calculator.then_divide(0)
276
+ |> Calculator.then_add(5)
277
+
278
+ assert {:error, "Division by zero"} = result
279
+ end
280
+ ```
281
+
282
+ ## まとめ
283
+
284
+ - **TDD サイクル**(Red-Green-Refactor)で段階的に実装
285
+ - **依存性注入**でテスタブルな設計
286
+ - **純粋関数**でビジネスロジックを表現
287
+ - **状態遷移**を純粋関数としてモデル化
288
+ - **テストデータビルダー**で柔軟なテストデータ作成
289
+ - **パラメタライズドテスト**で多くのケースをカバー
290
+
291
+ ## 関連リソース
292
+
293
+ - [ExUnit ドキュメント](https://hexdocs.pm/ex_unit/)
294
+ - [Test-Driven Development by Example](https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530)
@@ -0,0 +1,164 @@
1
+ # Chapter 07: 副作用と純粋関数
2
+
3
+ Elixir における副作用の管理と純粋関数の分離について学びます。
4
+
5
+ ## 概要
6
+
7
+ 関数型プログラミングでは、副作用(I/O、状態変更、時間、乱数)を純粋なビジネスロジックから分離することが重要です。このチャプターでは、その設計パターンを紹介します。
8
+
9
+ ## 主なトピック
10
+
11
+ 1. **純粋関数と副作用の分離**
12
+ 2. **Functional Core, Imperative Shell**
13
+ 3. **副作用の遅延実行**
14
+ 4. **Reader パターン**
15
+ 5. **依存性注入**
16
+
17
+ ## 純粋関数 vs 副作用
18
+
19
+ ### 純粋関数
20
+
21
+ - 同じ入力に対して常に同じ出力
22
+ - 外部状態を変更しない
23
+
24
+ ```elixir
25
+ # 純粋関数の例
26
+ def add(a, b), do: a + b
27
+ def upcase(s), do: String.upcase(s)
28
+ ```
29
+
30
+ ### 副作用を持つ関数
31
+
32
+ - I/O(コンソール、ファイル、ネットワーク)
33
+ - 状態変更
34
+ - 現在時刻の取得
35
+ - 乱数生成
36
+
37
+ ```elixir
38
+ # 副作用を持つ関数
39
+ def current_time, do: DateTime.utc_now() # 非決定的
40
+ def random_number, do: :rand.uniform() # 非決定的
41
+ def print(msg), do: IO.puts(msg) # I/O
42
+ ```
43
+
44
+ ## Functional Core, Imperative Shell
45
+
46
+ ビジネスロジックを純粋関数として実装し、副作用は境界層で処理します。
47
+
48
+ ```elixir
49
+ # Functional Core(純粋関数)
50
+ defmodule PricingCore do
51
+ def apply_discount(price, %{type: :percentage, value: pct}) do
52
+ price * (1 - pct / 100)
53
+ end
54
+
55
+ def calculate_total(products) do
56
+ products |> Enum.map(& &1.price) |> Enum.sum()
57
+ end
58
+ end
59
+
60
+ # Imperative Shell(副作用を扱う)
61
+ defmodule PricingShell do
62
+ def calculate_order_price(products, discount_fetcher, discount_code, tax_rate) do
63
+ # 副作用:外部から割引情報を取得
64
+ discount = discount_fetcher.(discount_code)
65
+ # 純粋関数でビジネスロジックを実行
66
+ PricingCore.calculate_final_price(products, discount, tax_rate)
67
+ end
68
+ end
69
+ ```
70
+
71
+ ## 副作用の遅延実行(Effect as Data)
72
+
73
+ 副作用をデータとして表現し、実行を遅延させます。
74
+
75
+ ```elixir
76
+ defmodule Effect do
77
+ def console_log(message) do
78
+ {:effect, :console_log, message, fn _ -> :ok end}
79
+ end
80
+
81
+ def get_current_time do
82
+ {:effect, :get_time, nil, fn time -> time end}
83
+ end
84
+
85
+ # 本番用インタープリター
86
+ def run({:effect, :console_log, message, cont}) do
87
+ IO.puts(message)
88
+ cont.(:ok)
89
+ end
90
+
91
+ # テスト用インタープリター
92
+ def run_test({:effect, effect_type, _, cont}, mock_values) do
93
+ cont.(Map.get(mock_values, effect_type))
94
+ end
95
+ end
96
+ ```
97
+
98
+ ## Reader パターン
99
+
100
+ 環境(設定、依存性)を引数として渡す関数をラップします。
101
+
102
+ ```elixir
103
+ defmodule Reader do
104
+ def pure(value), do: fn _env -> value end
105
+ def ask, do: fn env -> env end
106
+ def asks(selector), do: fn env -> selector.(env) end
107
+
108
+ def flat_map(reader, f) do
109
+ fn env -> f.(reader.(env)).(env) end
110
+ end
111
+
112
+ def run(reader, env), do: reader.(env)
113
+ end
114
+
115
+ # 使用例
116
+ def get_db_url do
117
+ Reader.asks(fn config -> config.db_url end)
118
+ end
119
+
120
+ def build_service do
121
+ Reader.flat_map(get_db_url(), fn db_url ->
122
+ Reader.flat_map(get_api_key(), fn api_key ->
123
+ Reader.pure(%{db: db_url, key: api_key, ready: true})
124
+ end)
125
+ end)
126
+ end
127
+ ```
128
+
129
+ ## 時間の抽象化
130
+
131
+ 時間依存をテスト可能にします。
132
+
133
+ ```elixir
134
+ defmodule TimeService do
135
+ def add_timestamp(data, time_provider) do
136
+ Map.put(data, :timestamp, time_provider.())
137
+ end
138
+
139
+ def is_expired?(expiry_date, time_provider) do
140
+ DateTime.compare(time_provider.(), expiry_date) == :gt
141
+ end
142
+ end
143
+
144
+ # テスト
145
+ test "is_expired? は期限切れを判定する" do
146
+ now = ~U[2024-01-15 12:00:00Z]
147
+ provider = fn -> now end
148
+
149
+ assert TimeService.is_expired?(~U[2024-01-10 12:00:00Z], provider) == true
150
+ assert TimeService.is_expired?(~U[2024-01-20 12:00:00Z], provider) == false
151
+ end
152
+ ```
153
+
154
+ ## まとめ
155
+
156
+ - **純粋関数**でビジネスロジックを実装
157
+ - **Functional Core, Imperative Shell**で副作用を分離
158
+ - **依存性注入**でテスト可能な設計
159
+ - **Reader パターン**で環境を引き回す
160
+
161
+ ## 関連リソース
162
+
163
+ - [Boundaries by Gary Bernhardt](https://www.destroyallsoftware.com/talks/boundaries)
164
+ - [Functional Core, Imperative Shell](https://www.youtube.com/watch?v=yTkzNHF6rMs)